Abbildung “Müllkalender” in openHAB
Um regelmäßig seine Mülltonnen am Entsorgungstag am Straßenrand zu stellen, haben die meisten Personen einen Papierkalender im Haus. Viele Entsorger stellen aber auch die Abholdaten der Mülltonnen online oder per Kalender bereit
Für den Landkreis Dachau gibt es eine App (DAH-Müll) und eine Oberfläche zur Visualisierung. Leider kann man auf die Daten dort nicht direkt per ICS / iCalendar zugreifen (da haben sich die Zuständigen etwas sehr gutes einfallen lassen).
Deswegen muss man jetzt manuell einmal die Kalenderdaten pro Jahr dort exportieren und sie in einen eigenen Kalender importieren (geht auch, aber Anwenderfreundlich ist etwas anderes).
Der Anwendungsfall ist also einen Kalender auszulesen und am Vortag eine Erinnerung an die digitalen Endgeräte, Sprachsteuerungen oder Kalender zu senden. Dazu wird in openHAB das CalDAV-Binding verwendet.
Beispiele für die Verwendung findet Ihr hier bei onesmarthome.de oder im openhabforum.de.
Kalendereinrichtung
Im ersten Schritt besorgt man sich die iCalendar-Daten aus seinem jeweiligen Landkreis / Ort. Bei mir waren die Daten hier.
Leider musste ich die Inhalte noch etwas “umformatieren”:
- DTEND-Tag fehlt in den Kalenderdaten (ohne diese können die Daten nicht in der ownCloud verwendet werden)
- DTEND-Tag muss einen Tag nach dem DTSTART-Tag gesetzt sein (sonst können die Daten nicht in der ownCloud verwendet werden)
Danach habe ich in meinem System (hier ownCloud) einen Kalender “Müll” erstellt und die oben beschriebenen Daten importiert.
Danach kann ich folgenden Link für die weitere Integration verwenden:
https://URL/remote.php/dav/calendars/USER/CALENDAR/
Die URL, USER und CALENDAR müsst Ihr an eure Anforderungen anpassen.
Binding
Das CalDAV1-Binding wird wie folgt installiert:
Paper UI – Add-ons – Bindings – CalDAV Binding (personal) – INSTALL
ACHTUNG: Das CalDAV Binding (command) wird zur Steuerung und Präsenzmeldung verwendet und ist für diesen Beitrag nicht notwendig.
Services (caldavio.cfg)
Es wird die Datei services/caldavio mit folgendem Inhalt erstellt:
caldavio:Muell:url=https://URL/remote.php/dav/calendars/USER/CALENDAR/
caldavio:Muell:username=USER
caldavio:Muell:password=PASSWORD
caldavio:Muell:reloadInterval=60
caldavio:Muell:preloadTime=2880
caldavio:Muell:disableCertificateVerification=true
caldavio:Muell:charset=utf8
Die groß geschriebenen Wörter bitte mit euren Daten ergänzen. Wichtig war in meiner Konfiguration noch disableCertificateVerification (wahrscheinlich wegen meinen kostenlosen Zertifikaten) und charset auf UTF-8.
Den reloadInterval kann man zum Testen auch auf 1 Minute stellen.
Items (CalDAV.items)
Ich habe für zwei Kalendereinträge und Datumswerte die Items generiert (es können bei mir zwei Tonnen zum gleichen Tag abgeholt werden):
/* Müllkalender */ String CalDAV_Muell_1 "Erste Tonne [%s]" <calendar> { caldavPersonal="calendar:Muell type:EVENT eventNr:1 value:NAME" } DateTime CalDAV_Muell_1_Date "Datum der Abholung [%1$td.%1$tm.%1$tY]" <calendar> { caldavPersonal="calendar:Muell type:EVENT eventNr:1 value:START" } String CalDAV_Muell_2 "Zweite Tonne [%s]" <calendar> { caldavPersonal="calendar:Muell type:EVENT eventNr:2 value:NAME" } DateTime CalDAV_Muell_2_Date "Datum der Abholung [%1$td.%1$tm.%1$tY]" <calendar> { caldavPersonal="calendar:Muell type:EVENT eventNr:2 value:START" }
Sitemap
In der Sitemap habe ich das recht einfach so dargestellt:
Frame label="Informationen" { Frame label="Müllkalender"{ Text item=CalDAV_Muell_1 Text item=CalDAV_Muell_1_Date Text item=CalDAV_Muell_2 Text item=CalDAV_Muell_2_Date } }
Rules (CalDAV.rules)
Nun erfolgt die Automatisierung und die Benachrichtigung in der Regel (das kann man bestimmt noch etwas eleganter “scripten”):
rule "Müllkalender" when //Time cron "0 * * ? * *" //every 1 Minute Time cron "0 15 17 * * ?" //once per Day 17:15 //Item date_today changed then var String muelltonne_1 muelltonne_1 = CalDAV_Muell_1.state.toString var String muelltonne_2 muelltonne_2 = CalDAV_Muell_2.state.toString // Prüfung ob der Wert gefüllt ist (damit beim cast auf DateTimeType keine Fehlermeldung erscheint) if (muelltonne_1 != "UNDEF") { // Datum der Abholung wird mit dem aktuellen Datum verglichen // die erste Bedingung prüft, ob das aktuelle Datum vor dem Ablaufdatum + 24 Std. liegt // die zweite Bedingung prüft, ob das aktuelle Datum nach dem Datum der Abholung liegt if (now.isBefore(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getCalendar().getTime()).plusHours(24)) && now.isAfter(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getCalendar().getTime()))) { // Benachrichtigung per Telegram an Bot senden if(muelltonne_2 == "UNDEF") { sendTelegram("xxx_bot", "Müllkalender: %s", muelltonne_1) logInfo("INFO","CalDAV.rules - Müllkalender: %s", muelltonne_1) } else { sendTelegram("xxx_bot", "Müllkalender: %s & %s", muelltonne_1, muelltonne_2) logInfo("INFO","CalDAV.rules - Müllkalender: %s & %s", muelltonne_1, muelltonne_2) } } } end
Fazit
Die Anbindung des Kalenders in openHAB war relativ einfach. Etwas schwieriger hat sich die Anpassung der ICS-Datei aus meinem Landkreis gestaltet. Danach hat man recht einfach (nach ein paar Tests) seine Kalenderdaten angebunden.
In der Regel waren dann noch ein paar Workarounds notwendig, aber dann waren die Daten auch richtig vorhanden. Die Konvertierung in UTF-8 / Unicode war nicht so einfach in der cfg zu finden. Auch den CRON-Job nur einmal am Tag zu einer bestimmten Zeit auszuführen war für einen “Nicht-UNIXer” nicht das einfachste 😉
Nun bekomme ich aber am Vortag um 17:15 Uhr eine Information per Telegram, dass die Müllabfuhr am nächsten Tag kommt.
Habt Ihr noch Ideen für die weitere Anbindung von Kalenderdaten? Habt Ihr eine Präsenzmeldung oder Steuerung eures SmartHome damit realisiert?
Hallo
Erst einmal danke für die ausführliche Anleitung.
Bekomme aber folgende Meldung
2018-10-20 20:01:14.445 [INFO ] [el.core.internal.ModelRepositoryImpl] – Validation issues found in configuration model ‘Muell.rules’, using it anyway:
The method getCalendar() from the type DateTimeType is deprecated
Gibt es eine Lösung ?
Danke
Ok habs gefunden
rule “Müllkalender”
when
Time cron “0 00 19 * * ?” or
System started
then
var String Tonne
Tonne = CalDav_Tonne .state.toString
if (Tonne != “UNDEF”)
{
if
(now.isBefore(new DateTime((CalDav_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)) &&
now.isAfter(new DateTime((CalDav_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli)))
{sendCommand(Muell, ON)}
{ sendTelegram(“xxx_bot”, “Morgen %s rausstellen “, Tonne ) }
}
end
Hallo Kai,
vielen Dank für die Verbesserung. Jetzt sind auch die “Deprecated-Meldungen” bei mir weg. Ich teste die Tage mal folgende Anpassung (den Artikel oben habe ich noch nicht aktualisiert):
if (now.isBefore(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)) &&
now.isAfter(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli))) {
und zum Beginn der Regel habe ich das “System started” noch mit aufgenommen.
Vielen Dank!
Hallo Reinhard,
Danke für die Anleitung. Ich habe aber noch Probleme mit dem if Term; Fehlermeldung bekomme ich nicht, aber auch keine Telegrams.
Vielleicht findest du ob ein Fehler drin ist:
Danke
if (now.isBefore(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)) && now.isAfter(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli))) {
Hallo Erwin,
ich habe gerade noch einmal meinen Stand kontrolliert. Der sieht wie folgt aus:
if (now.isBefore(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)) &&
now.isAfter(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).minusHours(8))) {
//logInfo(“INFO”,”CalDAV.rules – Müllkalender: TEST3″)
// Benachrichtigung per Telegram an Bot senden
if(muelltonne_2 == “UNDEF”) {
sendTelegram(“xxx”, “Müllkalender: ” + muelltonne_1)
logInfo(“INFO”,”CalDAV.rules – Müllkalender: ” + muelltonne_1)
} else {
sendTelegram(“xxx”, “Müllkalender: ” + muelltonne_1 + ” & ” + muelltonne_2)
logInfo(“INFO”,”CalDAV.rules – Müllkalender: ” + muelltonne_1 + ” & ” + muelltonne_2)
}
}
So funktioniert es bei mir in openHAB 2.4. Generell funktioniert Telegram bei dir, oder?
Hallo Reinhard,
danke für deine Mühe.
Die rule geht so semi bei mir.
Items werden geupdatet, aber die Benachrichtigung per pushover (bei dir per Telegramm) kommt immer erst am Tag der Abholung um 17:15 Uhr, wo es leider schon zu spät ist.
Ist das bei dir auch so?
Vielen Dank,
David
Hi David,
das ist bei mir abhängig wie die Kalenderdaten im CalDAV-Binding gelesen werden. Ich lasse das am Abend davor und am Abholtag ausgeben. Damit die Tonne auch wieder geholt wird 🙂
Ok, mein Termin im Item ist für den Abholtag um 00:00 Uhr gesetzt.
Kannst du mir sagen, wie ich es schaffe, einen Tag vorher zu benachrichtigen? Muss ich bei .plusHours(24) oder .minusHours(?) was ändern? 🙂
Ich habe es so drin:
if (now.isBefore(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).plusHours(24)) &&
now.isAfter(new DateTime((CalDAV_Muell_1_Date.state as DateTimeType).getZonedDateTime.toInstant.toEpochMilli).minusHours(8))) {
…
Und die Regel wird um 18 Uhr so ausgeführt:
rule “Müllkalender”
when
Time cron “0 0 18 * * ?” //once per Day 18:00
…
Damit kriege ich 18 Uhr vor dem Abholungstag eine Nachricht.
Hallo,
ich bin’s noch mal. Ich bekomme ein komisches Verhalten. Beim ersten start von rule und things wird alles gut ausgelesen und auch die Termine angezeigt. Aber schon am nächsten Tag bekommen die Variablen NULL als Wert und ich bekomme diesen Fehler:
[ERROR] [ntime.internal.engine.ExecuteRuleJob] – Error during the execution of rule ‘Muellkalender’: Could not cast NULL to org.eclipse.smarthome.core.library.types.DateTimeType; line 32, column 37, length 41
Die Abfrage erfolgt immer um 18 Uhr, das passt also …
Mittwoch wäre der Tag, an dem etwas angezeigt werden müsste, tut es aber leider nicht.
Hast du noch eine Idee? Wir nutzen übrigens die gleiche Kalenderquelle 😉
Nein, bei mir läuft es so.
Bist du auch im Münchner Umkreis?
Ja, auch im Dachauer LK.
Ist das Listing oben das aktuelle oder mit den Ergänzungen, Änderungen aus den Kommentaren?
Danke
Hi Erwin,
ich sende dir gleich mal die kompletten Dateien per E-Mail zu.
Schöne Grüße,
Reinhard
Hallo
Ich habe ungefähr die gleiche Rule, erhalte jedoch jedes Mal die folgende Fehlermeldung:
[ERROR] [ntime.internal.engine.RuleEngineImpl] – Rule ‘Abfalltermine sortieren’: Could not cast UNDEF to org.eclipse.smarthome.core.library.types.DateTimeType; line 13, column 47, length 31
Kannst du mir weiter helfen?
Das ist meine Rule:
rule “Abfalltermine sortieren”
when
Item Restmuell received update or
Item Biomuell received update or
Item Papiermuell received update or
Item RestmuellTage changed or
Item PapiermuellTage changed or
Item BiomuellTage changed or
Time cron “0 8 0 1/1 * ? *”
then
Thread::sleep(3000)
var DateTime varTempDatum
var DateTime varAbfall1Datum = new DateTime((Restmuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
logInfo(“Afval.rules”, “varAbfall1Datum” +varAbfall1Datum)
var DateTime varAbfall2Datum = new DateTime((Biomuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
logInfo(“Afval.rules”, “varAbfall2Datum” +varAbfall2Datum)
var DateTime varAbfall3Datum = new DateTime((Papiermuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
logInfo(“Afval.rules”, “varAbfall3Datum” +varAbfall3Datum)
var String varTempArt
var String varAbfall1Art = “Restmuell”
var String varAbfall2Art = “Biomuell”
var String varAbfall3Art = “Papiermuell”
var String varTempTage
var String varAbfall1Tage = RestmuellTage.state.toString
var String varAbfall2Tage = BiomuellTage.state.toString
var String varAbfall3Tage = PapiermuellTage.state.toString
var i = 1
while ((i=i+1) varAbfall2Datum) {
varTempDatum = varAbfall1Datum
varAbfall1Datum = varAbfall2Datum
varAbfall2Datum = varTempDatum
varTempArt = varAbfall1Art
varAbfall1Art = varAbfall2Art
varAbfall2Art = varTempArt
varTempTage = varAbfall1Tage
varAbfall1Tage = varAbfall2Tage
varAbfall2Tage = varTempTage
logInfo(“Afval.rules”, “varTempTage” +varTempTage)
if (varAbfall2Datum > varAbfall3Datum) {
varTempDatum = varAbfall2Datum
varAbfall2Datum = varAbfall3Datum
varAbfall3Datum = varTempDatum
varTempArt = varAbfall2Art
varAbfall2Art = varAbfall3Art
varAbfall3Art = varTempArt
varTempTage = varAbfall2Tage
varAbfall2Tage = varAbfall3Tage
varAbfall3Tage = varTempTage
logInfo(“Afval.rules”, “varTempTage” +varTempTage)
}
}
if (varAbfall2Datum > varAbfall3Datum) {
varTempDatum = varAbfall2Datum
varAbfall2Datum = varAbfall3Datum
varAbfall3Datum = varTempDatum
varTempArt = varAbfall2Art
varAbfall2Art = varAbfall3Art
varAbfall3Art = varTempArt
varTempTage = varAbfall2Tage
varAbfall2Tage = varAbfall3Tage
varAbfall3Tage = varTempTage
logInfo(“Afval.rules”, “varTempTage” +varTempTage)
}
}
Abfall_1_Datum.postUpdate(varAbfall1Datum.toString)
logInfo(“Afval.rules”, “Abfall_1_Datum” +Abfall_1_Datum)
logInfo(“Afval.rules”, “varAbfall1Datum” +varAbfall1Datum)
Abfall_2_Datum.postUpdate(varAbfall2Datum.toString)
Abfall_3_Datum.postUpdate(varAbfall3Datum.toString)
Abfall_1_Art.postUpdate(varAbfall1Art)
Abfall_2_Art.postUpdate(varAbfall2Art)
Abfall_3_Art.postUpdate(varAbfall3Art)
Abfall_1_Tage.postUpdate(varAbfall1Tage)
Abfall_2_Tage.postUpdate(varAbfall2Tage)
Abfall_3_Tage.postUpdate(varAbfall3Tage)
end
danke im voraus
(Google Translate)
Hallo Jeroen,
ist denn die Zeile 13 der folgende Auszug:
var DateTime varAbfall1Datum = new DateTime((Restmuell.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
Was kommt den hier bei dieser Log-Info bei dir an:
logInfo(„Afval.rules“, „varAbfall1Datum“ +varAbfall1Datum)
Es liest sich ja so, ob er da schon das Datum nicht entsprechend bekommt z.B. leer ist oder die “Konvertierung” nicht klappt. Das mit dem “UNDEF” kann in der Scripting-Welt leider sehr viel sein.
Schöne Grüße,
Reinhard
Hallo,
kann man den code vielleicht überarbeiten und posten mit den ganzen änderungen für mich als neuling ist das total unübersichtlich. danke
Hi marc,
schick mir bitte kurz deine E-Mail-Adresse, dann lasse ich dir vorab die kompletten Dateien von mir einmal zukommen.
Ich versuche dann auch demnächst einmal einen aktualisierten Artikel zu schreiben.
Schöne Grüße,
Reinhard
Hallo Reinhard,
wäre auch sehr interessiert, musste meine ics-Datei auch ordentlich umschreiben (Umkreis Stuttgart), aber hab zumindest alles im Kalender. Als opeHAB Neuling wären deine Dateien Gold wert, dann kann ich mich dran setzen und verstehe danach hoffentlich auch die Zusammenhänge besser!
Danke & Gruß,
Jörg