Seite 1 von 1

Nachricht über Niedrige Batterie mit Blockly

Verfasst: 25. Feb 2023 18:58
von AndyRPi
Ich habe mir ein Blockly erstellt um bei einem niedrigen Batteriestatus mir auf Telegram senden zu lassen.
Ich musste eine Verzögerung einbaunen da sonst die Meldugnen per Telegramm nicht sauber angekommen sind.
In den Logs kam es auch sauber wenn ich die Verzögerung nicht drin hatte.

Hoffe es kann mir jemand helfen
batteriestatus.JPG

Re: Nachricht über Niedrige Batterie mit Blockly

Verfasst: 25. Feb 2023 19:50
von udo1toni
Ich nehme an, Du hast eine weitere Rule, welche bei einem Update des Items Neue_Textnachricht die Message rausbläst. Da ist es kein Wunder, dass das nicht so funktioniert.
openHAB arbeitet asynchron. Wenn Du mittels postUpdate ein Item auf einen Status setzt, dann wird dieser "Job" gestartet und die Rule arbeitet weiter. Hier wechselt sie zum nächsten Item und haut das nächste Update raus (also mal vorausgesetzt, dass mehrere Items nacheinander den Status ON haben). Die postUpdates gehen also vermutlich deutlich im einstelligen Millisekundenbereich ein.

Deine Rule hat aber noch eine andere Schwäche, die natürlich nur zum Tragen kommt, wenn mehrere Items einen niedrigen Batteriestand melden, und das ist, dass Du für jedes Item eine einzelne Meldung bekommst. Das ist nicht schön.

Ich kann das jetzt leider nicht per Blockly zusammenklicken, weil ich bei der Arbeit bin :) aber sinnvoller ist es, so eine Liste zunächst aufzubauen und anschließend zu verschicken.
Weiterhin sollte es auch in Blockly eine Filter-Funktion geben. Statt also alle Items der Liste zu durchlaufen, wäre es sinnvoller, die Liste auf die Elemente zu filtern, deren Status ON ist.
Damit entfällt die Prüfung auf den Status und nebenbei erhältst Du auf Wunsch noch eine Information über die Anzahl Batterien, die Du besorgen musst :)
Als DSL Rule so:

Code: Alles auswählen

rule "Batteriestand melden"
when
    Item Abfrage changed to ON
then
    Abfrage.postUpdate(OFF)
    val StringBuilder Text = new StringBuilder
    val myItems = Low_Batt.members.filter[i|i.state == ON]
    if(myItems.size == 0)                                   // Wenn es nichts zu melden gibt
        return;                                             // Rule frühzeitig beenden

    Text.append("Niedriger Batteriestand bei ")
    myItems.forEach[j,h|
        Text.append(j.label)
        if(h < myItems.size - 1)
            Text.append(", ")
    ]
    Text.append(". Insgesamt "+myItems.size.toString+" Geräte betroffen.")
    Neue_Textnachricht.postUpdate(Text.toString)
end
Die Rule wird getriggert, wenn das Item Abfrage auf ON wechselt. Hier gehen natürlich auch andere Trigger :)
In der Rule wird der Trigger wieder zurückgesetzt. Anschließend wird ein StringBuilder initialisiert (könnte man auch über eine normale String Variable machen..., aber der StringBuilder macht das in "hübsch" :D ).
Nun wird die Liste der Items auf diejenigen gefiltert, die den Zustand ON haben.
Anschließend wird die Größe der Liste geprüft. Ist die null Elemente lang (.size == 0), so kann die Rule schon wieder beendet werden.
Läuft die Rule weiter, so ist klar, dass es eine Meldung geben muss, also wird nun der Meldetext zusammengebaut. Nach der einleitenden Information folgt eine Schleife über die gefilterte Liste, dabei wird für jedes Element der Liste das Label an den Text angehängt. Folgen noch weitere Elemente (h zählt die Schleifendurchläufe mit, beginnend mit 0!), wird noch ein Komma ergänzt.
Ist die Schleife fertig, so wird noch der Rest der Meldung ergänzt (incl. Anzahl der Items...)
Zum Abschluss wird der Meldetext abgesetzt (um den kümmert sich ja vermutlich eine andere Rule).

Wie gesagt kannst Du die Rule ziemlich sicher exakt so auch über Blockly zusammenklicken, eventuell musst Du eine String Variable anstatt des StringBuilders nutzen, der Rest sollte aber genauso funktionieren.
Allerdings kann man das in der DSL schon sehr schlank erledigen. :)
Ich habe auch schon mal die ein wenig anspruchsvollere Variante erstellt, die zwischen einem einzelnen und mehreren Geräten unterscheidet und im Satzbau darauf Rücksicht nimmt, incl. dass das letzte Komma der Aufzählung durch das Wort "und" ersetzt wird, also z.B.:
"Das Gerät Gerät01 meldet einen niedrigen Batteriestand."
"Die Geräte Gerät01 und Gerät05 melden einen niedrigen Batteriestand."
"Die Geräte Gerät01, Gerät03 und Gerät05 melden einen niedrigen Batteriestand. Betroffen sind 3 Geräte."

Re: Nachricht über Niedrige Batterie mit Blockly

Verfasst: 25. Feb 2023 23:22
von AndyRPi
Vielen Dank Udo für Deine Idee.
Ich würde da gerne Blockly besser verstehen daher will es damit probieren.
Die Liste bekomme ich erstellt, auf zwei Arten, jedoch bekomme ich keinen Filter hin
batteriestatus.JPG

Re: Nachricht über Niedrige Batterie mit Blockly

Verfasst: 26. Feb 2023 07:05
von Harka
Moin,
eine komfortable Filterfunktion konnte ich jetzt auch nicht finden. Mal sehen ob da mit OH 4 was kommt oder ob die neue Kopierfunktion dazu anregt sich eine entsprechende Funktion zu erstellen die man bei Bedarf einfach einfügt oder es veröffentlicht jemand einen Block für die Libraries....

Wenn Du, wie bei Udo, die Infos erst mal sammelst und erst am Ende die gesammelte Ausgabe an Telegramm schickst, funktionickelt es.
(musst halt noch die beiden item-Namen austauschen - wollte bei mir jetzt keine neuen anlegen)
Forum.jpg

Re: Nachricht über Niedrige Batterie mit Blockly

Verfasst: 26. Feb 2023 13:55
von udo1toni
Es ist erstaunlich, wie schnell man bei Blockly an Grenzen stößt... :)
Es gibt keine Grund, warum die Filter-Funktion nicht auch als Block zur Verfügung stehen sollte. Hat halt nur noch niemand gebaut :)
Natürlich kann man auch damit leben, die Bedingung innerhalb der Schleife zu nutzen, man muss dann halt bestimmte Dinge vermeiden oder anders lösen (man könnte z.B. innerhalb des forEach eine Liste mit Elementen füllen und anschließend mit dieser Liste arbeiten, auch dort stehen Informationen wie die Länge der Liste usw. zur Verfügung. Aber es ist natürlich weniger elegant :)