Was, zum Henker, soll hieran falsch sein ?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Benutzeravatar
guinnes
Beiträge: 146
Registriert: 21. Apr 2020 19:46
Answers: 0

Was, zum Henker, soll hieran falsch sein ?

Beitrag von guinnes »

Moin
Ich habe ien Rule, mit der ich einen Solar-Akku similieren will :

Code: Alles auswählen

    val Einspeis_Geld = -7.152              // Einspeisevergütung
    val Bezug_Geld = 22.65 * 1.19           // Preis pro kw/h

rule "Virtual Battery2 SaveMoney"
    when
        Item Virt_Batt2_Level changed                                   // Wattstunden !!
    then {
        var Einspeis_Delta = (Virt_Batt1_Einspeis_Ist.state as Number).floatValue - (Virt_Batt2_Einspeis.state as Number).floatValue
        var Bezug_Delta = (Virt_Batt1_Use_Ist.state as Number).floatValue - (Virt_Batt2_Use.state as Number).floatValue
        Einspeis_Delta = Einspeis_Delta * Einspeis_Geld / 100000        // € * kwh
        Bezug_Delta = Bezug_Delta * Bezug_Geld / 100000                // € * kwh
        logInfo("Batterie", "Bezug_Delta    = {}",Bezug_Delta)
        logInfo("Batterie", "Einspeis_Delta = {}",Einspeis_Delta)
        Virt_Batt2_Save.postUpdate(Bezug_Delta)
        Virt_Batt2_Save_Einspeis.postUpdate(Einspeis_Delta)
        var float Delta = Bezug_Delta - Einspeis_Delta
        logInfo("Batterie", "Delta = {}",Delta)
    }
end
Bei der vorletzten Zeile gibts einen Fehler-Eintrag im Log-File :
2022-05-30 16:53:42.855 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Virtual Battery2 SaveMoney': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_minus(float,float) on instance: null
Ich habe versucht :
mit einen normalen Variablen
mit einer Typisierten Variablen
mit -=
Die beiden Zeilen stehen nur deshalb am Ende, weil ich den Rest nicht stören will, ich habe natürlich auch versucht, das Ergebniss in ein Item zu schreiben, ohne Erfolg
Hat da jemand eine Idee ?
Glückauf
guinnes

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

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von udo1toni »

Grundsätzlich ist es riskant, mit Items zu rechnen ohne vorher auf gültige Werte zu prüfen, auch wenn Dir der Code dadurch länglich erscheinen sollte.
Auch etwas lockerere Formatierung hilft beim Blick auf den Code.

float als Datentyp ist gewöhnlich ungünstig. Nimm besser Number.
Wie sehen die konkret geloggten Zeilen vor dem Fehler aus?

Code: Alles auswählen

rule "Virtual Battery2 SaveMoney"
when
    Item Virt_Batt2_Level changed                                   // Wattstunden !!
