NEWS
[Gelöst] [Frage] setState schreibt "null" statt Wert?
-
Hallo Skripter :ugeek:
ich bin ein ganz Neuer :oops:
Ich habe auch schon brav viewtopic.php?f=8&t=9236 abgearbeitet :!:
Zu ioBroker kam ich durch den Wunsch für meine Heizung endlich mal eine vernünftige Visualisierung zu realisieren… Bisher hatte ich mit JavaScript überhaupt nichts zu tun, aber mit etwas Google und natürlich Dank der vielen Beiträge im Forum bin ich recht weit gekommen :shock: Jetzt scheitere ich aber an der bisher größten Hürde für mich: Es läuft nicht alles der Reihe nach sondern irgendwie gleichzeitig :lol:
Trotzdem bin ich nach nicht mal einer Woche extrem begeistert von ioBroker. Vielen Dank all denen die dazu in vielen Stunden Entwicklungszeit beigetragen haben!
Nun aber zum Problem bei dem ich jetzt nicht mehr weiterkomme:
- Die Funktion fOzwSetVals bekommt die ID eines Datenpunkts übergeben.
- Aus dieser wird der Wert und eine "ozwId" ermittelt.
- Damit wird dann ein http request gebastelt.
- Bei positiver Rückmeldung von der Heizung möchte ich den entsprechenden Datenpunkt auf ack=true setzen.
- Meistens ist aber da der zugehörige Variablenwert schon weg, weil der Rest der Funktion schon durchgelaufen ist und damit die Variable nicht mehr da ist (?)
- Ich brauche den Wert aber schon für den Request, muss ihn also vorher schon bestimmen.
Wie löse ich das sauber?
Funktion:
let fOzwSetVals = function(statName) { log ("OzwSetVals called!"); var ozwSetValue = getState(statName).val; var ozwId = getObject(statName).common.ozwId; require("request") (ozwUrl + '/api/menutree/write_datapoint.json?SessionId=' + sessionId + '&Id=' + ozwId + '&Type=Enumeration' + '&Value=' + ozwSetValue + '&EnumValue=' + ozwSetValue, function (error, response, results) { if(error) { log("OZW Wert schreiben fehlgeschlagen! (http request)"); } else { ozwObject = JSON.parse(results); switch (ozwObject.Result.Success) { case 'true': log("OZW Wert erfolgreich geschrieben!","info"); setState(statName,ozwSetValue,true); //HIER ist unter Umständen ozwSetValue "nicht mehr da..." break; case 'false': log("OZW Wert schreiben fehlgeschlagen! (OZW Rückmeldung)","warn"); log(JSON.stringify(results),"warn"); break; default: log("OZW Wert schreiben fehlgeschlagen, unbekannte OZW Rückmeldung!","warn"); log(JSON.stringify(results),"warn"); } } }); log("EndeGelände"); };
Log Ausgabe:
Man sieht, dass nach der ersten Änderung "Ende Gelände" vor "Wert erfolgreich geschrieben" erreicht wird. Mein Versuch den Datenpunkt auf Ack=True zu setzen geht dann in die Hose, es wird auch der Wert auf "Null" gesetzt. Das führt dazu, dass die übergeordnete Funktion eine Änderung erkennt und die Funktion erneut aufruft… Käse
javascript.0 2018-10-10 23:27:26.191 warn script.js.ozw.ozwtest2: "{\n \"Result\": {\n\t\t\"Success\": \"false\",\n\t\t\"Error\": {\n\t\t\t\"Txt\": \"value not valid\",\n\t\t\t\"Nr\": \"9\"\n\t\t}\n\t}\n} \n" javascript.0 2018-10-10 23:27:26.190 warn script.js.ozw.ozwtest2: OZW Wert schreiben fehlgeschlagen! (OZW Rückmeldung) javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: EndeGelände javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: getObject(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, enumName=undefined) => {"_id":"javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_m javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: getState(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, timerId=0) => {"val":null,"ack":true,"ts":1539206845909,"q":0,"from":"system.adapter.javascript. javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: OzwSetVals called! javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: OZW Session noch gültig javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: ozwGetSession called javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: Änderung! javascript.0 2018-10-10 23:27:25.919 info script.js.ozw.ozwtest2: setForeignState(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, state={"val":null,"ack":true}) javascript.0 2018-10-10 23:27:25.917 info script.js.ozw.ozwtest2: OZW Wert erfolgreich geschrieben! javascript.0 2018-10-10 23:27:25.315 info script.js.ozw.ozwtest2: EndeGelände javascript.0 2018-10-10 23:27:25.315 info script.js.ozw.ozwtest2: getObject(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, enumName=undefined) => {"_id":"javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_m javascript.0 2018-10-10 23:27:25.315 info script.js.ozw.ozwtest2: getState(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, timerId=0) => {"val":1,"ack":false,"ts":1539206844061,"q":0,"from":"system.adapter.admin.0","lc" javascript.0 2018-10-10 23:27:25.315 info script.js.ozw.ozwtest2: OzwSetVals called! javascript.0 2018-10-10 23:27:25.312 info script.js.ozw.ozwtest2: Session erfolgreich gestartet! javascript.0 2018-10-10 23:27:24.077 info script.js.ozw.ozwtest2: OZW Session abgelaufen! javascript.0 2018-10-10 23:27:24.077 info script.js.ozw.ozwtest2: ozwGetSession called javascript.0 2018-10-10 23:27:24.076 info script.js.ozw.ozwtest2: Änderung!
Danke schonmal vorab!
Konrad
Edit sagt, ich habe den Betreff angepasst
-
Hallo,
zeig mal bitte den rest des Programms.
Wann rufst du die Funktion:
fOzwSetVals
auf?
Du solltest das erst tun, wenn die Callback Funktion des request aufgerufen wird.
So in der Form…
request('url', function(error, response, results){ //erst hier wieder fOzwSetVals aufrufen})
-
Zur gewünschten Funktion des ganzen Ablaufs:
Wenn sich einer von mehreren Datenpunkten in einem Ordner ändert, dann:
- soll geprüft werden ob es noch eine gültige SessionId für die Heizung gibt
- falls nicht soll eine neue angefragt werden (bis hier fOzwGetSession)
- dann soll der Wert des geänderten Datenpunkts an die Heizung geschickt werden (fOzwSetVals)
- wenn das auch geklappt hat soll der Datenpunkt wieder auf ack=true gesetzt werden, und genau daran scheitert es
fOzwGetSession ist eine eigene Funktion weil ich parallel dazu auch noch zyklisch Werte lesen möchte und dazu auch eine SessionId brauche.
Ich habe auch noch etwas gespielt und den setState als callback einem vorhergehenden getState untergeordnet (siehe Kommentar im letzten Else Block).
Es funktioniert wenn der Wert 0 ist, alles !=0 wird als "null" in den Datenpunkt geschrieben. Auch wenn ich im setState direkt einen Zahlenwert eintrage. :shock:
Wird "null" geschrieben erkenne ich natürlich eine Änderung deswegen geht es von vorne los, das ist ja aber so gewünscht. Ich möchte ja nur ack=true setzen und nicht den Wert ändern.
Hier das ganze Elend :oops: :
const ozwUrl = "xyz"; const username = "xyz"; const password = "xyz"; const maxOzwSessionAge = 600; var sessionId; var sessionStat; var sessionTimeStamp = 0; var resobj; var sessionAge; $('state[id=.OzwAutoSetVals.*]').on(function (statObj) { log("Änderung!"); fOzwGetSession(fOzwSetVals,statObj.id); }); let fOzwGetSession = function (callback, statName) { log("ozwGetSession called"); sessionAge = (((new Date()).getTime())/1000)-sessionTimeStamp; if (sessionAge>maxOzwSessionAge) { log("OZW Session abgelaufen!"); require("request") (ozwUrl + '/api/auth/login.json?user=' + username + '&pwd=' + password, function (error, response, results) { if(error) { log("OZW Anmeldung fehlgeschlagen","Error"); } else { resobj = JSON.parse(results); sessionId=resobj.SessionId; sessionStat=resobj.Result.Success; sessionTimeStamp=new Date().getTime()/1000; if (sessionStat) { log("Session erfolgreich gestartet!"); callback (statName); } else { log("OZW Anmeldung ungültig", "Error"); } } }); } else { log("OZW Session noch gültig"); callback (statName); } }; let fOzwSetVals = function(statName) { log ("OzwSetVals called!"); var ozwSetValue = getState(statName).val; var ozwId = getObject(statName).common.ozwId; var temp; require("request") (ozwUrl + '/api/menutree/write_datapoint.json?SessionId=' + sessionId + '&Id=' + ozwId + '&Type=Enumeration' + '&Value=' + ozwSetValue + '&EnumValue=' + ozwSetValue, function (error, response, results) { if(error) { log("OZW Wert schreiben fehlgeschlagen! (http request)"); } else { //var statName; ozwObject = JSON.parse(results); switch (ozwObject.Result.Success) { case 'true': log("OZW Wert erfolgreich geschrieben!","info"); getState(statName, function (error, obj) { (statName,obj.val,true); //!!! das klappt nicht, es wird der Wert "Null" in den Datenpunkt geschrieben }); break; case 'false': log("OZW Wert schreiben fehlgeschlagen! (OZW Rückmeldung)","warn"); log(JSON.stringify(results),"warn"); break; default: log("OZW Wert schreiben fehlgeschlagen, unbekannte OZW Rückmeldung!","warn"); log(JSON.stringify(results),"warn"); } } }); log("EndeGelände"); };
Danke!
-
Hi,
Auf die schnelle…...
Aus meiner Sicht ist das mit deiner Zeitabfrage viel zu umständlich und eigentlich nicht funktional.
Erstelle dir eine Hilfsvariable z.b.
let active = false;
Wenn du dann deine Funktion aufrufst, fragst du vorher ab ob sie true ist, falls ja rufst du sie nicht auf.
Die Hilfsvariable setzt du dann in der callback function des requests auf false, sowohl bei Error als auch bei result.
Solltest du sehr viele Änderungen in den states haben, müsstest du eventuell mit einen Buffer arbeiten.
Gesendet von meinem Handy
-
Mahlzeit,
danke für den Hinweis!
Die Zeitgeschichte habe ich gebaut da die SessionIds irgendwann ablaufen. Wann genau hab ich noch nicht herausgefunden, gibt dazu keine sinnvolle frei verfügbare Doku (Siemens).
Ich verstehe aber immer noch nicht wie es dazu kommt, dass
log("OZW Wert erfolgreich geschrieben!","info");
getState(statName, function (error, obj) {
log(obj.val);
(statName,obj.val,true); //!!! das klappt nicht, es wird der Wert "Null" in den Datenpunkt geschrieben
});
den Datenpunkt "statName" mit "null" beschreibt wenn obj.val != 0 ist.
In der vorhergehenden Logausgabe erscheint der korrekte Wert…
javascript.0 2018-10-12 15:41:42.750 info script.js.ozw.ozwtest2: setForeignState(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, state={"val":null,"ack":true}) javascript.0 2018-10-12 15:41:42.745 info script.js.ozw.ozwtest2: 1 javascript.0 2018-10-12 15:41:42.719 info script.js.ozw.ozwtest2: OZW Wert erfolgreich geschrieben! javascript.0 2018-10-12 15:41:41.955 info script.js.ozw.ozwtest2: EndeGelände javascript.0 2018-10-12 15:41:41.955 info script.js.ozw.ozwtest2: getObject(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, enumName=undefined) => {"_id":"javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_m javascript.0 2018-10-12 15:41:41.955 info script.js.ozw.ozwtest2: getState(id=javascript.0.scriptEnabled.ozw.ozwtest2.OzwAutoSetVals.set_tww_mod, timerId=0) => {"val":1,"ack":false,"ts":1539351701726,"q":0,"from":"system.adapter.admin.0","lc" javascript.0 2018-10-12 15:41:41.955 info script.js.ozw.ozwtest2: OzwSetVals called! javascript.0 2018-10-12 15:41:41.947 info script.js.ozw.ozwtest2: Session erfolgreich gestartet! javascript.0 2018-10-12 15:41:41.753 info script.js.ozw.ozwtest2: OZW Session abgelaufen! javascript.0 2018-10-12 15:41:41.751 info script.js.ozw.ozwtest2: ozwGetSession called javascript.0 2018-10-12 15:41:41.746 info script.js.ozw.ozwtest2: Änderung!
-
Tja… wen für den Datenpunkt
max = null
definiert ist macht setState das so - ganz still und heimlich :shock:
Hat ein paar Stunden gedauert bis ich drauf gekommen bin :oops:
-
Tja… wen für den Datenpunkt
max = null
definiert ist macht setState das so - ganz still und heimlich :shock:
Hat ein paar Stunden gedauert bis ich drauf gekommen bin :oops: `
Dann bitte als erledigt markieren….