Jain. Prinzipiell geht das schon, aber sicher ist es halt nicht.
Und wo wir bei "Um die Ecke" sind, das trifft ja auch auf Deine Rule zu
Dieses Konstrukt:
(typeof zaehleraus == 'number' ? zaehleraus : 0) beispielsweise ist in dem Kontext komplett unsinnig,
zaehleraus ist immer vom Typ Number, weil Du es beim Eintritt in die Rule so definierst und vorbelegst. Die Rule wird niemals verlassen und wieder betreten, also ist die Variable beim Eintritt immer 0 und damit eine gültige Zahl.
Das Konstrukt
123 == 123 ist auch lustig

schreib einfach
true hin und gut.
Also, abgesehen davon, dass man das so halt nicht macht
Auch wenn Du "kein Java sprichst" hier mal das Gegenstück dazu:
Code: Alles auswählen
var Timer tPool = null
val Long lPool = 1500000000 // 1,5 Sekunden als Nanosekunden
var Number nHysterese = 10 // default Wert falls Hysterese nicht gelesen werden kann
rule "Pumpe aus Zähler"
when
// der Rule Trigger
then
if(tPool !== null) // falls Timer schon existiert
return; // Abbruch
if(hysteresisCounterPoolpumpe.state instanceof Number)
nHysterese = hysteresisCounterPoolpumpe.state as Number
tPool = createTimer(now.plusNanos(lPool),[
var Integer nAus = if(Poolpumpenzaehler.state instanceof Number) (Poolpumpenzaehler.state as Number).intValue else 0
var Number nVerbrauch = if(Shelly3EM_KumulierterVerbrauch.state instanceof Number) (Shelly3EM_KumulierterVerbrauch.state as Number) else 0
if(nVerbrauch <-400)
nAus -= 2
else if(nVerbrauch <-300)
nAus -= 1
else if(nVerbrauch > 300)
nAus += 3
else if(nVerbrauch > 100)
nAus += 2
else if(nVerbrauch > 0)
nAus += 1
if(nAus > nHysterese)
5Poolpumpe_Betrieb.sendCommand(OFF)
if(Math::abs(nAus) > nHysterese) {
nAus = 0
tPool = null
} else
tPool.reschedule(now.plusNanos(lPool))
Poolpumpenzaehler.postUpdate(nAus)
])
end
Wenn der Messzyklus zwei Sekunden betrüge, könnte man auf die Nanos verzichten und stattdessen plusSeconds(2) schreiben
Gleich zu Anfang kannst Du aber sehen, dass die Rule abgebrochen wird, sobald ein laufender Timer entdeckt wird.
Leider fehlt in Deinem Code der Trigger, welcher eigentlich mit ausgegeben wird.
Die Rule selbst macht nichts weiter, als zu prüfen, ob der Timer existiert, und falls das nicht der Fall ist, die aktuell eingestellte Hysterese auszulesen und den Timer anzulegen. Danach ist die Rule beendet.
Ab sofort existiert im Scheduler der Timer, welcher nach 1,5 Sekunden das erste Mal den Code ausführen lässt. Das ist der Block zwischen [| und ]
Im großen und ganzen entspricht der Code dem von Blockly, mit ein paar kleineren Unterschieden.
Zunächst liest der Code den aktuellen Zählerstand jeweils vom Item ein, genau wie den aktuellen Verbrauch. Beides wird in einer lokalen Variable gespeichert. Sollte gerade kein gültiger Wert geliefert werden, so wird ein Default Wert genommen.
Der Vergleichsblock ist ähnlich Deinem Block aufgebaut, allerdings gibt es da in Deinem Code evtl. einen Fehler. Du nutzt immer nur if(), was bedeutet, dass z.B. bei einem Wert über 300 drei Bedingungen zutreffen, denn der Wert ist größer als 0, größer als 100 und größer als 300, es wird also bei einem einzigen Durchlauf 6 hinzugezählt, nicht etwa 3.
Kurzer Einschub:
Man könnte hier übrigens auch mit einer SCALE Transformation arbeiten, das sähe dann im Code so aus:
Code: Alles auswählen
nAus += Integer::parseInt(transform("SCALE","pumpe.scale",nVerbrauch))
Dafür steht dann aber im Code nicht, wie der Wert zustande kommt. Die Scale Transformation solltest Du auch aus Blockly heraus nutzen können.
Ich bin mir nicht zu 100% sicher, ob der Umweg über Integer::parseInt() notwendig ist, aber immerhin kann Scale Text liefern, also wird auch eine Zahl vermutlich eher als String herauskommen.
Die Datei
pumpe.scale sähe dann so aus:
Die Datei wird immer von oben nach unten abgearbeitet, das erste Match wird genommen. Man muss also entweder genauere wertebereiche angeben oder auf die Reihenfolge der Einträge achten (so wie auch in meiner Rule)
Zurück zur Rule:
Das += ist eine fiese Abkürzung

ich könnte natürlich ebensogut nAus = nAus + 1 schreiben, aber so sieht es halt viel schicker aus
Wenn der Schwellwert überschritten wurde, wird die Pumpe abgeschaltet.
Liegt der Absolutwert des Zählers über dem Schwellwert so wird der Timer nicht mehr weiter ausgeführt, ansonsten wird der Timer erneut eingeplant. Erst nach diesem Schritt wird noch der aktuelle Zählerstand ins Item geschrieben. Damit ist der Code fertig ausgeführt.
Je nachdem, ob im vorletzten Schritt der Timer neu geplant wurde oder der Zähler auf 0 gesetzt und der Timer genullt wurde wird nach 1.5 Sekunden der Scheduler den Code erneut ausführen lassen.
Das Einschalten der Pumpe kann mit sehr hoher Wahrscheinlichkeit genauso abgewickelt werden. Eventuell geht das sogar aus derselben Rule heraus, je nach Trigger...