Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. getState ohne/mit await

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    getState ohne/mit await

    This topic has been deleted. Only users with topic management privileges can see it.
    • paul53
      paul53 @FernetMenta last edited by

      @fernetmenta sagte: Wenn "Do not subscribe all states on start" nicht aktiv ist (default), dann benötigt man keine callback

      Ja, dann wird gepuffert.

      H 1 Reply Last reply Reply Quote 1
      • H
        hub01 @paul53 last edited by

        @paul53
        korrigierte Fassung,
        nur gültig, wenn beim Start alle Zustände abonniert werden (mit Puffer)

        011.PNG
        012.PNG

        FernetMenta 1 Reply Last reply Reply Quote 0
        • FernetMenta
          FernetMenta @hub01 last edited by

          @hub01 Das stimmt so nicht ganz, wenn ich den code vom javascript adapter richtig gelesen habe. Wenn alle Zustände aboniert sind, holt der Adapter die Werte immer aus dem Puffer. Es ist egal welchen Befehl man verwendet.

          paul53 1 Reply Last reply Reply Quote 0
          • paul53
            paul53 @FernetMenta last edited by paul53

            @fernetmenta sagte: Wenn alle Zustände aboniert sind, holt der Adapter die Werte immer aus dem Puffer. Es ist egal welchen Befehl man verwendet.

            Nein. Auszug "sandbox.js" (Zeile 2479 ff.):

                    getState: function (id, callback) {
                        if (typeof id !== 'string') {
                            sandbox.log(`getState has been called with id of type "${typeof id}" but expects a string`, 'error');
                            return undefined;
                        }
            
                        if (typeof callback === 'function') {
                            if (!id.includes('.')) {
                                adapter.getState(id, (err, state) =>
                                    callback(err, context.convertBackStringifiedValues(id, state)),
                                );
                            } else {
                                adapter.getForeignState(id, (err, state) =>
                                    callback(err, context.convertBackStringifiedValues(id, state)),
                                );
                            }
                        } else {
                            if (adapter.config.subscribe) {
                                sandbox.log(
                                    'The "getState" method cannot be used synchronously, because the adapter setting "Do not subscribe to all states on start" is enabled.',
                                    'error',
                                );
            

            getStateAsync(id):

                    getStateAsync: async function (id) {
                        let state;
                        if (id.includes('.')) {
                            state = await adapter.getForeignStateAsync(id);
                        } else {
                            state = await adapter.getStateAsync(id);
                        }
                        return context.convertBackStringifiedValues(id, state);
                    },
            
            FernetMenta 1 Reply Last reply Reply Quote 0
            • FernetMenta
              FernetMenta @paul53 last edited by

              @paul53 danke, da hab ich wohl den Code zu schnell und falsch gelesen 🙂

              1 Reply Last reply Reply Quote 0
              • H
                hub01 @paul53 last edited by hub01

                @paul53
                Erst mal ein großes Danke, weil du auf jede Frage eingehst und richtig stellst.

                Wenn meine letzte Aufstellung passt, würde ich gern noch die weiteren Varianten betrachten.
                Ich hoffe, dass ich alles richtig verstanden und eingetragen habe.

                EDIT: get/setStateAsync durchgestrichen
                013a.PNG

                Noch eine Frage zu get/setState mit Callback:
                die Funktion arbeitet zwar asynchron, die Callbackfunktion wird aber erst aufgerufen, wenn der DP gelesen wurde?

                paul53 1 Reply Last reply Reply Quote 0
                • paul53
                  paul53 @hub01 last edited by paul53

                  @hub01 sagte: Noch eine Frage zu get/setState mit Callback:
                  die Funktion arbeitet zwar asynchron, die Callbackfunktion wird aber erst aufgerufen, wenn der DP gelesen wurde?

                  Ja, das Ergebnis (Zustand) wird an die Callback-Funktion übergeben.

                  @hub01 sagte in getState ohne/mit await:

                  die weiteren Varianten betrachten.

                  Wozu setStateAsync gut ist, erschließt sich mir nicht.
                  Die ...Async Funktionen kann man nicht ohne await aufrufen. Ergebnis bei getStateAsync ohne await:

                  Promise { <pending> }
                  

                  Die Callback-Funktion bei setState() dient nur einer möglichen Fehlerauswertung. Sie unterscheidet sich ansonsten nicht von setState() ohne Callback und wird so gut wie nie verwendet.

                  EDIT: Folgende Funktionen sind sinnvoll:

                  • const state = getState(id) nur mit Puffer
                  • getState(id, cb) Aufruf mit cb(err, state)
                  • const state = await getStateAsync(id)
                  • setState(id, state)
                  H 1 Reply Last reply Reply Quote 1
                  • H
                    hub01 @paul53 last edited by

                    @paul53
                    „await setStateAsync“ wäre auch noch brauchbar, oder?

                    paul53 1 Reply Last reply Reply Quote 0
                    • paul53
                      paul53 @hub01 last edited by

                      @hub01 sagte: „await setStateAsync“ wäre auch noch brauchbar, oder?

                      Wofür?

                      T H 3 Replies Last reply Reply Quote 0
                      • T
                        ticaki Developer @paul53 last edited by ticaki

                        @paul53

                        Wenn man States in einer so hohen Frequenz ändert, das die Möglichkeit besteht einen "Rückstau" zu erzeugen. Mit await setStateAsync() würde man den neuen Schreibvorgang immer erst dann auslösen, wenn der alte abgeschlossen ist.

                        1 Reply Last reply Reply Quote 0
                        • H
                          hub01 @paul53 last edited by

                          @paul53 sagte in getState ohne/mit await:

                          @hub01 sagte: „await setStateAsync“ wäre auch noch brauchbar, oder?

                          Wofür?

                          ich dachte, z.B. wegen Post #9
                          Wird aber vermutlich selten bis gar nicht gebraucht.
                          Da es die Funktion gibt, und diese macht, was sie machen soll, lasse ich sie vollständigkeitshalber in meiner Aufstellung drin.
                          (aber mit Anmerkung)

                          1 Reply Last reply Reply Quote 0
                          • H
                            hub01 @paul53 last edited by

                            @paul53 sagte in getState ohne/mit await:

                            @hub01 sagte: „await setStateAsync“ wäre auch noch brauchbar, oder?

                            Wofür?

                            ich will 1x pro Tag den Energiewert der PV-Anlage in einen Datenpunkt speichern,
                            und danach den Energiewert löschen.
                            Dabei war mir nicht klar, ob ich dafür ein setStateAsync bzw. getStateAsync benötige.

                            // ====================================================
                            //   um 23:59:55
                            //   - akt. Tagesenergie als 1 Tageswert sichern
                            //   - alle Energiewerte löschen
                            //
                            //   PVGes       = PV1+PV2
                            //   EnergieTag  = aktuelle aufsummierte Tagesenergie
                            //   EnergieTag2 = 1 gesicherter Wert/Tag (Tageswert)
                            // ====================================================
                            schedule({hour:23, minute:58, second:0}, async() => {
                                await setStateAsync((prePVAllg +".PVGesEnergieTag2"), 
                                 await getStateAsync(prePVAllg +".PVGesEnergieTag"), true);     // Ges-Energie als Tageswert sichern
                                console.log("Gesamt-Energie als Tageswert gesichert")
                            
                                // danach:
                                setState((prePVAllg +".PVGesEnergieTag"), 0, true);             // CLR Gesamt-Energie
                                setState((preWR1 +".TodayYield"), 0, true);                     // CLR Energie Haus
                                setState((preWR2 +".dailyEnergyYield"), 0, true);               // CLR Energie Garage
                                console.log("Energiewerte gelöscht")
                            });
                            
                            paul53 1 Reply Last reply Reply Quote 0
                            • paul53
                              paul53 @hub01 last edited by paul53

                              @hub01 sagte: 1x pro Tag den Energiewert der PV-Anlage in einen Datenpunkt speichern

                              Du speicherst nicht nur den Wert, sondern den kompletten Zustand in "Tag2".

                              @hub01 sagte in getState ohne/mit await:

                              setStateAsync bzw. getStateAsync benötige.

                              Wenn der Puffer der JS-Instanz nicht deaktiviert wurde, weder - noch

                                  setState(prePVAllg + ".PVGesEnergieTag2", getState(prePVAllg + ".PVGesEnergieTag").val, true);     // Ges-Energie als Tageswert sichern
                              

                              Was stört daran, dass das Skript durchgelaufen ist, bevor setState() für "Tag2" fertig ist?
                              Aus "Tag" wird synchron gelesen und danach werden die DP auf 0 gesetzt.

                              H 1 Reply Last reply Reply Quote 1
                              • H
                                hub01 @paul53 last edited by

                                @paul53 sagte in getState ohne/mit await:

                                @hub01 sagte: 1x pro Tag den Energiewert der PV-Anlage in einen Datenpunkt speichern

                                Du speicherst nicht nur den Wert, sondern den kompletten Zustand in "Tag2".

                                ja, habe ich bemerkt,
                                ist aber für mich ein Vorteil, weil ich dadurch sehe, wann sich der Wert das letzte mal geändert hat

                                @paul53 sagte in getState ohne/mit await:

                                @hub01 sagte in getState ohne/mit await:

                                setStateAsync bzw. getStateAsync benötige.

                                Wenn der Puffer der JS-Instanz nicht deaktiviert wurde, weder - noch

                                    setState(prePVAllg + ".PVGesEnergieTag2", getState(prePVAllg + ".PVGesEnergieTag").val, true);     // Ges-Energie als Tageswert sichern
                                

                                Auf Grund dieser Diskussion bin ich auch zu diesem Schluss gekommen.
                                Vorher war das set/getStateAsync für mich erst mal die sichere Methode.

                                Danke nochmals für die ganzen Infos.

                                H 1 Reply Last reply Reply Quote 0
                                • H
                                  hub01 @hub01 last edited by hub01

                                  Jetzt habe ich noch einen Fall, wo ich mir nicht sicher bin.

                                  Ich habe einen Verbrauchszähler, der jeden Tag den Tageswert aufsummiert.
                                  Der Zähler wird archiviert und als Trend angezeigt.

                                  Am Monatsende, bzw. Monatsersten soll der Zähler noch den letzten Tageswert addieren
                                  und dann wieder mit Null anfangen.

                                  // ==================================
                                  //   jeden Monatsersten um 00:00:00
                                  // ==================================
                                  schedule({date:1, hour:0, minute:0}, () => {
                                  
                                      var mCount = getState(preTest +".Monatszähler").val;
                                      var tVal   = getState(preTest +".Tageswert").val;
                                  
                                      // letzten Tageswert addieren
                                      setState((preTest +".Monatszähler"), mCount + tVal, true);
                                  
                                      // danach: Monatszähler löschen
                                      setState((preTest +".Monatszähler"), 0, true);
                                  
                                  });
                                  

                                  Können hier die beiden asynchronen setState´s Probleme machen, weil sie direkt aufeinander folgen
                                  und den gleichen Datenpunkt beschreiben?

                                  paul53 1 Reply Last reply Reply Quote 0
                                  • paul53
                                    paul53 @hub01 last edited by paul53

                                    @hub01 sagte: Am Monatsende, bzw. Monatsersten soll der Zähler noch den letzten Tageswert addieren und dann wieder mit Null anfangen.

                                    Es macht keinen Sinn, erst einen Zählwert in den DP zu schreiben, um ihn gleich darauf wieder zu löschen. Unterscheide zwischen "letzter Monat" und "aktueller Monat".

                                    H 1 Reply Last reply Reply Quote 0
                                    • H
                                      hub01 @paul53 last edited by

                                      @paul53
                                      Es geht darum, dass vor dem Löschen noch der letzte Tageswert im Zähler erfasst wird, damit der Chart stimmt.
                                      Beim letzten Zählerstand würde ich noch den Zeitstempel um 1 Sek. verringern, damit es in den letzten Monat fällt.

                                      paul53 1 Reply Last reply Reply Quote 0
                                      • paul53
                                        paul53 @hub01 last edited by paul53

                                        @hub01 sagte: damit der Chart stimmt.

                                        Du stellst ansteigende Werte im Chart dar (Sägezahn)?
                                        Für richtige Chart-Darstellungen muss man kurz vor Mitternacht triggern.
                                        Beispiel in Blockly:

                                        Blockly_Periodenwerte.JPG

                                        H 1 Reply Last reply Reply Quote 0
                                        • H
                                          hub01 @paul53 last edited by

                                          @paul53 sagte in getState ohne/mit await:

                                          @hub01 sagte: damit der Chart stimmt.

                                          Du stellst ansteigende Werte im Chart dar (Sägezahn)?

                                          im 1. Schritt, ja - nur zum Testen
                                          Danach soll der Endwert 1x pro Monat in eine eigene Chart-Variable kopiert werden.

                                          Mir geht’s nur um das Verständnis, ob in so einem Fall ein „await setStateAsync“ besser wäre.
                                          Wäre für mich wieder die sichere Methode.

                                          1 Reply Last reply Reply Quote 0
                                          • P
                                            ple last edited by

                                            @hub01
                                            Dein Thread passt ja wie geschnitten auf meine Frage. Ich fange jetzt wieder an mit iobroker und Scripte für mein KNX. Eigentlich musste ich da nicht ran, weil es einfach läuft, aber ich will ja jetzt ein wenig mehr dazulernen.
                                            Ich komme noch aus der Zeit mit Admin2.0, da waren meine Scripte alle nur getState oder setState. Ja ich hatte damals Callback gehört, aber nie richtig verstanden. Ich komme eher aus der Welt der Siemens S7.

                                            Jetzt nach einigem lesen und Chatgpt, bin ich auf await/async gestoßen.
                                            Wenn der Code von oben nach unten durchrattert, bewirkt jetzt ein await getStateasync und ein await setStateasync, dass genau in dieser Zeile solange gewartet wird, bis die States gesetzt sind?

                                            Hier mal ein Beispiel, kam von GROK.

                                            async function createAndSetState(id, initialValue, config, newValue) {
                                                try {
                                                    await createStateIfNotExists(id, initialValue, config, initialValue);
                                                    const current = await getStateAsync(id);
                                                    if (current?.val !== newValue) {
                                                        await setStateAsync(id, newValue, true);
                                                        log(`[update] ${id}: ${JSON.stringify(current?.val)} → ${JSON.stringify(newValue)}`, 'debug');
                                                    } else {
                                                        log(`[skip] ${id} unverändert: ${JSON.stringify(newValue)}`, 'debug');
                                                    }
                                                } catch (err) {
                                                    log(`Fehler bei State ${id}: ${err.message}`, 'error');
                                                }
                                            }
                                            

                                            Die Funktion soll mir nur die States beschreiben, wenn diese unterschiedlich sind zum vorherigen um die schreiblast zu minimieren. Ausgelesen wird eine MSSQL Antwort und dann gesplittet.

                                            Aufruf wäre dann in einer async function.

                                            for (const dp of dataPoints) {
                                                        await createAndSetState(dp.id, dp.value, dp.config, dp.value);
                                                    }
                                            
                                                    await setStateAsync(`${pfad}is_syncing`, false, true);
                                            

                                            Ich gehe mal davon aus, dass wenn erst alle State beschrieben worden sind, das dann is_syncing auf false gesetzt wird.

                                            Das gleiche dann auch für createState, wenn die noch nicht vorhanden sind.

                                            async function createStateIfNotExists(id, initialValue, config, defaultValue) {
                                                try {
                                                    const exists = await existsStateAsync(id);
                                                    if (!exists) {
                                                        await createStateAsync(id, initialValue, config);
                                                        await setStateAsync(id, defaultValue, true);
                                                    }
                                                } catch (err) {
                                                    log(`Fehler bei State ${id}: ${err.message}`, 'error');
                                                }
                                            }
                                            

                                            Sehe ich das alles so richtig? Oder gibt es einfachere Wege. Stehe da ein wenig auf dem Schlauch.

                                            Gruß und Besten Dank.

                                            paul53 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            666
                                            Online

                                            31.8k
                                            Users

                                            80.0k
                                            Topics

                                            1.3m
                                            Posts

                                            6
                                            43
                                            1070
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo