NEWS
Trigger: Wenn Wert länger gehalten wird
-
Moin,
ich baue mir gerade mehrere Scripte die diverse nicht-smarte Haushaltsgeräte anhand vom Energieverbraucht überwachen (Spül-/Waschmaschine fertig, Ofen vorgeheizt, TV auf Standby etc.).Problem ist, dass die Leistung logischerweise immer ziemlich hin-, und herspringt. Bei einigen Geräten ist das so kurz, dass ich das über "letzter Wert" abfangen konnte. Oft klappt das aber nicht. So ist z.B. die Spülmaschine fertig, wenn die Leistung für unter 5Watt sinkt. Zwischendurch springt sie aber auch für zwei bis drei Sekunden darunter, so dass ich einen Trigger brauche, der checkt, ob der Wert für ca 10s unter 5 Watt sinkt...
Hat jemand da zufällig da eine schicke, generische Lösung? Vorzugsweise, ohne, dass ich noch für jedes Gerät irgendwo einen State im Objektbaum zwischenspeichern muss.
Momentan schwebt mir da eine kleine, rekursive JS-Funktion vor, mache mir aber Sorgen um die Performance, da ich das häufiger brauche.
Oder gibt es sowas schon ioB und ich habe es nur übersehen?
Ist sowas angedacht, in das Scripting zu übernehmen?EDIT:
Lösung gibt es hier:
https://forum.iobroker.net/topic/37141/trigger-wenn-wert-länger-gehalten-wird/6 -
@D-VE es gibt zwei Möglichkeiten
- nach ein paar Sekunden/Minuten noch mal den Wert überprüfen und erst dann Meldung geben wenn er immer noch unter der Schwelle ist
- einen gleitenden Mittelwert über die letzten x Messungen berechnen und die Meldung erst dann ausgeben wenn dieser unter den Schwellwert fällt
-
@D-VE sagte:
einen Trigger brauche, der checkt, ob der Wert für ca 10s unter 5 Watt sinkt...
-
@Homoran said in Trigger: Wenn Wert länger gehalten wird:
@D-VE es gibt zwei Möglichkeiten
- nach ein paar Sekunden/Minuten noch mal den Wert überprüfen und erst dann Meldung geben wenn er immer noch unter der Schwelle ist
- einen gleitenden Mittelwert über die letzten x Messungen berechnen und die Meldung erst dann ausgeben wenn dieser unter den Schwellwert fällt
Kann ich den dazu wenigstens Variablen nehmen? Bleiben die persistent innerhalb der Blockly-Scripte, oder geht das nur mit States im Objektbaum?
-
@D-VE sagte in Trigger: Wenn Wert länger gehalten wird:
Kann ich den dazu wenigstens Variablen nehmen?
natürlich!
@D-VE sagte in Trigger: Wenn Wert länger gehalten wird:
Bleiben die persistent innerhalb der Blockly-Scripte
nur in dem jeweiligen Skript
States als "Systemvariable" nutzen geht auch, ergibt IMHO aber keinen Sinn, da du wahrscheinlich nicht auf die gleichen Werte von mehreren Skripten zugreifen willst/musst
-
Ich hab mal eine kleine Methode implementiert, die das realisiert.
Einfach als Globale JS Funktion einfügen:var historyValuesOBJ ; function compareHistoryValue(currentValueFLT, operatorSTR, compareValueFLT, durationINT, identifierSTR) { console.log(currentValueFLT + " " + operatorSTR + " " + compareValueFLT + " For " + durationINT + "s"); //Current timestamp var currentTimeTST = Math.round(new Date().getTime() / 1000); //check if the global object exists and create it if not if (typeof historyValuesOBJ == "undefined") { historyValuesOBJ = {}; historyValuesOBJ[identifierSTR] = {}; historyValuesOBJ[identifierSTR].lastCallINT = currentTimeTST; historyValuesOBJ[identifierSTR].countINT = 0; } //Calculate the delata since last Call var deltaTimeINT = currentTimeTST - historyValuesOBJ[identifierSTR].lastCallINT; //Add the dealte to the count value historyValuesOBJ[identifierSTR].countINT = historyValuesOBJ[identifierSTR].countINT + deltaTimeINT; //set the last call to current timestamp historyValuesOBJ[identifierSTR].lastCallINT = currentTimeTST; console.log("Time since Last Call: " + historyValuesOBJ[identifierSTR].countINT ); if (operatorSTR == '<' ){ //if comparison fails, reset counter if (currentValueFLT >= compareValueFLT) { historyValuesOBJ[identifierSTR].countINT = 0; return false; } //if comparison is true else if (currentValueFLT < compareValueFLT) { //return true if value is larger if (historyValuesOBJ[identifierSTR].countINT >= durationINT){ return true; } return false; } } else if (operatorSTR == '>' ){ //if comparison fails, reset counter if (currentValueFLT <= compareValueFLT) { historyValuesOBJ[identifierSTR].countINT = 0; return false; } //if comparison is true else if (currentValueFLT > compareValueFLT) { //return true if value is larger if (historyValuesOBJ[identifierSTR].countINT >= durationINT){ return true; } return false; } } }
Im Blockly baut man sich dann noch einen Wrapper (JS-Funktion mit Ergebnis):
Und kann das dann so benutzen:
Das obige Script gibt true zurück, wenn der Wert für mindestens 45 Sekunden unter 500 geblieben ist.
ToDo:
- Ich habe nur größer und kleine implementiert, es fehlen noch Gleich sowie Größer-Gleich und Kleine-Gleich an Operatoren
- Auch vergleiche mit true/false fehlen noch
- Leider muss man noch einen Identifier angeben, damit das Script die Werte intern korrekt speichern kann.
Wenn jemand eine Idee hat, wie man das Generisch gestalten kann, immer her damit.