NEWS
[Gelöst] - GetState in Schleife liefert zuerst false
-
Hi,
ich versuche über eine for Schleife Werte aus Datenpunkten auszulesen.
Beim ersten Durchlauf der Schleife bei dem der Objekt-key 0 ist, bekomme ich false als Wert, die darauf folgenden Durchläufe funktionieren.Kann mir einer sagen warum das so ist?
Hier das Script:
// ******************************************************************************************************* // // SchaltUhr // // // v1.0 - 10.11.2022 init // // // ******************************************************************************************************** // ----------------------------------------------------------------------------- // allgemeine Variablen // ----------------------------------------------------------------------------- var loglevel = 2; // Loglevel 0 = kein Logging / 1 -3 Logging wird genauer var debugging = false; // Debugging on/off - Bei On werden keine Aktoren geschalten nur Log-Ausgaben var Systemlog = true; // Systemmeldungen anlegen ja/nein var instanz = '0_userdata.0'; instanz = instanz +'.'; var pfad0 = 'SwitchingAutomatic'; pfad0 = pfad0 +'.'; const devices = [ /*Device ID */ /*Device Name für Datenpunkt */ /*Device Typ (state / level) */ /*Doppelfenster Küche - Steckdose rechts - rechts*/ {'deviceID':'shelly.0.SHSW-25#XXXXXXXXXX#1.Relay1.Switch'/*Switch*/, 'deviceName':'Steckdose_Kueche_Doppelfenster_rechts-rechts', 'deviceType':'state'}, /*Doppelfenster Küche rechts - Steckdose rechts - links*/ {'deviceID':'shelly.0.SHSW-25#XXXXXXXXXX#1.Relay0.Switch'/*Switch*/, 'deviceName':'Steckdose_Kueche_Doppelfenster_rechts-links', 'deviceType':'state'}, /*Doppelfenster Küche - Steckdose links - rechts*/ {'deviceID':'shelly.0.SHSW-25#YYYYYYYYYY#1.Relay1.Switch'/*Switch*/, 'deviceName':'Steckdose_Kueche_Doppelfenster_links-rechts', 'deviceType':'state'}, /*Doppelfenster Küche - Steckdose links - links*/ {'deviceID':'shelly.0.SHSW-25#YYYYYYYYYY#1.Relay0.Switch'/*Switch*/, 'deviceName':'Steckdose_Kueche_Doppelfenster_links-links', 'deviceType':'state'} ]; // ############################################################################# // # # // # Funktion Geräte Stati erstellen # // # # // ############################################################################# async function createDeviceStates(){ try { for(var i = 0; i < Object.keys(devices).length; i++) { await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.switchingAutomatic', {name: 'Automatisches Schalten', type:'boolean', def:false, read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.onTime1', {name: 'Einschaltzeit 1', type:'string', def:'8:00', read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.onTime2', {name: 'Einschaltzeit 2', type:'string', def:'8:00' , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.offTime1', {name: 'Ausschaltzeit 1', type:'string', def:'23:00' , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.offTime2', {name: 'Ausschaltzeit 2', type:'string', def:'23:00' , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.reactOnSleepingMode', {name: 'Auf Schlafmodus reagieren', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.reactOnAlarmingMode', {name: 'Auf Alarmanlage reagieren', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.reactOnSunrise', {name: 'Auf Sonnenaufgang reagieren', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.reactOnSunset', {name: 'Auf Sonnenuntergang reagieren', type:'boolean', def:false , read:true, write:true}); // Unterscheidung Typen (state / level) switch(devices[i].deviceType){ case 'state': // Gerätetyp State await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateSleepingModeOn', {name: 'Geraetestatus bei Schlafmodus ein', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateSleepingModeOff', {name: 'Geraetestatus bei Schlafmodus aus', type:'boolean', def:true , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateAlarmingModeOn', {name: 'Geraetestatus bei Alarmanlage ein', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateAlarmingModeOff', {name: 'Geraetestatus bei Alarmanlage aus', type:'boolean', def:true , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateSunriseOn', {name: 'Geraetestatus bei Sonnenaufgang', type:'boolean', def:false , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.stateSunsetOn', {name: 'Geraetestatus bei Sonnenuntergang', type:'boolean', def:false , read:true, write:true}); break; case 'level': // Gerätetyp Level await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelSleepingModeOn', {name: 'Geraetelevel bei Schlafmodus ein', type:'number', def:0 , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelSleepingModeOff', {name: 'Geraetelevel bei Schlafmodus aus', type:'number', def:100 , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelAlarmingModeOn', {name: 'Geraetelevel bei Alarmanlage ein', type:'number', def:0 , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelAlarmingModeOff', {name: 'Geraetelevel bei Alarmanlage aus', type:'number', def:100 , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelSunriseOn', {name: 'Geraetelevel bei Sonnenaufgang ein', type:'number', def:0 , read:true, write:true}); await createStateAsync(instanz + pfad0 + devices[i].deviceName + '.levelSunsetOn', {name: 'Geraetelevel bei Sonnenuntergang ein', type:'number', def:0 , read:true, write:true}); break; } } } catch (error) { log(`Unexpected error - ${error}`, 'error'); } } createDeviceStates(); // ############################################################################# // # # // # Schedule für Ein-/Ausschalten # // # # // ############################################################################# //test(); async function scheduleDeviceStates(){ try { //const deviceSchedules = new Object(); for(var i = 0; i < Object.keys(devices).length; i++) { log(getState(instanz + pfad0 + devices[i].deviceName + '.onTime1').val+' --->'+i) } } catch (error) { log(`Unexpected error - ${error}`, 'error'); } } // liefert beim ersten wert false scheduleDeviceStates();
Hier die Log-Ausgabe dazu:
javascript.0 2022-11-29 12:39:00.928 info script.js.Wandtablet.Schaltautomatik: 8:00 --->3 javascript.0 2022-11-29 12:39:00.928 info script.js.Wandtablet.Schaltautomatik: 8:01 --->2 javascript.0 2022-11-29 12:39:00.928 info script.js.Wandtablet.Schaltautomatik: 8:02 --->1 javascript.0 2022-11-29 12:39:00.928 info script.js.Wandtablet.Schaltautomatik: false --->0
Und wenn ich es mit await getStateAsync versuche bekomme ich gar keine Werte:
javascript.0 2022-11-29 12:41:21.533 info script.js.Wandtablet.Schaltautomatik: undefined --->3 javascript.0 2022-11-29 12:41:21.533 info script.js.Wandtablet.Schaltautomatik: undefined --->2 javascript.0 2022-11-29 12:41:21.533 info script.js.Wandtablet.Schaltautomatik: undefined --->1 javascript.0 2022-11-29 12:41:21.533 info script.js.Wandtablet.Schaltautomatik: undefined --->0
Da ich speziell auch noch bei dem Async Thema meine Schwierigkeiten habe, ist es mir fast unmöglich nachzuvollziehen woran das liegt.
Gerne her mit Unterstützung.
-
@peoples sagte in GetState in Schleife liefert zuerst false:
createDeviceStates
JS ist ja nicht unbedingt meine Kernkompetenz, aber ich versuch's mal:
Alles was Du in
createDeviceStates
lostrittst, wird ja asynchron ausgeführt.
Nach meinem Verständnis kehrt die Methode also quasi unmittelbar nach dem Aufruf zurück.
Wenn Du dannscheduleDeviceStates
aufrufst kannst Du nicht sicher sein, dass die DP auch tatsächlich angelegt sind.Warum nicht einfach nur ein
createState
? (ohne "Async") -
@codierknecht
HI also das Problem ist nicht das erstellen der Datenpunkte das funktioniert sondern das auslesen in der Schleife.Selbst wenn die erstellt sind, kann ich die States nicht abrufen es geht immer der erste nicht.
Macht auch keinen Unterschied ob Async oder nicht.Sobald bei devices[i].deviceName das i den Wert 0 hat funktioniert es nicht.
-
@peoples
Also zunächst mal finde ich persönlich es extrem schwierig zu lesen, wenn innerhalb der Objektdefinition Kommentare eingefügt sind. Ich würde das außerhalb der Deklaration dokumentieren (wenn überhaupt - was da gemacht wird ist eigentlich auch ohne Kommentare klar).Auch warum die beiden Variablen
instanz
undpfad0
nicht direkt als Stringliterale besetzt sondern zusammengebaut werden, erschließt sich nicht. Macht es nur schwerer zu lesen.Was sagt denn das hier:
async function scheduleDeviceStates() { try { for(var i = 0; i < devices.length; i++) { log(devices[i].deviceName + ' --->' + i); } } catch (error) { log(`Unexpected error - ${error}`, 'error'); } }
Wird das array zumindest sauber gelesen?
Bei mir schon - ich vermute immer noch, dass beim ersten Durchlauf noch nicht alle DP existieren bzw. mit ihren Defaultwerten besetzt sind.Warum überhaupt
createStateAsync
? Nur um die parallel zu erzeugen?
Wenn die sauber nacheinander erzeugt werden, dauert das doch nur wenige Millisekunden.
Da wäre mir der ganze Verwaltungskram für die Parallelität zu aufwändig.
Ich würde das zunächst mal ganz klassisch synchron machen. Wenn's zu viel Performance frisst, kann man das später immer noch optimieren.
KISS ... keep it simple stupidRules of Optimization:
Rule 1: Don’t do it.
Rule 2 (for experts only): Don’t do it yet.Oder um es mit den Worten von Donald Knuth zu sagen:
premature optimization is the root of all evil
-
@codierknecht
Gerade genau Dein Script mal in 2 Stufen laufen lassen:
1.) Den zweiten Funktionsaufruf auskommentiert. Es werden wie erwartet alle DP erzeugt.
2.) Den ersten Funktionsaufruf auskommentiert. Ergebnis:29.11.2022, 19:50:30.280 [info ]: javascript.1 (23493) Start javascript script.js.test.Test_JS 29.11.2022, 19:50:30.296 [info ]: javascript.1 (23493) script.js.test.Test_JS: 8:00 --->0 29.11.2022, 19:50:30.297 [info ]: javascript.1 (23493) script.js.test.Test_JS: 8:00 --->1 29.11.2022, 19:50:30.297 [info ]: javascript.1 (23493) script.js.test.Test_JS: 8:00 --->2 29.11.2022, 19:50:30.297 [info ]: javascript.1 (23493) script.js.test.Test_JS: 8:00 --->3
-
Danke ich habe jetzt meinen Fehler gefunden
-
@peoples sagte in [Gelöst] - GetState in Schleife liefert zuerst false:
Nicht jeder ist ein "ausgebildeter / studierter" Programmierer, ergo man macht vieles wie man denkt.
Auch Zitate helfen oft wenig weiter und fördern nur einen Eindruck den man wahrscheinlich seinem Gegenüber nicht vermitteln will.Akzeptiert ... war aber tatsächlich nur gut gemeint
Ich beschäftige mich mittlerweile seit Jahren viel mit dem Thema "CleanCode".
Meine Quintesenz: Gut lesbarer Code funktioniert meist - weil sich Bugs nicht so leicht verstecken können.
Ausgebildet/studiert übrigens nicht - ich hatte lediglich das große Glück, mein Hobby zum Beruf machen zu können.Ich bin gerade dabei, mich in die Grundzüge von
await
undasync
einzulesen.
Ich hoffe, in ein paar Minuten eine Lösung für Dein Problem anbieten zu können.
Mein erster Ansatz funktioniert nämlich im Übrigen nicht.createState
scheint grundsätzlich asynchron zu sein. Man weiß ohne besondere Vorkehrungen also nicht, wann alle DP tatsächlich existieren. -
@peoples sagte in [Gelöst] - GetState in Schleife liefert zuerst false:
Danke ich habe jetzt meinen Fehler gefunden
Und der wäre? Interessiert mich auch.
-
@codierknecht
Ich bin ein IdiotIch hatte in dem ersten Datenpunkt keine Zeit '8:00' drin stehen sondern tatsächlich ein 'false'.
Deswegen hat er auch immer das false ausgegeben -
Ich habe mittlerweile folgende Lösung gefunden:
async function scheduleDeviceStates(){ try { await createDeviceStates(); for(var i = 0; i < Object.keys(devices).length; i++) {
Die erste Funktion wird nicht bei Scriptstart aufgerufen, sondern bevor in der zweiten Funktion die DP verarbeitet werden.
Mit diesem Konstrukt wird auf die Beendigung gewartet und erst dann die Schleifenverarbeitung gestartet.Wieder was dazugelernt - Danke!
Da wirste alt wie 'ne Kuh und lernst immer noch dazu
-
@codierknecht sagte in GetState in Schleife liefert zuerst false:
Ich bin gerade dabei, mich in die Grundzüge von await und async einzulesen.
dann interessiert dich möglicherweise das hier. Ist aber nichts was man unbedingt sofort versteht
-
@peoples
Nur der Vollständigkeit halber und weil wir am Ende des Tages dann beim Smalltalk angekommen sind:
Die Krux ist tatsächlich dieser Async-Kram. Den muss man an der Ecke halt irgendwie in den Griff kriegen.
Wirkliche "Fehler" waren in Deinem Code ja nicht vorhandenFalls es interessiert: https://clean-code-developer.de/
Ist jetzt nicht die allerbeste Adresse, weil da kommerzielle Gedanken dahinterstehen. Aber das ist ja durchaus legitim und die Seite fasst Dinge gut zusammen, die man sich sonst aus allen möglichen Quellen zusammensuchen muss. -
@fastfoot
Danke!