// Stadtreinigung Hamburg Abfuhrkalender | |
// von Markus Fritze, loxone@sarnau.com | |
// Version: 30.07.2018 | |
// | |
// Ausgänge: | |
// TQ1: Welche Tonnen werden am nächsten Termin abgeholt | |
// TQ2: Volltext "In xyz Tagen: tonne1, tonne2, ..." | |
// AQ1: In wieviel Tagen wird TQ1 (siehe oben) abgeholt (0 = Heute) | |
// Die folgenden Eingänge geben an in wieviel Tagen die jeweilige Müllsorte | |
// abgeholt wird. Achtung: regelmäßig wird mehr als eine Sorte am Tag abgeholt! | |
// Negative Zahl (-1) heißt: kein Termin gefunden. Dies ist z.B. der Fall bei | |
// Laub (nur im Herbst bis Dezember) und Weihnachtsbäumen (nur im Januar) | |
// AQ2: Restmüll (Schwarze Tonne) | |
// AQ3: Papier (Blaue Tonne) | |
// AQ4: Wertstoff (Gelbe Tonne, Gelber Sack) | |
// AQ5: Bio (Grüne Tonne) | |
// AQ6: Laub (Laubsäcke) | |
// AQ7: Weihnachtsbäume (ja, wirklich) | |
// Der Straßenname, wir müssen die Leerzeichen durch %20 ersetzen. | |
// Umlaute sollten als "ae" "oe", etc. geschrieben werden. | |
char *streetName = "STRASSENNAME"; | |
// Die Hausnummer an. Ein '-' muß als %2D geschrieben werden | |
char *streetNumber = "HAUSNUMMER"; | |
// Nachdem das Program einmal durchlaufen ist, kann man im Log die asId und hnId finden. | |
// Man kann sie dann hier eintragen. Das erspart beim Reboot einen Request und die Nummern | |
// sind für eine gegebene Adresse unveränderlich. | |
int asId = 0; | |
int hnId = 0; | |
char *HTTPPtr; | |
// Zuerst muß die AddressID und die HausnummernID ermittelt werden. Dies braucht nur | |
// beim Reboot geschehen, da sie für eine gegebene Adresse unveränderlich sind. | |
if(asId == 0 || hnId == 0) { | |
char buffer[200]; | |
sprintf(buffer, "/privatkunden/abfuhrkalender/index.html?strasse=%s&hausnummer=%s&bestaetigung=true&mode=search", streetName, streetNumber); | |
//setlogtext(buffer); | |
HTTPPtr = httpget("www.stadtreinigung.hamburg", buffer); | |
//setlogtext(HTTPPtr); | |
char *sp = strstrskip(HTTPPtr, "\"asId\" value=\""); | |
if(sp != NULL) { | |
asId = batoi(sp); | |
sprintf(buffer, "asId = %d", asId); | |
setlogtext(buffer); | |
} else { | |
errorprintf("asId not found"); | |
} | |
sp = strstrskip(HTTPPtr, "\"hnId\" value=\""); | |
if(sp != NULL) { | |
hnId = batoi(sp); | |
sprintf(buffer, "hnId = %d", hnId); | |
setlogtext(buffer); | |
} else { | |
errorprintf("hnId not found"); | |
} | |
free(HTTPPtr); | |
// Falls die IDs nicht ermittelt werden konnten, müssen wir hier aufgeben. | |
if(asId == 0 || hnId == 0) { | |
errorprintf("asId/hnId not found"); | |
exit(); | |
} | |
} | |
// Konvertiere TT.MM.JJJJ String in ein Datum und dann in eine Tagesdifferenz zu Heute. | |
// Dies erlaubt es uns zu sagen: in xxx Tagen. | |
void calcDate(char *date, int *var) | |
{ | |
int day = batoi(date); | |
int month = batoi(date+3); | |
int year = batoi(date+6); | |
int currentTime = getcurrenttime(); | |
int deltaDays = (gettimeval(year, month, day, 0, 0, 0, 0) - gettimeval(getyear(currentTime, 1), getmonth(currentTime, 1), getday(currentTime, 1), 0, 0, 0, 1)) / (60*60*24); | |
// nach 16 Uhr ist es zu spät für die Mülltonne, d.h. wir haben den heutigen Termin verpaßt. | |
if(deltaDays == 0 && gethour(currentTime, 1) >= 16) | |
return; | |
if(*var < 0 || *var > deltaDays) | |
*var = deltaDays; | |
} | |
// Delta-Tage in einen netten String wandeln. Ich vermeide "Übermorgen" um Umlaute | |
// nicht zu nutzen. | |
void calcDateStr(int deltaDays, char *whenBuffer) | |
{ | |
if(deltaDays == 0) { | |
strcpy(whenBuffer, "Heute"); | |
} else if(deltaDays == 1) { | |
strcpy(whenBuffer, "Morgen"); | |
} else if(deltaDays > 1) { | |
sprintf(whenBuffer, "In %d Tagen", deltaDays); | |
} else { // negativ, d.h. keinen Abfuhrtermin gefunden | |
whenBuffer[0] = 0; | |
} | |
} | |
// Hier nun eine Endlosschleife, die alle 3 Stunden einmal durchlaufen wird, d.h. | |
// die Mülltermine werden 8x am Tag neu ermittelt. | |
while(1) { | |
// In Hamburg gibt es 6 verschiedene Abfuhrtermine. Es ist möglich, daß mehr als | |
// eine Tonne an einem Tag abgeholt wird. Eine Überschneidung von Restmüll und | |
// einer anderen Tonne ist sehr üblich. | |
int papiertonne = -1; // einmal pro Monat | |
int restmuell = -1; // je nach Bestellung: wöchentlich bis monatlich | |
int wertstoff = -1; // alle 2 Wochen | |
int bio = -1; // alle 2 Wochen | |
int laub = -1; // Laub ist nur im Herbst | |
// Den folgenden Event kann der Script noch nicht parsen, da er nur im Januar | |
// auftritt und ich dadurch den String momentan nicht ermitteln kann. | |
int weihnachtsbaum = -1; // die Weihnachtsbäume werden nur im Januar abgeholt | |
int i; | |
for(i=0; i<10; ++i) { // 10 Versuche in 60s Abständen die Daten zu lesen, falls das scheitert: in 3h nochmal versuchen | |
// Wir laden die Kalendardaten von der Stadtreinigung Hamburg | |
char buffer[200]; | |
sprintf(buffer, "/privatkunden/abfuhrkalender/Abfuhrtermin.ics?asId=%d&hnId=%d&adresse=%s%%20%s", asId, hnId, streetName, streetNumber); | |
HTTPPtr = httpget("www.stadtreinigung.hamburg", buffer); | |
// Durch den HTTP Request suchen. Alle Beschreibungen folgen dem Schema: | |
// "wird am TT.MM.JJJJ ... ___ ..." | |
char *httpPtr = HTTPPtr; | |
while(httpPtr != NULL) { | |
char *thttpPtr = strstrskip(httpPtr, "wird am "); | |
if(thttpPtr == NULL) | |
thttpPtr = strstrskip(httpPtr, "werden am "); | |
httpPtr = thttpPtr; | |
if(httpPtr == NULL) // Ende erreicht | |
break; | |
char tempEventBuffer[50]; | |
strncpy(tempEventBuffer, httpPtr, 50); tempEventBuffer[49] = 0; | |
if(strstr(tempEventBuffer, "Papier") != NULL) { | |
calcDate(tempEventBuffer, &papiertonne); | |
} else if (strstr(tempEventBuffer, "Rest") != NULL) { | |
calcDate(tempEventBuffer, &restmuell); | |
} else if (strstr(tempEventBuffer, "Wertstoff") != NULL) { | |
calcDate(tempEventBuffer, &wertstoff); | |
} else if (strstr(tempEventBuffer, "Bio") != NULL) { | |
calcDate(tempEventBuffer, &bio); | |
} else if (strstr(tempEventBuffer, "Laub") != NULL) { | |
calcDate(tempEventBuffer, &laub); | |
} | |
// Hier muß noch die Weichnachtsbaumabfuhr nachgetragen werden | |
} | |
free(HTTPPtr); | |
if(restmuell >= 0) // den Termin muß es immer geben, wenn wir den finden, sind die Daten valide | |
break; | |
sleep(60*3); // 3 Minuten Pause vor dem nächsten Versuch | |
} | |
if(restmuell >= 0) { | |
char nextBuffer[150]; // dies ist der Text für den nächsten Termin der Müllabfuhr | |
nextBuffer[0] = 0; | |
int nextDay = -1; // dies ist der nächste Termin der Müllabfuhr | |
setoutput(1, restmuell); | |
if(restmuell >= 0) { | |
strcpy(nextBuffer, "Restmüll"); | |
nextDay = restmuell; // dies ist der nächste Termin der Müllabfuhr | |
} | |
setoutput(2, papiertonne); | |
if(papiertonne >= 0) { | |
if(papiertonne < nextDay) { | |
strcpy(nextBuffer, "Papier"); | |
nextDay = papiertonne; | |
} else if(papiertonne == nextDay) { | |
strcat(nextBuffer, ", Papier"); | |
} | |
} | |
setoutput(3, wertstoff); | |
if(wertstoff >= 0) { | |
if(wertstoff < nextDay) { | |
strcpy(nextBuffer, "Wertstoff"); | |
nextDay = wertstoff; | |
} else if(wertstoff == nextDay) { | |
strcat(nextBuffer, ", Wertstoff"); | |
} | |
} | |
setoutput(4, bio); | |
if(bio >= 0) { | |
if(bio < nextDay) { | |
strcpy(nextBuffer, "Bio"); | |
nextDay = bio; | |
} else if(bio == nextDay) { | |
strcat(nextBuffer, ", Bio"); | |
} | |
} | |
setoutput(5, laub); | |
if(laub >= 0) { | |
if(laub < nextDay) { | |
strcpy(nextBuffer, "Laub"); | |
nextDay = laub; | |
} else if(laub == nextDay) { | |
strcat(nextBuffer, ", Laub"); | |
} | |
} | |
setoutput(6, weihnachtsbaum); | |
if(weihnachtsbaum >= 0) { | |
if(weihnachtsbaum < nextDay) { | |
strcpy(nextBuffer, "Weihnachtsbaum"); | |
nextDay = weihnachtsbaum; | |
} else if(weihnachtsbaum == nextDay) { | |
strcat(nextBuffer, ", Weihnachtsbaum"); | |
} | |
} | |
if(nextDay < 0) { | |
setoutputtext(0, "-"); | |
setoutputtext(1, "Kein Termin"); | |
} else { | |
char dayBuffer[150]; | |
calcDateStr(nextDay, dayBuffer); | |
strcat(dayBuffer, ": "); | |
strcat(dayBuffer, nextBuffer); | |
setoutput(0, nextDay); // Wann wird das nächste mal Müll abgeholt? | |
setoutputtext(0, nextBuffer); // Welche Tonnen werden abgeholt? | |
setoutputtext(1, dayBuffer); // Wann und welche Tonnen werden abgeholt? | |
} | |
} | |
sleeps(60*60*3); // update alle 3 Stunden | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment