Skip to content
  • Recent
  • Tags
  • 0 Unread 0
  • Categories
  • Unreplied
  • Popular
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Fragen zur Ausführung von setState und getState

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.1k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    1.8k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    15
    1
    2.1k

Fragen zur Ausführung von setState und getState

Scheduled Pinned Locked Moved JavaScript
javascript
13 Posts 4 Posters 1.5k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • mplogasM Offline
    mplogasM Offline
    mplogas
    wrote on last edited by mplogas
    #1

    Hallo.
    Ich habe ein Script, welches Batteriewerte meiner Sensoren und Schalter aggregiert und in eigenen Datenpunkten ablegt. Leider funktioniert das Script nicht wie erwartet und ich verstehe nicht wieso. Ich habe das Problem in einem Repro extrahiert und würde mich freuen, wenn ihr mal draufschauen könntet und mir meinen Fehler zeigt.

    Erwartetes Verhalten:

    1. Datenpunkt wird mit der Clear()-Methode gelöscht
    2. Der Datenpunkt enthält ein leeres serialisiertes JSON-Array
    3. Ein string ("test1") wird dem Datenpunkt mit der Add()-Methode hinzugefügt
    4. Der Datenpunkt enthält ein serialisiertes JSON-Array mit einem Item: "test1"

    Beobachtetes Verhalten:

    1. Run, Clear() ist erfolgreich
    11:16:10.846	info	javascript.0 (27065) Start javascript script.js.dev.mvp
    11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: add: [] | | test1
    11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: content: []
    11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: registered 0 subscriptions and 0 schedules
    11:16:10.856	info	javascript.0 (27065) script.js.dev.mvp: arrayjavascript.0.DEV.repro cleared: []
    11:16:10.856	info	javascript.0 (27065) script.js.dev.mvp: added test1 to list
    
    1. Run, Clear() ist nicht erfolgreich
    11:16:43.390	info	javascript.0 (27065) Start javascript script.js.dev.mvp
    11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: add: ["test1"] | test1 | test1
    11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: content: ["test1"]
    11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: registered 0 subscriptions and 0 schedules
    11:16:43.399	info	javascript.0 (27065) script.js.dev.mvp: arrayjavascript.0.DEV.repro cleared: ["test1"]
    

    Script:

    createState("DEV");
    createArray("DEV.repro");
    
    Test();
    
    function Test() {
        const id = "javascript.0.DEV.repro";
        let data = "test1";
        
        Clear(id);
        Add(id, data);
        Remove(id, data);
        Add(id, "test2");
    
        log("content: " + getState(id).val);
    }
    
    function createArray(name) {
        let data = [];
        createState(name, "", {
            read: true,
            write: true,
            desc: "Beschreibung",
            type: "string",
            def: JSON.stringify(data)
        });
    }
    
    function Add(array, value) {
        let data = [];
        let raw = getState(array).val;
        if(raw.length > 2) {
            data = JSON.parse(raw);
        }
    
        log("add: " + raw + " | " + data + " | " + value);
    
        if(!data.includes(value)) {
            data.push(value);
            setState(array, JSON.stringify(data));                        
            log("added " + value + " to list");
        }
    }
    
    function Clear(array) {
        let data = [];
        log(JSON.stringify(data));
        setState(array, JSON.stringify(data));
        log("array" + array + " cleared: " + getState(array).val);
    }
    

    Workarounds

    Ich hatte die Vermutung, dass es sich um ein Timing-Problem handelt und habe daher versucht, beim setState() mit Callbacks zu arbeiten. Leider ändert sich nichts, laut Log. Clear() ist immer nur jedes zweite Mal erfolgreich.

    function Clear(array, callback) {
       let data = [];
       setState(array, JSON.stringify(data), false, callback);   
    }
    
    ...
    Clear(id, function() {
            log("array" + id + " cleared: " + getState(id).val);
            Add(id, data, function() {
                log("content: " + getState(id).val);
            });
    });
    ...
    

    Was mache ich falsch?

    AlCalzoneA 1 Reply Last reply
    0
    • mplogasM mplogas

      Hallo.
      Ich habe ein Script, welches Batteriewerte meiner Sensoren und Schalter aggregiert und in eigenen Datenpunkten ablegt. Leider funktioniert das Script nicht wie erwartet und ich verstehe nicht wieso. Ich habe das Problem in einem Repro extrahiert und würde mich freuen, wenn ihr mal draufschauen könntet und mir meinen Fehler zeigt.

      Erwartetes Verhalten:

      1. Datenpunkt wird mit der Clear()-Methode gelöscht
      2. Der Datenpunkt enthält ein leeres serialisiertes JSON-Array
      3. Ein string ("test1") wird dem Datenpunkt mit der Add()-Methode hinzugefügt
      4. Der Datenpunkt enthält ein serialisiertes JSON-Array mit einem Item: "test1"

      Beobachtetes Verhalten:

      1. Run, Clear() ist erfolgreich
      11:16:10.846	info	javascript.0 (27065) Start javascript script.js.dev.mvp
      11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: add: [] | | test1
      11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: content: []
      11:16:10.853	info	javascript.0 (27065) script.js.dev.mvp: registered 0 subscriptions and 0 schedules
      11:16:10.856	info	javascript.0 (27065) script.js.dev.mvp: arrayjavascript.0.DEV.repro cleared: []
      11:16:10.856	info	javascript.0 (27065) script.js.dev.mvp: added test1 to list
      
      1. Run, Clear() ist nicht erfolgreich
      11:16:43.390	info	javascript.0 (27065) Start javascript script.js.dev.mvp
      11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: add: ["test1"] | test1 | test1
      11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: content: ["test1"]
      11:16:43.397	info	javascript.0 (27065) script.js.dev.mvp: registered 0 subscriptions and 0 schedules
      11:16:43.399	info	javascript.0 (27065) script.js.dev.mvp: arrayjavascript.0.DEV.repro cleared: ["test1"]
      

      Script:

      createState("DEV");
      createArray("DEV.repro");
      
      Test();
      
      function Test() {
          const id = "javascript.0.DEV.repro";
          let data = "test1";
          
          Clear(id);
          Add(id, data);
          Remove(id, data);
          Add(id, "test2");
      
          log("content: " + getState(id).val);
      }
      
      function createArray(name) {
          let data = [];
          createState(name, "", {
              read: true,
              write: true,
              desc: "Beschreibung",
              type: "string",
              def: JSON.stringify(data)
          });
      }
      
      function Add(array, value) {
          let data = [];
          let raw = getState(array).val;
          if(raw.length > 2) {
              data = JSON.parse(raw);
          }
      
          log("add: " + raw + " | " + data + " | " + value);
      
          if(!data.includes(value)) {
              data.push(value);
              setState(array, JSON.stringify(data));                        
              log("added " + value + " to list");
          }
      }
      
      function Clear(array) {
          let data = [];
          log(JSON.stringify(data));
          setState(array, JSON.stringify(data));
          log("array" + array + " cleared: " + getState(array).val);
      }
      

      Workarounds

      Ich hatte die Vermutung, dass es sich um ein Timing-Problem handelt und habe daher versucht, beim setState() mit Callbacks zu arbeiten. Leider ändert sich nichts, laut Log. Clear() ist immer nur jedes zweite Mal erfolgreich.

      function Clear(array, callback) {
         let data = [];
         setState(array, JSON.stringify(data), false, callback);   
      }
      
      ...
      Clear(id, function() {
              log("array" + id + " cleared: " + getState(id).val);
              Add(id, data, function() {
                  log("content: " + getState(id).val);
              });
      });
      ...
      

      Was mache ich falsch?

      AlCalzoneA Offline
      AlCalzoneA Offline
      AlCalzone
      Developer
      wrote on last edited by
      #2

      @mplogas Mir ist zwar gerade nicht ganz klar, warum es nicht funktioniert, aber eine Empfehlung habe ich:
      Aggregiere die nötigen Werte in einer Variablen und schreibe diese 1x am Ende der Aggregation per setState in einen State. So vermeidest du mögliche Timing-Probleme ganz.

      Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

      mplogasM 1 Reply Last reply
      0
      • AlCalzoneA AlCalzone

        @mplogas Mir ist zwar gerade nicht ganz klar, warum es nicht funktioniert, aber eine Empfehlung habe ich:
        Aggregiere die nötigen Werte in einer Variablen und schreibe diese 1x am Ende der Aggregation per setState in einen State. So vermeidest du mögliche Timing-Probleme ganz.

        mplogasM Offline
        mplogasM Offline
        mplogas
        wrote on last edited by
        #3

        @AlCalzone das mache ich tatsächlich in meinem ursprünglichen Batterie-Skript. Meine Clear()-Methode zeigt aber, dass der mit setState() gesetzte Wert nicht zuverlässig mit getState() abgerufen werden kann. Da meine JSONArray-CRUDs Teil eines globalen Scripts sind interessiert mich was ich falsch mache.

        AlCalzoneA 1 Reply Last reply
        0
        • mplogasM mplogas

          @AlCalzone das mache ich tatsächlich in meinem ursprünglichen Batterie-Skript. Meine Clear()-Methode zeigt aber, dass der mit setState() gesetzte Wert nicht zuverlässig mit getState() abgerufen werden kann. Da meine JSONArray-CRUDs Teil eines globalen Scripts sind interessiert mich was ich falsch mache.

          AlCalzoneA Offline
          AlCalzoneA Offline
          AlCalzone
          Developer
          wrote on last edited by AlCalzone
          #4

          @mplogas sagte in Fragen zur Ausführung von setState und getState:

          setState() gesetzte Wert nicht zuverlässig mit getState() abgerufen werden kann

          Ich vermute dass da noch ein Delay drin ist zwischen "Schreibvorgang erfolgreich" und "wurde im Cache aktualisiert". Bei Triggern kann es auch manchmal sein, dass der Wert in obj.state.val neuer ist als der, der von getState zurückgegeben wird.
          Wenn du es irgendwie vermeiden kannst, nutze Datenpunkte nicht wie Variablen, die du sofort wieder benötigst.

          Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

          mplogasM 1 Reply Last reply
          0
          • MicM Offline
            MicM Offline
            Mic
            Developer
            wrote on last edited by Mic
            #5

            @mplogas

            @AlCalzone sagte in Fragen zur Ausführung von setState und getState:

            Wenn du es irgendwie vermeiden kannst, nutze Datenpunkte nicht wie Variablen, die du sofort wieder benötigst.

            Dem kann ich nur zustimmen. Wenn du in einem Script einen Datenpunkt setzt (setState()), dann weißt du ja bereits, was du setzt. Das kannst du dir in einer (globalen) Variable "merken", dann brauchst du danach getState() nicht mehr.
            getState() ist "expensive", d.h. es braucht deutlich mehr System-Ressourcen (und Ausführungszeit), als den Wert aus einer (globalen) Variable auszulesen.
            Die Seiteneffekte, die du siehst, sollten dann auch weg sein.
            Wenn du noch mehr Hilfe brauchst, poste am besten ein komplettes Script, damit wir das schnell nachvollziehen/testen können 😉

            1 Reply Last reply
            0
            • T Offline
              T Offline
              tombox
              wrote on last edited by
              #6

              Das ganze ist nicht so schön aber um es zu fixen könntest du mit await und den async methoden arbeiten
              await getStateAsync
              await setStateAsync

              MicM AlCalzoneA 2 Replies Last reply
              0
              • MicM Offline
                MicM Offline
                Mic
                Developer
                wrote on last edited by Mic
                #7

                Nachtrag:
                Falls viele Datenpunkte und Schleifen, dann halte ich mir jeden Datenpunkt-Inhalt für setState und getState in einer globalen Variable, Typ Array, vor. Damit kann ich dann auch schön in Schleifen darauf zugreifen. Es sei denn, man braucht diesen Datenpunktinhalt jeweils nur einmal pro Schleifen-Durchlauf, dann einfach nur eine Variable innerhalb der Schleife.

                1 Reply Last reply
                0
                • T tombox

                  Das ganze ist nicht so schön aber um es zu fixen könntest du mit await und den async methoden arbeiten
                  await getStateAsync
                  await setStateAsync

                  MicM Offline
                  MicM Offline
                  Mic
                  Developer
                  wrote on last edited by Mic
                  #8

                  @tombox sagte in Fragen zur Ausführung von setState und getState:

                  await getStateAsync
                  await setStateAsync

                  Guter Punkt, aber meines Erachtens ist das hier unnötig 🙂 Mal zur Veranschaulichung:

                  1. Ich habe einen Text in einem String, z.B. let str = 'das hier ist ein Text.'.
                  2. Nun speichere ich diesen Text, warum auch immer, auf die Festplatte als txt.-Datei (oder z.B. - wie oben - per setState() in einen Datenpunkt).
                  3. Danach brauche ich im selben Script wieder den Text, der weiterhin auch im Speicher und in der Variable str vorliegt. Soll ich mir nun tatsächlich die Mühe machen, die txt-Datei wieder auszulesen (oder - wie oben - den State per getState()), obwohl in der Variable str mein Text 'das hier ist ein Text.' bereits vorhanden ist?
                  1 Reply Last reply
                  0
                  • T tombox

                    Das ganze ist nicht so schön aber um es zu fixen könntest du mit await und den async methoden arbeiten
                    await getStateAsync
                    await setStateAsync

                    AlCalzoneA Offline
                    AlCalzoneA Offline
                    AlCalzone
                    Developer
                    wrote on last edited by
                    #9

                    @tombox Das hat die gleichen Probleme, da die Async-Methoden nur ein Wrapper um die Callbacks darstellen.

                    Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                    1 Reply Last reply
                    0
                    • mplogasM Offline
                      mplogasM Offline
                      mplogas
                      wrote on last edited by
                      #10

                      @Mic said in Fragen zur Ausführung von setState und getState:

                      Wenn du noch mehr Hilfe brauchst, poste am besten ein komplettes Script, damit wir das schnell nachvollziehen/testen können

                      Mein Repro-Code im OP zeigt mein Problem. Was ich eigentlich machen will ist einmal am Tag durch alle Sensoren und Switches rennen und alle Sensoren unter einem Schwellwert in einem JSON-Array als string-Datenpunkt speichern. Dieser Teil funktioniert ohne Probleme und ist auch nicht zeitkritisch. Ich möchte allerdings beim Scriptstart sinnvollerweise den Datenpunkt vorher "leeren" (lies: mit einem leeren JSON-Array beschreiben).
                      Genau dieses Clear() bereitet mir Probleme: wenn ich getValue(id) zeitnah nach setValue(id, value) aufrufe ist bei jedem zweiten Mal (warum jedes Zweite?) nicht der erwartete (und geschriebene) Inhalt im Datenpunkt.

                      Ich habe meinen Code mal angehangen, aber da passiert auch nicht viel mehr als im Repro. ClearArray und AddToArray sind globale Methoden, die Clear und Add im Repro entsprechen.

                      schedule("30 5 * * *", CheckBattery);
                      function CheckBattery() {
                          const warning = "javascript.0.x.batterywarning";
                          const empty = "javascript.0.x.batteryempty";
                      
                          ClearArray(warning);
                          ClearArray(empty);    
                      
                          let sensors = getObject("enum.sensors.battery").common.members;
                          let switches = getObject("enum.switches.battery").common.members;
                          let state = sensors.concat(switches);
                      
                          for(let i = 0; i < state.length; i++) {
                              let battery = getState(state[i]).val;
                      
                              if(battery < 30) {
                                  log("critical: " + state[i] + " " + battery);
                                  AddToArray(empty, state[i]);
                              } else if(battery < 50) {
                                  log("warning: " + state[i] + " " + battery);
                                  AddToArray(warning, state[i]);
                              }
                          }
                      }
                      
                      1 Reply Last reply
                      0
                      • AlCalzoneA AlCalzone

                        @mplogas sagte in Fragen zur Ausführung von setState und getState:

                        setState() gesetzte Wert nicht zuverlässig mit getState() abgerufen werden kann

                        Ich vermute dass da noch ein Delay drin ist zwischen "Schreibvorgang erfolgreich" und "wurde im Cache aktualisiert". Bei Triggern kann es auch manchmal sein, dass der Wert in obj.state.val neuer ist als der, der von getState zurückgegeben wird.
                        Wenn du es irgendwie vermeiden kannst, nutze Datenpunkte nicht wie Variablen, die du sofort wieder benötigst.

                        mplogasM Offline
                        mplogasM Offline
                        mplogas
                        wrote on last edited by
                        #11

                        @AlCalzone Ja, ich kann natürlich drumherum-engineeren indem ich kein Clear nutze sondern ein Overwrite schreibe und somit den Datenpunkt "zeitunkritisch" schreibe. Mich interessierte, ob/was ich falsch gemacht hatte - wenn das by-design ist das auch OK 🙂

                        AlCalzoneA 1 Reply Last reply
                        0
                        • mplogasM mplogas

                          @AlCalzone Ja, ich kann natürlich drumherum-engineeren indem ich kein Clear nutze sondern ein Overwrite schreibe und somit den Datenpunkt "zeitunkritisch" schreibe. Mich interessierte, ob/was ich falsch gemacht hatte - wenn das by-design ist das auch OK 🙂

                          AlCalzoneA Offline
                          AlCalzoneA Offline
                          AlCalzone
                          Developer
                          wrote on last edited by
                          #12

                          @mplogas Ich denke das wichtigste ist, Datenpunkte und get/set State nicht als Ersatz für (temporäre) Variablen zu nutzen. Die Analogie von Mic ist ziemlich treffend.

                          Ich möchte allerdings beim Scriptstart sinnvollerweise den Datenpunkt vorher "leeren" (lies: mit einem leeren JSON-Array beschreiben).

                          Das kannst du durchaus machen. Allerdings weißt du dann, dass der Inhalt ein leeres Array ist, das brauchst du nicht wieder auslesen.

                          Warum `sudo` böse ist: https://forum.iobroker.net/post/17109

                          mplogasM 1 Reply Last reply
                          0
                          • AlCalzoneA AlCalzone

                            @mplogas Ich denke das wichtigste ist, Datenpunkte und get/set State nicht als Ersatz für (temporäre) Variablen zu nutzen. Die Analogie von Mic ist ziemlich treffend.

                            Ich möchte allerdings beim Scriptstart sinnvollerweise den Datenpunkt vorher "leeren" (lies: mit einem leeren JSON-Array beschreiben).

                            Das kannst du durchaus machen. Allerdings weißt du dann, dass der Inhalt ein leeres Array ist, das brauchst du nicht wieder auslesen.

                            mplogasM Offline
                            mplogasM Offline
                            mplogas
                            wrote on last edited by
                            #13

                            @AlCalzone said in Fragen zur Ausführung von setState und getState:

                            Das kannst du durchaus machen. Allerdings weißt du dann, dass der Inhalt ein leeres Array ist, das brauchst du nicht wieder auslesen.

                            Das Auslesen geschieht ja nur im Log, weil ich versuchte den Fehler zu finden. Mir ist aufgefallen, dass ich jeden zweiten Tag (bzw. jeden zweiten Lauf) die Werte des vorherigen Laufs noch im Array hatte obwohl ich Clear() aufgerufen hatte. Wie auch immer, ich habe Clear() ersetzt und überschreibe das Array jetzt mit den neuen Werten. Ist leider nicht ganz so modular wie erhofft, aber vermutlich muss ich mich ohnehin gedanklich von den SOLID-Prinzipien lösen und mehr "hacken".

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            Support us

                            ioBroker
                            Community Adapters
                            Donate

                            589

                            Online

                            32.4k

                            Users

                            81.4k

                            Topics

                            1.3m

                            Posts
                            Community
                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                            ioBroker Community 2014-2025
                            logo
                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Recent
                            • Tags
                            • Unread 0
                            • Categories
                            • Unreplied
                            • Popular
                            • GitHub
                            • Docu
                            • Hilfe