Hilfe bei der Gestaltung einer DSL Regel

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Benutzeravatar
scotty
Beiträge: 676
Registriert: 28. Apr 2020 04:44
Answers: 0

Hilfe bei der Gestaltung einer DSL Regel

Beitrag von scotty »

Hallo,

Bei meinem selbst gebauten Widget zur Anzeige von eingehenden oder ausgehenden Telefonaten kommt es vor, dass der Teilnehmer nicht in meinem Telefonbuch enthalten ist. In diesen Fällen wird aktuell im Item 'Name' und im Item 'Telefonnummer' die Telefonnummer gesetzt.
Nun möchte ich eine textbasierte Regel schreiben, welche bei derartigen Vorkommen in das Item Name dann 'unbekannt' setzt. Momentan stehe ich allerdings etwas auf dem Schlauch.
Der Trigger wäre ein Update für das Item 'Name'.

Hat jemand einen Vorschlag für mich?
Zuletzt geändert von scotty am 4. Nov 2022 17:21, insgesamt 2-mal geändert.
OH 3.4.5 im Docker auf Synology DS918+ mit USV, Reolink-RLC-511WA, Philips Hue, AVM Fritz!Box 6591C, Alexa, Logitech Harmony und diversen Shelly's

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

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von udo1toni »

Na, Du musst ja nur prüfen, ob in beiden Items das gleiche drin steht...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
scotty
Beiträge: 676
Registriert: 28. Apr 2020 04:44
Answers: 0

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von scotty »

Ist klar, mir geht es um die Formulierung, wie geprüft werden soll,

z. B.
when Item1 changed update
then
if item1 = item1
item1.postupdate("irgendwas")

oder wie?
OH 3.4.5 im Docker auf Synology DS918+ mit USV, Reolink-RLC-511WA, Philips Hue, AVM Fritz!Box 6591C, Alexa, Logitech Harmony und diversen Shelly's

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

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von udo1toni »

Du musst schon die Status miteinander vergleichen. also z.B.

Code: Alles auswählen

rule "unbekannt setzen"
when
    Item CallerName changed
then
    if(newState.toString == CallerNumber.state.toString)
        CallerName.postUpdate("unbekannt")
end
So halt...

newState enthalt CallerName,state, weil CallerName das Item ist, welches die Rule getriggert hat. Auch wenn es sich bei beiden Items um String Items handelt, und damit der Status jeweils ein String ist, muss zunächst .toString verwendet werden.

Das hier ist übrigens meine Rule für eingehende Anrufe:

Code: Alles auswählen

rule "incoming call"
 when
    Member of Anruf received update
 then
    logInfo ("incoming","Call: {}",triggeringItem.state.toString)
    val StringBuilder sb = new StringBuilder
    sb.append(transform("JSONPATH","$.name",triggeringItem.state.toString))
    sb.append(" (")
    sb.append(transform("JSONPATH","$.number",triggeringItem.state.toString)) 
    sb.append(") -> ")
    sb.append(transform("JSONPATH","$.extension",triggeringItem.state.toString))
    logInfo ("incoming","sb {}",sb.toString)
    Anrufer.postUpdate(sb.toString)
    Anrufzeit.postUpdate(new DateTimeType())
    if (VDR_GF_Living_NH.state==ON)
        VDR_GF_Living_OSDMessage.sendCommand ('Anruf von ' + sb.toString)
    if (VDR_FF_Parents_NH.state==ON)
        VDR_FF_Parents_OSDMessage.sendCommand ('Anruf von ' + sb.toString)
end
Ich habe für jede ankommende Rufnummer ein eigenes Item, welches per JSON seine Infos abliefert.
Daraus baue ich einen String der Form "Name (Nummer) -> Anrufnummer"
Wobei meine TK-Anlage bei unbekannten Nummern von sich aus "unbekannt" als Name setzt, aber das wäre ja nur ein Detail, welches ich genauso gut in der Regel abfangen könnte. Der Punkt ist, dass ich nur ein Item für den Anruf verwende (gut, zwei, weil ich noch die Anrufzeit separat setze).
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
scotty
Beiträge: 676
Registriert: 28. Apr 2020 04:44
Answers: 0

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von scotty »

Super, dafür habe ich den ganzen Nachmittag getestet. Bei mir sind übrigens auch für jedes ausgehende und eingehendes Gespräch Items angelegt.

Leider kenne ich mich mit JSON nicht aus. Das ist nicht JavaScript, oder?
OH 3.4.5 im Docker auf Synology DS918+ mit USV, Reolink-RLC-511WA, Philips Hue, AVM Fritz!Box 6591C, Alexa, Logitech Harmony und diversen Shelly's

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

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von udo1toni »

Die verschiedenen Trigger für Items:

received command [COMMAND]: Das Item hat entweder über sendCommand() oder über die UI einen Befehl erhalten (wahlweise kann auch ein bestimmter Befehl angegeben werden)
received update [STATUS]: Das Item hat ein Update seines Status erhalten. Wahlweise einen bestimmten Status. Entweder über eine externe Quelle (Binding), ein Update aus der UI heraus (als Folge eines sendCommand() mit anschließendem autoUpdate) oder über den Befehl postUpdate().
changed [from STATUS] [to STATUS]: Das Item hat den Status geändert. Wahlweise von oder/und zu einem bestimmten Status. (ansonsten wie bei receved update)

Der Unterschied: received update triggert immer, wenn der Status aktualisiert wurde, egal, ob es sich um den gleichen Status handelt, während changed nur triggert, wenn sich der Status durch das Update auch ändert.
Es kann natürlich im vorliegenden Fall passieren, dass zweimal hintereinander die gleiche Nummer anruft, welche nicht im Telefonbuch hinterlegt ist.
Dadurch wird dennoch ein changed Ereignis ausgelöst, denn das Item wurde vorher von der selben Rule auf unbekannt gesetzt, während der zweite Anruf dort wieder die Nummer einspeichert. Es ist also sinnvoll, nur auf changed zu triggern, da nur in diesem Fall eine Überprüfung notwendig sein kann. received update braucht man meist nur, wenn ein Channel ausschließlich ein bestimmtes Telegramm sendet, z.B. ein Klingeltaster sendet evtl. kein OFF nach dem ON, weil ja klar ist, dass der Taster auch wieder losgelassen wird.
In den meisten Fällen ist changed die bessere Wahl.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
scotty
Beiträge: 676
Registriert: 28. Apr 2020 04:44
Answers: 0

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von scotty »

Vielen Dank, die Antwort habe ich gleich mal gespeichert. Leider hast du meine zweite Frage nicht beantwortet. Zu der habe ich nämlich noch eine Anschlussfrage: kannst du ein Buch über JavaScript mit Beispielen empfehlen?

Aber noch eine weitere Frage zum aktuellen Projekt. Da werden die Ergebnisse in Sekunden ermittelt und anschließend in einem String- Item abgelegt. Wenn das Ergebnis z. B. '1271' ist, siehst du dann eine Möglichkeit dieses zu konvertieren und im Format Stunden:Minuten:Sekunden anzuzeigen?
OH 3.4.5 im Docker auf Synology DS918+ mit USV, Reolink-RLC-511WA, Philips Hue, AVM Fritz!Box 6591C, Alexa, Logitech Harmony und diversen Shelly's

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

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von udo1toni »

Ups, sorry... ich wusste, da war noch ein zweiter Teil...

JSON -> JavaScript Object Notation. Es handelt sich also um eine Form, Objekte in Textform zu speichern. Dabei kann ein Objekt mehrere Eigenschaften haben, die dann gewöhnlich hierarchisch strukturiert sind. JSON definiert, wie diese Struktur aussehen muss. Das Ganze heißt zwar JavaScript ... ist aber dank der guten Lesbarkeit bei gleichzeitig geringem Overhead auch bei vielen anderen Programmiersprachen und allgemein als Datenformat sehr beliebt.
XML ist ja ähnlich aufgebaut, erfordert aber meist weitere externe Quellen, um es vollständig abzubilden. Der Overhead ist bei XML dank der TAGS höher.
JSON ist JSON und ohne weitere Beschreibung gültig. Gewöhnlich kann man auch ohne Dokumentation anhand eines JSON Beispiels direkt erkennen, wie man auf die Daten zugreifen muss.

JavaScript ist eine Programmiersprache. JavaScript ist dabei nicht Java, es ist tatsächlich weit von Java entfernt, wobei ich kein Programmierer bin und die Unterschiede nicht erklären kann. An vielen Stellen werden einem Dinge bekannt vorkommen, aber das ist bei Python und PHP auch so, und sogar C in seinen verschiedenen Ausprägungen kann Ähnlichkeiten aufweisen und hat doch so gar nichts mit JavaScript zu tun.

Literatur zu dem Thema habe ich keine zur Hand, sowohl für JavaScript als auch für Java gibt es so viel Literatur, dass man damit vermutlich nie fertig wird...

Bezüglich der Umrechnung in eine lesbare Zeit habe ich das bei mir schon mit Scripten gelöst, hier per JavaScript über transformation. Entsprechend die Datei /etc/openhab/transform/secinhms.js (SecondsInHourMinuteSecond - aber in der Kürze liegt die Würze):

Code: Alles auswählen

(function(seconds){
    var retval = "";
    var hours = Math.floor(seconds / 3600)
    seconds = seconds % 3600
    var minutes = Math.floor(seconds / 60)
    seconds = seconds % 60
    if (hours < 10)
        retval = retval + "0";
    retval = retval + hours + ":";
    if (minutes < 10)
        retval = retval + "0";
    retval = retval + minutes + ":";
    if (seconds < 10)
        retval = retval + "0";
    retval = retval + seconds;
    return retval;
})(input)
Die Funktion kann aus einer Rule heraus mit

Code: Alles auswählen

val strTime = transform("JS","secinhms.js",seconds)
angesprochen werden.

Der Code funktioniert folgendermaßen:
Zunächst wird ein leerer String retval angelegt. Nun werden die Stunden ermittelt, indem der Ganzzahlanteil des Ergebnisses der Division durch 3600 bestimmt wird. Also z.B. 10000 Sekunden ergibt 2, weil 3600 zweimal in die 10000 passt.
Nun werden die Sekunden auf den Rest reduziert, und zwar mit dem Modulo Operator %. Hier wird also der Rest der Division als Ergebnis behalten, also im Beispiel 2800. Das gleiche Spiel findet erneut statt, diesmal aber für die Minuten. Eine Minute hat 60 Sekunden, also kommt hier der Divisor 60 zum Einsatz. Das Ergebnis ist 46, weil die 60 eben 46 mal in die 2800 passt. Anschließend die Modulo Operation wie gehabt. Das Ergebnis ist hier 40.
Zum Abschluss wird der String zusammengebaut. Bei weniger als 10 Stunden wird eine 0 ergänzt. Dahinter folgt ein Doppelpunkt und eine führende 0 für die Minuten, falls es weniger als 10 Minuten sind. Wieder ein Doppelpunkt als Abgrenzung zu den Sekunden und ein letztes Mal die führende 0, falls benötigt. Als Ergebnis sateht dann im String, der zurückgegeben wird "02:46:40"
Auf Wunsch kann die führende 0 für die Stunden natürlich auch entfallen, dann lässt man die beiden Zeilen dafür einfach weg.

Man könnte die Sekunden aber auch in ein DateTime Item speichern (im korrekten Format natürlich...) und das Item auf die Anzeige von Stunden, Minuten und Sekunden konfigurieren. Allerdings wird die Anzeige dann maximal 23:59:59 erlauben, irgendwas ist ja immer...
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
scotty
Beiträge: 676
Registriert: 28. Apr 2020 04:44
Answers: 0

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von scotty »

Hallo Udo,

ich danke dir nochmals für die ausführlichen Informationen. Für Leute die (wie ich) mit Docker auf einer Synology arbeiten ist der Speicherort /docker/openhab/conf/transform/secinhms.js

Allerdings, der Aufruf aus einer Rule heraus funktioniert nicht. Liegt es vielleicht daran, dass es sich um String-Items handelt bzw. welcher Trigger muss verwendet werden?
OH 3.4.5 im Docker auf Synology DS918+ mit USV, Reolink-RLC-511WA, Philips Hue, AVM Fritz!Box 6591C, Alexa, Logitech Harmony und diversen Shelly's

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

Re: Hilfe bei der Gestaltung einer DSL Regel

Beitrag von udo1toni »

Innerhalb der Rule sollte der Sekundenwert als Zahl vorliegen. Dort sollte der Aufruf erfolgen. Der Rückgabewert ist die Dauer in der Schreibweise HH:MM:SS, und zwar als String. Der String muss natürlich in ein String Item übergaben werden.
Die Funktion wird in einer laufenden Rule verwendet, (die, in der die Zeit ausgerechnet wird -> Sekunden liegen als Zahl vor), der Trigger sollte für den Funktionsaufruf keine Rolle spielen.

Der Pfad in Docker ist der Pfad, den Du beim erzeugen des Containers festlegst, das ist komplett individuell. Ich gebe immer die Standard Pfade einer openHABian Installation an, weil die genau festgelegt sind. In allen anderen Systemen hängen die Pfade davon ab, was beim Installieren konfiguriert wurde.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten