Skip to content

Instantly share code, notes, and snippets.

@sarnau
Created July 30, 2018 10:14
Show Gist options
  • Save sarnau/6bfc02ff7a8623467f75fa558f55f72b to your computer and use it in GitHub Desktop.
Save sarnau/6bfc02ff7a8623467f75fa558f55f72b to your computer and use it in GitHub Desktop.
// 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