then
    if(!(Virt_Batt1_Einspeis_Ist.state instanceof Number)) {
        logWarn("Batterie","Virt_Batt1_Einspeis_Ist liefert keinen gültigen Wert! {}", Virt_Batt1_Einspeis_Ist.state)
        return;
    }
    if(!(Virt_Batt2_Einspeis.state instanceof Number)) {
        logWarn("Batterie","Virt_Batt2_Einspeis liefert keinen gültigen Wert! {}", Virt_Batt2_Einspeis.state)
        return;
    }
    if(!(Virt_Batt1_Use_Ist.state instanceof Number)) {
        logWarn("Batterie","Virt_Batt1_Use_Ist liefert keinen gültigen Wert! {}", Virt_Batt1_Use_Ist.state)
        return;
    }
    if(!(Virt_Batt2_Use.state instanceof Number)) {
        logWarn("Batterie","Virt_Batt2_Use liefert keinen gültigen Wert! {}", Virt_Batt2_Use.state)
        return;
    }
    if(!(Einspeis_Geld instanceof Number)) {
        logWarn("Batterie","Einspeis_Geld liefert keinen gültigen Wert! {}", Einspeis_Geld)
        return;
    }
    if(!(Bezug_Geld instanceof Number)) {
        logWarn("Batterie","Bezug_Geld liefert keinen gültigen Wert! {}", Bezug_Geld)
        return;
    }

    var Number Einspeis_Delta = (Virt_Batt1_Einspeis_Ist.state as Number).floatValue - (Virt_Batt2_Einspeis.state as Number).floatValue
    var Number Bezug_Delta    = (Virt_Batt1_Use_Ist.state      as Number).floatValue - (Virt_Batt2_Use.state      as Number).floatValue

    Einspeis_Delta = Einspeis_Delta * Einspeis_Geld / 100000        // € * kwh
    Bezug_Delta    = Bezug_Delta    * Bezug_Geld    / 100000        // € * kwh

    logInfo("Batterie", "Bezug_Delta    = {}",Bezug_Delta)
    logInfo("Batterie", "Einspeis_Delta = {}",Einspeis_Delta)

    Virt_Batt2_Save.postUpdate(Bezug_Delta)
    Virt_Batt2_Save_Einspeis.postUpdate(Einspeis_Delta)

    var Number Delta = Bezug_Delta - Einspeis_Delta
    logInfo("Batterie", "Delta          = {}",Delta)
end
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
guinnes
Beiträge: 146
Registriert: 21. Apr 2020 19:46
Answers: 0

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von guinnes »

Moin, Udo1toni
Erst mal Danke für deine Antwort.
Die letzten Zeilen im Log-File vor dem Fehler sind :
2022-05-30 17:21:00.642 [INFO ] [ipse.smarthome.model.script.Batterie] - Bezug_Delta = 9518.5
2022-05-30 17:21:00.649 [INFO ] [ipse.smarthome.model.script.Batterie] - Einspeis_Delta= 14315.0
Es ist sicherlich manchmal sinnvoll, Items auf ihren Typ zu prüfen, aber wohl nur in Unterprogrammen. Wenn ich konkrete Items angebe, weiss ich den Typen immer.
Aber ich habe vo 20 Minuten die Lösung gefunden :
Die globalen Variablen

Code: Alles auswählen

    val Einspeis_Geld = -7.152              // Einspeisevergütung
    val Bezug_Geld = 22.65 * 1.19           // Preis pro kw/h
sind der Grund !! Wenn ich die innerhalb der Rule deklariere bzw nur die Werte benutze, gehts. Leider gibts kein const.
Jetzt hab ich die Variablen in ein Unterprogramm gepackt und alles ist gut :

Code: Alles auswählen

val Calc_Virtual_Battery  =       
[ NumberItem IstBezug,              // Item in dem der Bezug mit Batterie steht
  NumberItem IstEinspeisung,        // Item in dem die Einspeisung mit Batterie steht
  NumberItem MinusEinspeisung,      // Item in das die Mindereinnahmen durch die Batterie geschrieben wird
  NumberItem PlusBezug,             // Item in das die Ersparniss durch geringeren Bezug geschrieben wird
  NumberItem GesSpar                // Item in das die Gesammte Ersparniss geschrieben wird
  |
    val Einspeis_Geld = -7.152              // Einspeisevergütung
    val Bezug_Geld = 22.65 * 1.19           // Preis pro kw/h
    var Einspeis_Delta = ((Virt_Batt1_Einspeis_Ist.state as Number).floatValue - (IstEinspeisung.state as Number).floatValue) * Einspeis_Geld / 100000
    var Bezug_Delta = ((Virt_Batt1_Use_Ist.state as Number).floatValue - (IstBezug.state as Number).floatValue) * Bezug_Geld / 100000
    PlusBezug.postUpdate(Bezug_Delta)
    MinusEinspeisung.postUpdate(Einspeis_Delta)
    GesSpar.postUpdate(Bezug_Delta + Einspeis_Delta)
]
Vielen Dank nochmal für deine Antwort und bis demnächst :D
Glückauf
guinnes

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

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von udo1toni »

