Kalendereintrag einen Tag früher

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Antworten
arohleder
Beiträge: 9
Registriert: 13. Apr 2022 13:41
Answers: 0

Kalendereintrag einen Tag früher

Beitrag von arohleder »

Hallo zusammen,
Schon wieder ein Problem.
Kann mir einer sagen warum ich beim Ausführen der Rule:

Code: Alles auswählen

rule "Abfall_morgen"
    when
    	Time cron "0 0 19 * * ?"
    then
		if(new Date((ir.getItem("AbfallKalender_Next_Start").state()) - new Date()) < 104400000)
			{
    	telegramAction = getActions("telegram","telegram:telegramBot:0815")
		telegramAction.sendTelegram("Abholung morgen: " + AbfallKalender_Current_Title.state)
		}
    end
Folgende Fehlermeldung bekomme?

Code: Alles auswählen

2024-09-20 20:37:45.938 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Abfall_morgen-1' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.xtext.common.types.JvmType.eIsProxy()" because "type" is null in Abfall_morgen
Wäre Toll wenn ihr ne Lösung hättet.
Gruß Achim

Benutzeravatar
udo1toni
Beiträge: 15240
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Kalendereintrag einen Tag früher

Beitrag von udo1toni »

Du wirfst da verschiedene Sprachen durcheinander.

Der Rahmen

Code: Alles auswählen

rule "Rulename"
when
// Trigger
then
 // Codeblock
end
ist die openHAB Rules DSL (domain specific language).
Das Statement

Code: Alles auswählen

ir.getItem("AbfallKalender_Next_Start").state()
stammt aber aus einer anderen Sprache, evtl. aus der Definition eines Widgets in der Main UI (nicht ganz eindeutig...)
Du möchtest gerne auf den Status des Items zugreifen, welcher offenbar ein Datum enthält.
Die Funktion

Code: Alles auswählen

new Date()
gibt es so in der DSL auch nicht.
Mir ist nicht so ganz klar, was die Zahl 104400000 darstellen soll, aber ich nehme an, dass Du möchtest, dass die Rule Dir um 19 Uhr eine Nachricht schickt, wenn der Status des DateTime Items innerhalb des nächsten Tages liegt (das wären 104.000 Sekunden, siehe unten).

Dazu ist zunächst zu sagen, dass das Rechnen mit Datum und Uhrzeit in der DSL nicht so einfach ist wie in anderen Sprachen, das liegt darin begründet, dass ein DateTime Item den Datentyp DateTimeType enthält, die DSL intern aber DateTime (ohne Type, das ist der Java Datentyp) verwendet. Das bedeutet, Du musst leider die Datentypen konvertieren. Ist aber eigentlich gar nicht soooo wild...

Code: Alles auswählen

rule "Abfall morgen"
 when
    Time cron "0 0 19 * * ?"
 then
    if(!(AbfallKalender_Next_Start.state instanceof DateTimeType))                    // check for valid date
        return;                                                                       // not valid, break
    val theDate = (AbfallKalender_Next_Start.state as DateTimeType).getZonedDateTime
    if(theDate.toEpochSecond - now.toEpochSecond > 104000)                            // 29*60*60, check for tomorrow
        return;                                                                       // not tomorrow, break

    val telegramAction = getActions("telegram","telegram:telegramBot:0815")
    telegramAction.sendTelegram("Abholung morgen: " + AbfallKalender_Current_Title.state.toString)
end
Die Rule funktioniert etwas anders als Deine, aber dann doch sehr ähnlich...
Zunächst wird nach dem Triggern der Rule geprüft, ob das Item AbfallKalender_Next_Start als Status ein gültiges Datum enthält (der Status ist vom Typ DateTimeType). Ist das nicht der Fall (das ! bedeutet logisches NOT), so bricht die Rule ab,
mittels return; - Achtung! Dieser Befehl ist der einzige, an dem ein Semikolon angehängt werden muss.
Die Prüfung auf den Datentyp ist wichtig, denn der Status könnte genauso gut auch NULL oder UNDEF enthalten. Beides würde eine nullPopinterException auslösen.
Als nächstes wird der Status in ZonedDateTime überführt (das bedeutet, die Zeitzone ist Bestandteil des Wertes)
Nun wird der Vergleich durchgeführt, ganz ähnlich wie in Deinem Code, indem vom Zielzeitpunkt (enthalten in theDate) der aktuelle Zeitpunkt (now) abgezogen wird. Das lässt sich am einfachsten erledigen, indem man mit EpochSecond rechnet. Das ist die Zeit seit dem 1.1.1970, 0:00:00 Uhr (ohne Berücksichtigung von Schaltsekunden) in Sekunden. Die Umrechnung geht einfach, weil der Datentyp DateTime die Methode toEpochSecond bereitstellt.
Ist der Wert größer als 29 * 60 * 60, so bricht die Rule ab. (19 Uhr + 5 Stunden + 24 Stunden ergibt Übermorgen, 0:00:00 Uhr)
Falls die Rule nun immer noch läuft, sind alle Bedingungen erfüllt, um die Meldung zu verschicken, also wird eine lokale Konstante mit dem Zeiger auf die telegram Actions geladen (val ist hier essenziell, sonst meckert openHAB).
Zu guter Letzt wird die Action sendTelegram aufgerufen und im Text wird der Status des Items AbfallKalender_Current_Title mit ausgegeben, nachdem dieser Status in einen String gewandelt wurde.
Die Konvertierung nach String ist in diesem Fall notwendig, auch wenn das Item bereits einen String bereitstellt.

Merke:
Ein Status ist kein String :) auch wenn er einen enthält.
DateTime ist keine Zahl, man kann nicht einfach so DateTime voneinander abziehen.
Items werden in der DSL immer direkt angesprochen, nicht über Konstrukte wie .getItem(Itemname).
Typprüfungen durchführen...
Wenn möglich, mit Codeabbruch arbeiten (kostet weniger Zeit als die normale bedingte Verzweigung)
Alle Wertzuweisungen in Variablen oder Konstanten müssen durch deren Definition eingeleitet werden - val für Konstante, var für Variable.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

arohleder
Beiträge: 9
Registriert: 13. Apr 2022 13:41
Answers: 0

Re: Kalendereintrag einen Tag früher

Beitrag von arohleder »

Perfekt, vielen Dank das funktioniert!!!
Gut das es Euch gibt!!!

arohleder
Beiträge: 9
Registriert: 13. Apr 2022 13:41
Answers: 0

Re: Kalendereintrag einen Tag früher

Beitrag von arohleder »

Eine Frage hätte ich dann noch:
Wenn ich das nicht auf Telegram, sondern an openhab schicken will, geht das so aber nicht.
Verwechsle ich da auch wieder die Sprachen?
var NotificationAction = org.openhab.io.openhabcloud.NotificationAction;
NotificationAction.sendNotification("x@x.net", "Abholung heute: " + AbfallKalender_Current_Title.state);
Vielen Dank schon mal vorab

Benutzeravatar
udo1toni
Beiträge: 15240
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Kalendereintrag einen Tag früher

Beitrag von udo1toni »

Es gibt verschiedene Optionen, Nachrichten zu verschicken. Da ich kein MyOpenHAB nutze, bin ich da eher die falsche Person :) aber ganz grundsätzlich reicht ein

Code: Alles auswählen

sendNotification("me@email.com", "Front door was opened!")
für eine Benachrichtigung an den openHAB Cloud User mit der eMail me@email.com. (die Notification ist Teil von Core, weshalb Du hier gar nichts importieren musst).
Voraussetzung ist aber die Nutzung der openHAB Cloud (z.B. myopenhab.org).
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

tim.l
Beiträge: 71
Registriert: 24. Jun 2022 08:16
Answers: 2
Wohnort: Bielefeld
Kontaktdaten:

Re: Kalendereintrag einen Tag früher

Beitrag von tim.l »

Hallo arohleder,

ggf. noch als Ergänzung. Das ist der Grund, warum ich bei meiner müll.io Idee ( siehe https://müll.io/integration/openhab ) ein relatives Datum mit aufgenommen habe. Dadurch kannst du einfach schauen, ob um 19.00 uhr das relative Datum auf 1 (also noch 1 Tag) ist und dann entsprechend die Benachrichtigung auslösen und brauchst nicht mehr selbst durchzurechnen. Falls müll.io bei dir nicht geht, sag Bescheid. Gerne ergänze ich Provider...

Beste Grüße,
Tim
Meine openHAB Erfahrungen bei mir im Blog: https://360friends.de/tag/openhab/ ;)

Antworten