IF Vergleich von zwei int Werten

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
iTob
Beiträge: 51
Registriert: 8. Mär 2020 19:58
Answers: 0

IF Vergleich von zwei int Werten

Beitrag von iTob »

Hallo,

ich nutze ein Item vom Bindig ntp für die aktuelle Uhrzeit Zeit_akt
mit

Code: Alles auswählen

var int h_akt = Zeit_akt.state.format("%1$tH")
weiße ich die Stunde einer Variable zu.

Endgültig will ich dann zwei solche Variablen vergleichen. Aktuell teste ich gerde mit:

Code: Alles auswählen

if (h_akt == 1){...}
Das bringt mir den Fehler:
An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_equals(int,int) on instance: null in raumeinfluss_mail
Ich habe das auch schon mit Variable string getestet, aber das bringt folgenden Fehler:
Script execution of rule with UID 'raumeinfluss_mail-3' failed: Unknown variable or command '==';
Warum funkioniert das nicht? Wo liegt hier mein Denkfehler? Kann mir jemand helfen?

Viele Grüße
Tobias

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

Re: IF Vergleich von zwei int Werten

Beitrag von udo1toni »

Ähm... Warum?
Nicht, dass man das nicht machen könnte... das ist nur eine unnötig komplizierte Herangehensweise.

Aber zunächst: Das ntp Binding liefert pro Thing zwei Channel, der eine vom Typ String, der andere vom Typ DateTime, die jeweils nur mit dem entsprechenden Itemtyp "kompatibel" sind.
Um mit format die Stunde zu extrahieren, könntest Du den String verwenden (nicht DateTime), allerdings hast Du danach immer noch "nur" einen String, auch wenn dieser String eine Zahl enthält.
Du müsstest also aus dem String erst ein Integer erzeugen, damit dieser Wert überhaupt in einer Integer variablen gespeichert werden kann, das wäre dann

Code: Alles auswählen

var Integer h_akt = Integer:ParseInt(Zeit_akt.state.toString.format("%1$tH"))
(ungetestet). Das .toString ist notwendig, damit .format überhaupt zur Verfügung steht.

Ein wenig einfacher wäre es, den Inhalt von DateTime nach Java Time zu konvertieren

Code: Alles auswählen

var Integer h_akt  = (Zeit_akt.state as DateTimeType).getZonedDateTime().getHour()
Voraussetzung ist hier, dass das Item auch vom Typ DateTime ist, nicht vom Typ String.

Die Frage ist allerdings, warum Du für die aktuelle Zeit nicht einfach die Systemzeit nutzt, welche - wenn man das System richtig aufsetzt - ebenfalls über ntp synchronisiert sein sollte. Dann sähe es so aus:

Code: Alles auswählen

var Integer h_akt = now.getHour()
Das ntp Binding ist nicht dazu gedacht, im System die Zeit zur Verfügung zu haben (allenfalls, wenn man eine Art Weltzeituhr baut und dort mit den Zeiten rechnen will...), sondern die Zeit auf dem openHAB Bus zur Verfügung zu haben, ohne dafür eine Rule bauen zu müssen. Ich nutze das z.B., um die Uhren in meinem knx System automatisch zu stellen (die Raumtemperaturregler haben eine Zeitanzeige).

Übrigens: int definiert ein Primitive, Integer definiert ein Objekt.
Das Primitive benötigt in etwa 100 mal länger für die Initialisierung und es gibt kaum legitime Gründe, das Primitive zu nutzen.
Also besser Integer, nicht int. :)
openHAB5.1.2 stable in einem Debian-Container (trixie, OpenJDK 21 headless runtime - LXC, 4 Kerne, 3 GByte RAM)
Hostsystem Proxmox VE 9.1.5 - AMD Ryzen 5 3600 6 Kerne, 12 Threads - 64 GByte RAM - ZFS Pools: Raid Z1, 3 x 20 TB HDD -> 40 TByte und Raid Z0-Mirrored 4 x 1 TByte NVMe -> 2 TByte

iTob
Beiträge: 51
Registriert: 8. Mär 2020 19:58
Answers: 0

Re: IF Vergleich von zwei int Werten

Beitrag von iTob »

Vielen Dank.
Mit diesen Tipps funktioniert es.

Wo finde ich denn zu diesen Befehlen eine Dokumentation?
Aktuell suche ich, wie ich mit now die komplette Zeit und Datum als String auslesen kann...
Ich war bei der Suche im Internet eben auf diese Möglichkeit über ntp gestoßen.
Wenn ich das richtig verstehe, kann ich mit if auch keine Strings vergleichen?

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

Re: IF Vergleich von zwei int Werten

Beitrag von udo1toni »

iTob hat geschrieben: 30. Jan 2026 19:01 Wenn ich das richtig verstehe, kann ich mit if auch keine Strings vergleichen?
Doch, warum sollte das nicht gehen?

if(expression) liefert true oder false. Du benötigst also lediglich die korrekte expression :)

Vorweg: Gerade Einsteiger tun sich oftmals leichter mit Blockly. Inzwischen gibt es auch kaum noch Dinge, die man nicht (irgendwie) in Blockly lösen könnte.
Und das Schöne: Du kannst Dir den Code anschließend anschauen. Blockly erzeugt ECMA JavaScript Scripte, Du kannst also bei Bedarf jederzeit Code Snippets mittels Blockly zusammenklicken.

Wieder zurück zur DSL:
Eine der wichtigen Eigenschaften der DSL ist, dass sie sehr picky ist, was Datentypen betrifft. es kann sein, dass Du mit einer unsauberen Definition der Datentypen davon kommst, dann hast Du Glück gehabt :) normalerweise wird sich die Rule Engine aber beschweren, weil Datentypen nicht zueinander passen.
Die Fehlermeldung aus dem ersten Posting:

Code: Alles auswählen

Could not invoke method: org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_equals(int,int) on instance: null
besagt, dass der Vergleich mit null nicht möglich war. Der Vergleich geschieht explizit zwischen zwei Integer Werten, aber mindestens einer davon (der erste... der zweite ist ja die Ziffer 1) ist null, also keine (Integer) Zahl. Das bedeutet, dass die Variable h_akt keine gültige Integer Zahl enthält.

Warum der Vergleich auf int,int? Weil Du die Variable als Integer definiert hast :)
Wenn Du zwei Strings miteinander vergleichst, wird DSL korrekt org.eclipse.xtext.xbase.lib.StringExtensions.operator_equals(string,string) verwenden.
Die offizielle Doku quillt quasi über vor lauter Beispielen, z.B. https://www.openhab.org/docs/configurat ... s-dsl.html oder https://www.openhab.org/docs/concepts/rules.html#dsl (man beachte das #DSL, Du kannst innerhalb der Seite umschalten, für welche Sprache die Code-Beispiele angezeigt werden). Das Dumme daran: es gibt speziell für die DSL kein echtes Tutorial, welches engmaschig alles erklärt. Ganz grob kannst Du Dich an Java orientieren, aber eben nur ganz grob.

Ein paar grundsätzliche Befehle:
if(expression) befehl [else befehl] Der Befehl nach if() wird ausgeführt, falls expression true ergibt, ansonsten wird der Befehl nach else ausgeführt. Der else-Teil ist optional. Es wird immer exakt ein Befehl ausgeführt. Allerdings kann man mehrere Befehle zu eine mBlock zusammenfassen, und zwar mit geschwungenen Klammern, also so:

Code: Alles auswählen

if(a == b) {
    befehl 1
    befehl 2
    befehl 3
} else {
    befehl 4
    befehl 5
}
Du kannst auch mehrere Optionen auswerten: if(expression1) Option1 else if(expression2) Option2 else if(expression3) Option3 else Option4
Oder Du nutzt stattdessen den switch() Befehl:

Code: Alles auswählen

switch(value) {
    case value1: Option1
    case value2: Option2
    case value3: Option3
    case value4: Option4
    default: Option5
}
Einschränkung hier: pro case hast Du immer einen Test auf Gleichheit (es sei denn, Du schreibst den kompletten Vergleich hin...)

Wenn Du einen Vergleich mit if() ausführst, muss der Ausdruck innerhalb der Klammer vom Typ Boolean sein, also entweder true oder false ergeben. Entsprechend braucht es Vergleichsoperatoren, als da wären:
a < b -> a Kleiner b
a > b -> a größer b
a <= b -> a kleiner oder gleich b
a >= b -> a größer oder gleich b
a == b -> a gleich b.
a != b -> a ungleich b
a === b -> a identisch b (Sonderfall, wird ausschließlich im Zusammenhanb mit Prüfung auf null verwendet)
a !== b -> a nicht identisch b (siehe voriger Vergleich)
!(a > b) a nicht größer b (eigentlich: nicht a größer b) (einfacher: a <= b, hier eher, um das NOT zu zeigen)
und es gibt noch ein paar speziellere Methoden, z.B. instanceof, das liefert ebenfalls true oder false, abhängig davon, ob ein Datum einem bestimmten Datentyp zugehörig ist:
a instanceof Number ist wahr, falls a eine Zahl enthält.
openHAB5.1.2 stable in einem Debian-Container (trixie, OpenJDK 21 headless runtime - LXC, 4 Kerne, 3 GByte RAM)
Hostsystem Proxmox VE 9.1.5 - AMD Ryzen 5 3600 6 Kerne, 12 Threads - 64 GByte RAM - ZFS Pools: Raid Z1, 3 x 20 TB HDD -> 40 TByte und Raid Z0-Mirrored 4 x 1 TByte NVMe -> 2 TByte

Antworten