guinnes hat geschrieben: 30. Mai 2022 21:40Leider gibts kein const.
Was meinst Du damit? Die Definition von Konstanten? val ist nichts anderes als eine Konstante, nach der Definition darf der Wert nicht mehr geändert werden. var ist eine Variable, die nach der Definition beliebig neue Werte zugewiesen bekommen darf (abhängig vom zuerst zugewiesenen Datentyp, bzw. abhängig vom angegebenen Datentyp)

Ich denke, Du hast den Grund der Prüfung zu Beginn der Rule nicht erfasst. In dem Moment, wo eines Deiner Items als Status keine gültige Zahl enthält, bekommst Du eine NullPointer Exception. Dabei ist es vollkommen egal, wo die Variablen oder Konstanten definiert sind. Auch das Auslagern in eine Funktion hilft hier nicht, null ist null und kann nicht für Rechenoperationen herangezogen werden.

Du lässt Deine Rule auf ein Change eines Items triggern, welches dann in der Rule selbst überhaupt keine Rolle spielt. Das ist zumindest ungewöhnlich, aber ich vermute, dass die Items alle in gewisser Weise zusammenhängen.
Variablen können lokal oder global definiert werden. Einzige Voraussetzung ist, dass global definierte Variablen vor der ersten Rule in der Datei definiert sind. Das wäre noch ein möglicher Fehler in dem Zusammenhang.
Eine Prüfung auf sinnvolle Werte in den globalen Variablen ist nicht so wichtig, der Vollständigkeit halber habe ich dies aber mit gelistet. Der Unterschied besteht hier darin, dass Du weißt, dass eine Variable immer einen gültigen Wert enthält, im Unterschied zum Itemstatus, der immer auch den Wert NULL oder UNDEV annehmen kann. Beide Werte lassen Deine Rule abrupt enden, wenn Du keine Vorsorge triffst.

Solange Werte fix verwendet werden, (also als Konstanten) kannst Du den Wert leicht per ternärem Operator setzen:

Code: Alles auswählen

val Number nWert = if(MyItem.state instanceof Number) (MyItem.state as Number).floatValue else 35.7
Oder Du nutzt statt einer Konstanten eine Variable:

Code: Alles auswählen

var Number nWert = 35.7 
if(MyItem.state instanceof Number) 
    nWert = (MyItem.state as Number).floatValue
Beide Arten sind äquivalent, aber nur im ersten Fall kannst Du eine Konstante definieren.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
guinnes
Beiträge: 146
Registriert: 21. Apr 2020 19:46
Answers: 0

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von guinnes »

udo1toni hat geschrieben: 30. Mai 2022 22:31 Was meinst Du damit? Die Definition von Konstanten? val ist nichts anderes als eine Konstante, nach der Definition darf der Wert nicht mehr geändert werden.
Das ist nur theoretisch der Fall. In meire Rule für das Openweathermap-Binding benutze ich val auch als Variable, weil var nicht außerhalb einer For Each-Schleife definiert werden darf. Benutze ich dagegen val kommt zwar beim registrieren der Rule eine Meldung, aber funktioneiern tuts trotzdem
Ich denke, Du hast den Grund der Prüfung zu Beginn der Rule nicht erfasst. In dem Moment, wo eines Deiner Items als Status keine gültige Zahl enthält, bekommst Du eine NullPointer Exception. Dabei ist es vollkommen egal, wo die Variablen oder Konstanten definiert sind. Auch das Auslagern in eine Funktion hilft hier nicht, null ist null und kann nicht für Rechenoperationen herangezogen werden.
Mir ist schon klar, daß man das machen soll, wenn die Möglichkeit besteht, daß ein Item NULL sein kann. In meinem Fall sind alle Items sinnvoll initialisiert ( bei Starten der Batterie-Simulation )
Variablen können lokal oder global definiert werden. Einzige Voraussetzung ist, dass global definierte Variablen vor der ersten Rule in der Datei definiert sind. Das wäre noch ein möglicher Fehler in dem Zusammenhang.
Eindeutig ist die Definition außerhalb der Rules der Grund für den Fehler. Das hängt wahrscheinlich damit zusammen, daß jede Rule in einem eigenen Thread läuft und die Thread-Verwaltung dafür sorgt, daß auf eine Konstante nur mit einem Thread zugegriffen werden darf. Warum der 2. Thread nicht wartet, ist mir nicht klar
..im Unterschied zum Itemstatus, der immer auch den Wert NULL oder UNDEV annehmen kann. Beide Werte lassen Deine Rule abrupt enden, wenn Du keine Vorsorge triffst.
Ich sehe da keine großen Unterschied : Auf der einen Seite treibe ich Aufwand und breche die Funktion im Fehlerfall selber ab, auf der anderen Seite bricht der Interpreter die Funktion ab und das ohne mein Zutun. Ist aber schon klar, sauberer ist deine Lösung aber mit einem viel zu hohem Aufwand
Glückauf
guinnes

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

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von udo1toni »

guinnes hat geschrieben: 31. Mai 2022 11:31 weil var nicht außerhalb einer For Each-Schleife definiert werden darf
Nein. Du kannst eine Variable oder Konstante beliebig im Code definieren. Außerhalb einer Rule (ganz oben in der Datei) gilt die Definition in allen Rules dieser Datei. Innerhalb einer Rule (unmittelbar hinter dem then) gilt die Definition nur für die Rule selbst, und nur, solange die Rule noch ausgeführt wird. Innerhalb eines Blocks (egal ob durch {} oder durch [] gebildet) gilt die Definition auch nur innerhalb dieses Blocks. Wenn Du hier andere Erfahrungen machst, poste bitte mal Beispielcode.
guinnes hat geschrieben: 31. Mai 2022 11:31 In meinem Fall sind alle Items sinnvoll initialisiert
Ja, solange es sich um eine Simulation handelt, wo also Items ausschließlich über eigenen Programmcode beeinflusst werden, ist das korrekt, nicht aber, sobald auch nur eines der beteiligten Items über ein Binding gefüllt wird. Dann entzieht sich der Inhalt des Items Deiner Kontrolle und Du kannst nur noch vermuten, dass "eigentlich" ein gültiger Wert vorliegen müsste.

openHAB ist übrigens keine Simulationssoftware. Nutze bitte keinen Hammer, um eine Schraube in ein Stück Holz zu bekommen.
guinnes hat geschrieben: 31. Mai 2022 11:31 Eindeutig ist die Definition außerhalb der Rules der Grund für den Fehler. Das hängt wahrscheinlich damit zusammen, daß jede Rule in einem eigenen Thread läuft und die Thread-Verwaltung dafür sorgt, daß auf eine Konstante nur mit einem Thread zugegriffen werden darf.
Nein! Wenn die Konstanten und Variablen zu Beginn der Datei definiert sind, kannst Du ohne jegliche Einschränkungen mit jeder Rule in dieser Datei auf die Konstanten und Variablen zugreifen. Ist das nicht der Fall, dann lösche bitte openHAB vollständig und installiere es neu, denn dann hast Du ein kaputtes System.
guinnes hat geschrieben: 31. Mai 2022 11:31 Auf der einen Seite treibe ich Aufwand und breche die Funktion im Fehlerfall selber ab, auf der anderen Seite bricht der Interpreter die Funktion ab und das ohne mein Zutun. Ist aber schon klar, sauberer ist deine Lösung aber mit einem viel zu hohem Aufwand
Was ist denn daran hoher Aufwand? Du prüfst jeden Wert auf Korrektheit und kannst sicher sein, dass die Rule anschließend funktioniert.
Oder Du scheust den Aufwand, die Rule funktioniert nicht und Du weißt nach zwei Tagen immer noch nicht, woran es letztlich liegt.
Ich nutze globale Variablen und Konstanten in großer Menge und habe weder Probleme mit parallelem Zugriff noch mit fehlerhaften Berechnungen. Ich habe im Fehlerfall auch keine NullPointer Exception über 60 Zeilen oder mehr, mit der ich (bis auf Teile der ersten und zweiten sowie letzten Zeile genau gar nichts anfangen kann), sondern eine klare Meldung, die mir verrät, warum die Rule nicht ausgeführt wird.
Du musst solche Mechansimen auch nicht unbedingt in jede Rule einbauen, aber wenn es Probleme gibt, ist es sinnvoll, die Rule, welche Probleme bereitet so aufzubauen, dass der Fehler möglichst präzise eingegrenzt werden kann. Um mehr geht es nicht.

By the way: Welche openHAB Version nutzt Du?
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
guinnes
Beiträge: 146
Registriert: 21. Apr 2020 19:46
Answers: 0

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von guinnes »

udo1toni hat geschrieben: 31. Mai 2022 19:29 openHAB ist übrigens keine Simulationssoftware. Nutze bitte keinen Hammer, um eine Schraube in ein Stück Holz zu bekommen.
Hast du eine bessere Idee wie ich eine Solarbatterie simulieren kann ? Dann nur her damit. Im Openhab stehen mir die nötigen Messwerte sowieso zur Verfügung ( Einspeise - bzw Bezugs-Zähler ). Bei jeden anderen System müßte ich irgendwie an diese Werte kommen.
By the way: Welche openHAB Version nutzt Du?
Produktiv : 2.5.12 Test : 3.3.0 Build 2893
Zu den anderen Sachen werde ich dir heute abend Beispiele posten
Glückauf
guinnes

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

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von udo1toni »

guinnes hat geschrieben: 1. Jun 2022 10:41
udo1toni hat geschrieben: 31. Mai 2022 19:29 openHAB ist übrigens keine Simulationssoftware. Nutze bitte keinen Hammer, um eine Schraube in ein Stück Holz zu bekommen.
Hast du eine bessere Idee wie ich eine Solarbatterie simulieren kann ? Dann nur her damit. Im Openhab stehen mir die nötigen Messwerte sowieso zur Verfügung ( Einspeise - bzw Bezugs-Zähler ). Bei jeden anderen System müßte ich irgendwie an diese Werte kommen.
Ah. Vielleicht habe ich Dich da falsch verstanden. Ich ging davon aus, dass alle Messwerte ebenfalls simuliert sind. Du meinst mit Simulation aber vermutlich eher, dass Du aus den echten Messwerten errechnen willst, was Du in einen Speicher einspeisen kannst? evtl. um Rückschlüsse zu ziehen, wie groß der Akku sinnvollerweise werden sollte? Simulation ist gemeinhin etwas komplexer... ;)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
guinnes
Beiträge: 146
Registriert: 21. Apr 2020 19:46
Answers: 0

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von guinnes »

udo1toni hat geschrieben: 1. Jun 2022 13:01 Ah. Vielleicht habe ich Dich da falsch verstanden. Ich ging davon aus, dass alle Messwerte ebenfalls simuliert sind. Du meinst mit Simulation aber vermutlich eher, dass Du aus den echten Messwerten errechnen willst, was Du in einen Speicher einspeisen kannst? evtl. um Rückschlüsse zu ziehen, wie groß der Akku sinnvollerweise werden sollte? Simulation ist gemeinhin etwas komplexer... ;)
So siehts aus
Nein! Wenn die Konstanten und Variablen zu Beginn der Datei definiert sind, kannst Du ohne jegliche Einschränkungen mit jeder Rule in dieser Datei auf die Konstanten und Variablen zugreifen. Ist das nicht der Fall, dann lösche bitte openHAB vollständig und installiere es neu, denn dann hast Du ein kaputtes System.
Ich habs jetzt aus 3 Systemsn probiert :
2 Unabhängige 2.5.12 unter Windows und auf meinen Raspberry. Das Verhalten ist gleich
Du Kannst mir sichelich sagen, warum diese 5! Rules alle auf die Bretter gehen, obwohl es keinen logischen Grud dafür gibt :
Die Rules :

Code: Alles auswählen

var Timer DemoTimer = null

val Inc = 0.5
val Sub = 0.1

var Calc_Demo1  =       
[ NumberItem DasItem
  |
  var Value = (DasItem.state as Number).floatValue
  logInfo("test", "Value Inc 3 = {}",Value)
  Value = Value + Inc
  logInfo("test", "Value Inc 3 nach + = {}",Value)
  Value = Value * Sub
  logInfo("test", "Value Inc 3 nach + = {}",Value)
  DasItem.postUpdate(Value)
]

var Calc_Demo2  =       
[ NumberItem DasItem
  |
  val Inc1 = 0.5
  val Sub1 = 0.1
  var Value = (DasItem.state as Number).floatValue
  logInfo("test", "Value Inc 4 = {}",Value)
  Value = Value + Inc1
  logInfo("test", "Value Inc 4 nach + = {}",Value)
  Value = Value * Sub1
  logInfo("test", "Value Inc 4 nach + = {}",Value)
  DasItem.postUpdate(Value)
]

var Calc_Demo3  =       
[ NumberItem DasItem
  |
  var Value = (DasItem.state as Number).floatValue
  logInfo("test", "Value Inc 5 = {}",Value)
  Value = Value + 0.5
  logInfo("test", "Value Inc 5 nach + = {}",Value)
  Value = Value * 0.1
  logInfo("test", "Value Inc 5 nach + = {}",Value)
  DasItem.postUpdate(Value)
]

rule "Demo Start"
when
    Item Start_Demo received command ON
then{
  logInfo("test", "Trigger")
  Item1.postUpdate(0)
  Item2.postUpdate(0)
  Item3.postUpdate(0)
  Item4.postUpdate(0)
  Item5.postUpdate(0)
  if(DemoTimer === null) {
    DemoTimer = createTimer(now.plusSeconds(1), [|
    Start_Demo.sendCommand(OFF)
    DemoTimer = null
  ])}
  }
end
   
rule "Demo Inc 1"
when
    Time cron "0 * * * * ?" 
then
  var Value = (Item1.state as Number).floatValue
  logInfo("test", "Value Inc 1 = {}",Value)
  Value = Value + Inc
  logInfo("test", "Value Inc 1 nach + = {}",Value)
  Value = Value * Sub
  logInfo("test", "Value Inc 1 nach + = {}",Value)
  Item1.postUpdate(Value)
end

rule "Demo Inc 2"
when
    Time cron "0 * * * * ?" 
then
  val Inc1 = 0.5
  val Sub1 = 0.1
  var Value = (Item2.state as Number).floatValue
  logInfo("test", "Value Inc 2 = {}",Value)
  Value = Value + Inc1
  logInfo("test", "Value Inc 2 nach + = {}",Value)
  Value = Value * Sub1
  logInfo("test", "Value Inc 2 nach - = {}",Value)
  Item2.postUpdate(Value)
end

rule "Demo Inc 3"
when
    Time cron "0 * * * * ?" 
then
    Calc_Demo1.apply(Item3)
end

rule "Demo Inc 4"
when
    Time cron "0 * * * * ?" 
then
    Calc_Demo2.apply(Item4)
end

rule "Demo Inc 5"
when
    Time cron "0 * * * * ?" 
then
    Calc_Demo3.apply(Item5)
end
Die dazugehörigen Items :

Code: Alles auswählen

Number          Item1                        "Test Inc 1 [%.1f]"
Number          Item2                        "Test Inc 2 [%.1f]"
Number          Item3                        "Test Inc 3 [%.1f]"
Number          Item4                        "Test Inc 4 [%.1f]"
Number          Item5                        "Test Inc 5 [%.1f]"
Switch          Start_Demo                   "Demo Starten"
und die Sitemap :

Code: Alles auswählen

sitemap Demo label="Demo" {
    Frame label="Test" {
        Switch item=Start_Demo
        Text item=Item1
        Text item=Item2
        Text item=Item3
        Text item=Item4
        Text item=Item5
    }
}
es gibt folgende Log-Einträge :

Code: Alles auswählen

2022-06-01 19:18:00.002 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 4 = 0.0
2022-06-01 19:18:00.003 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 4 nach + = 0.5
2022-06-01 19:18:00.003 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Demo Inc 4': Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_multiply(float,double) on instance: null
2022-06-01 19:18:00.006 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 1 = 0.0
2022-06-01 19:18:00.007 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 1 nach + = 0.5
2022-06-01 19:18:00.007 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Demo Inc 1': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_multiply(float,double) on instance: null
2022-06-01 19:18:00.009 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 3 = 0.0
2022-06-01 19:18:00.011 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Demo Inc 3': Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_plus(float,double) on instance: null
2022-06-01 19:18:00.012 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 5 = 0.0
2022-06-01 19:18:00.013 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 5 nach + = 0.5
2022-06-01 19:18:00.014 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Demo Inc 5': Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_multiply(float,double) on instance: null
2022-06-01 19:18:00.035 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 2 = 0.0
2022-06-01 19:18:00.036 [INFO ] [.eclipse.smarthome.model.script.test] - Value Inc 2 nach + = 0.5
2022-06-01 19:18:00.037 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Demo Inc 2': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.FloatExtensions.operator_multiply(float,double) on instance: null
Ich bin ratlos, werde das aber noch auf Openhab 3.3.0 probieren
Glückauf
guinnes

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

Re: Was, zum Henker, soll hieran falsch sein ?

Beitrag von udo1toni »

Das Problem ist ziemlich sicher, dass die Variablen und Konstanten nicht typisiert sind. +

Der Code ist (das wirst Du sicher selbst erkennen) fürchterlich.
Funktionen sind in der DSL nicht gut unterstützt, und ja, man kann Lambdas dazu missbrauchen, muss dann aber damit leben, dass oftmals sehr seltsame Dinge passieren.

Die Timer Variable ist beispielsweise global definiert, und Timer funktionieren absolut zuverlässig (im möglichen Rahmen, d.h. die *.rules Datei darf nicht zwischendrin neu geladen werden und bevor die Timer Variable mit einem Timer gefüllt wird (bzw. mit dem Zeiger auf den Scheduler Eintrag) muss ein evtl. vorhandener Timer immer gecancelt werden, also so:

Code: Alles auswählen

//vor der ersten Rule
var Timer tMyTimer = null // Initialisierung wenn die Datei neu geladen wird

rule " meine Timer Rule"
when
   Item Blah received command
then
    tMyTimer?.cancel  // Falls ein Timer läuft bbrechen
    if(receivedCommand==ON)
        tMyTimer = createTimer(now.plusSeconde(1),[|
            // tu was
            tMyTimer = null
        ])
end
funktioniert immer.

Code: Alles auswählen

val Integer iMyConst = 51

rule "nutze globale Konstante"
when
   Item Blah received command
then
    logInfo("const","iMyConst = {}; x 5 = {}",iMyConst,iMyConst*5)
end
Geht natürlich auch mit Float Werten oder auch mit Number, das wäre etwas allgemeiner. Wenn die Werte veränderlich sein sollen, tauscht man val mit var. Typisierung ist nicht immer notwendig, manchmal aber schon. Willst Du z.B. einen Unix Zeitstempel speichern, so musst Du zwingend Long oder long verwenden (wobei ich immer das Objekt (groß geschrieben) bevorzugen würde, denn Primitives brauchen wesentlich länger beim Initialisieren.

In der Fehlermeldung siehst Du ja, dass er immer versucht, float mit double zu multiplizieren, da bin ich mir ziemlich sicher, dass das nicht automatisch geht.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten