NEWS
Mysteriöser Zeittrigger
-
Hi,
dieses Script hat lange funktioniert. Allerdings scheint es seit dem letzten Abspeichern (ich habe nur den Wasserfilter ergänzt) oder Javascript Adapter Update falsch zu zählen / zu oft zu laufen.
Jeden Tag um 0:10:00 zählt das Script die Zahl am jeweiligen Datenpunkt um 1 hoch.
Tatsächlich erhöht sich der Wert aber um 2!
Ich habe mir mal eine "Debug"ausgabe über Telegram schicken lassen.
Aber ich verstehe nicht was passiert.Wo ist der Sprung von -159 zu -158?
Der Wert vor der Änderung ist schon um 1 reduziert und wird mit der Änderung erneut um 1 reduziert. "Wasserfilter"
Lasse ich mir die Ausgabe als Trigger bei Änderung des Datenpunktes geben "Wasserfilter frisch geändert" so schlägt er mit den gleichen Zahlen an.
Das heißt für mich, dass Script führt schon vor der 1. Telegramnachricht im Zeittrigger die Steuerbefehle aus.Auch im JS findet sich kein Fehler:
schedule("0 10 0 * * *", async () => { sendTo("telegram.0", "send", { text: ('Wasserfilter ' + String(getState('0_userdata.0.Wasserfilter').val)) }); setState('0_userdata.0.Wasserfilter' /* Wasserfilter */, (getState('0_userdata.0.Wasserfilter').val + 1)); sendTo("telegram.0", "send", { text: ('Wasserfilter ' + String(getState('0_userdata.0.Wasserfilter').val)) }); }); on({ id: [].concat(['0_userdata.0.Wasserfilter']), change: 'ne' }, async (obj) => { let value = obj.state.val; let oldValue = obj.oldState.val; sendTo("telegram.0", "send", { text: ('Wasserfilter frisch geändert ' + String(getState('0_userdata.0.Wasserfilter').val)) }); });
Das Ändern des Zeittriggers von Wizard auf Cron hat auch nichts geändert.
Eine doppelte Ausführung des Triggers findet nicht statt. Das sieht man an den Telegram Nachrichten.
Eine Änderung des Wertes durch ein anderes Script auch nicht, sonst müsste "Wasserfilter frisch geändert" mehrfach anschlagen. -
@maxpd teste mal bitte folgendes:
- erzeuge eine Variable “Wasserfilter_lokal”
- hol bei skriptstart den Wert von wasserfilter in diese variable
- Bau die Berechnung im Zeitplan so um das du mit der variablen rechnest, und nur einmal per setstate den DP aktualisierst.
A.
-
-
@maxpd
Fast. Eigentlich sollte die Variable beim skriptstart (außerhalb des Zeitplan) gesetzt werden, und dann im Zeitplan erst einmal erhöht und dann in den State geschrieben werden, so das der State im Zeitplan nicht ‘gelesen’ wird.A.
-
@asgothian mich wundert ja trotzdem, dass es vorher auf die simple Art und Weise funktionierte, aber jetzt nicht mehr. dann probieren wir es mal so:
-
@Asgothian Hat so funktioniert
ein rätsel bleibts mir
-
@maxpd sagte in Mysteriöser Zeittrigger:
@Asgothian Hat so funktioniert
ein rätsel bleibts mir
Erklären kann ich es nicht. Ich empfehle trotzdem immer zu vermeiden auf dem identischen Datenpunkt in einem Skript "herumzuhämmern", und statt dessen den Wert aus dem Datenpunkt in einer Variable zu halten.
dazu gehört z.Bsp. auch das in einem Trigger auf einen Datenpunkt dessen Wert von mir immer über den Baustein "Wert" (Ist im Trigger-Bereich der Baustein der mit Objekt ID vorbelegt ist, umgestellt auf Wert) ausgewertet wird, und nicht über "Wert von Objekt ID"
A.
-
@asgothian aber wie ist es denn in anderen Programmiersprachen? schreibt man dort auch erst Werte in eine variable um die am Schluss wieder in den Wert zu schreiben? kommt mir umständlich vor. in meinem Fall war das nur ein Beispiel. von diesem Wasserfilter gibt es noch 5 weitere.
ja das mit dem Wert aus dem Trigger habe ich auch schon an einer Stelle benutzt. allerdings habe ich selten nur ein Objekt im trigger sondern bis zu 8. damals dachte ich nur einen Wert wählen zu können. aber habe Grad bei Google Bilder gesehen, dass man scheinbar je nach Objekt Trigger ein anderen Wert auch auswählen kann. muss ich daheim nochmal anschauen
-
@maxpd sagte in Mysteriöser Zeittrigger:
@asgothian aber wie ist es denn in anderen Programmiersprachen? schreibt man dort auch erst Werte in eine variable um die am Schluss wieder in den Wert zu schreiben? kommt mir umständlich vor. in meinem Fall war das nur ein Beispiel. von diesem Wasserfilter gibt es noch 5 weitere.
Das ist eine Abwägungssache. Dabei hilft es, sich die Objekte als eine Datenbank vorzustellen, sprich der Baustein "Wert von Objekt ID targetID." bzw. der JS Befehl "getState(targetID).val" übersetzt sich in Umgangssprache in "hole aus der Datenbank das Objekt mit der ID targetID und gib mir dessen Wert.
Das umgekehrte passiert beim Schreiben. Diese Operationen kosten also Zeit. Inzwischen ist Blockly so umgestellt worden das darauf Rücksicht genommen wird, früher war es aber so das die Kombination aus erst einen Wert in ein Objekt hinein schreiben und diesen danach direkt wieder herauslesen zu interessanten Effekten geführt hat. Mal hatte man den korrekten, mal den alten Wert.Deswegen hat sich (für mich) eingebrannt:
- Objektwerte in einem Skript nach Möglichkeit einmal lesen und einmal schreiben.
- Immer erst lesen, dann schreiben, nie umgekehrt.
Wenn ich also einen Objektwert mehrfach benötige (für Ausgaben, Berechnungen, Bedingungen) dann hole ich den immer in eine Variable (1x)
Wenn ich den nur einmal benötige lasse ich das.
Und wenn ich innerhalb eines Triggers irgend eine Eigenschaft des den Trigger auslösenden Objekts brauche dann mache ich das wenn möglich über den oben beschriebenen Baustein - der wird vom Trigger bereits gefüllt, da muss ich nicht "nochmal in die Datenbank schauen", sozusagen.A.