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?

13 Kommentare
  1. Avatar
    Kai sagte:

    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

  2. Avatar
    Kai sagte:

    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

  3. Reinhard Eidelsburger
    Reinhard Eidelsburger sagte:

    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!

  4. Avatar
    Erwin sagte:

    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))) {

  5. Reinhard
    Reinhard sagte:

    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?

  6. Avatar
    David sagte:

    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

  7. Reinhard
    Reinhard sagte:

    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 🙂

  8. Avatar
    David sagte:

    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? 🙂

  9. Reinhard
    Reinhard sagte:

    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.

  10. Avatar
    Erwin sagte:

    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 😉

  11. Avatar
    Erwin sagte:

    Ja, auch im Dachauer LK.

    Ist das Listing oben das aktuelle oder mit den Ergänzungen, Änderungen aus den Kommentaren?

    Danke

  12. Reinhard Eidelsburger
    Reinhard Eidelsburger sagte:

    Hi Erwin,

    ich sende dir gleich mal die kompletten Dateien per E-Mail zu.

    Schöne Grüße,
    Reinhard

Dein Kommentar

An Diskussion beteiligen?
Hinterlasse uns Deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.