Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • 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

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Entwicklung
  4. SetState() nur bei Änderung von Werten?!?

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    14
    1
    262

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    13
    1
    586

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    25
    1
    1.8k

SetState() nur bei Änderung von Werten?!?

Geplant Angeheftet Gesperrt Verschoben Entwicklung
17 Beiträge 7 Kommentatoren 4.6k Aufrufe
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • paul53P Offline
    paul53P Offline
    paul53
    schrieb am zuletzt editiert von
    #4

    @jens.maus:

    mittels eines Konstruktes aus "if(getState() != val) setState()" ? Denn auch das erscheint mir unnötiger Overhead auf der Adapter-Seite zu sein, `
    Den geringsten Overhead hat man sicherlich, wenn man für jeden Wert eine (globale) Skriptvariale hat, mit der verglichen wird, bevor sie aktualisiert und der Datenpunkt geändert wird.

    varN = getState(id).val;
    
    ...
    
    if(varN != val) {
      varN = val;
      setState(id, val, true);
    }
    

    Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
    Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

    1 Antwort Letzte Antwort
    0
    • apollon77A Offline
      apollon77A Offline
      apollon77
      schrieb am zuletzt editiert von
      #5

      Einzige sinnvolle Variante ist die aktuellen Werte im Adapter-Prozess nochmal im Speicher zu haben. Dann kannst Du mit denen vergleichen und entscheiden wann Du neu in setState schreibst. Das kostet an sich nicht sooo viel Speicher.

      Am Ende ist halt die Frage was das für Werte sind und welche Dinge die Nutzer damit anstellen. Vllt ist es ja interessant auch "nicht geänderte Werte" getriggert zu bekommen. Das geht dann nicht mehr wenn Du Sie nur bei Änderungen schreibst. Aber bei "Pull-Szenarien" (also regelmäßiges abholen) ist das wohl eher nicht so relevant.

      Beitrag hat geholfen? Votet rechts unten im Beitrag :-) https://paypal.me/Apollon77 / https://github.com/sponsors/Apollon77

      • Debug-Log für Instanz einschalten? Admin -> Instanzen -> Expertenmodus -> Instanz aufklappen - Loglevel ändern
      • Logfiles auf Platte /opt/iobroker/log/… nutzen, Admin schneidet Zeilen ab
      1 Antwort Letzte Antwort
      0
      • jens.mausJ Offline
        jens.mausJ Offline
        jens.maus
        schrieb am zuletzt editiert von
        #6

        @paul53:

        @jens.maus:

        mittels eines Konstruktes aus "if(getState() != val) setState()" ? Denn auch das erscheint mir unnötiger Overhead auf der Adapter-Seite zu sein, Den geringsten Overhead hat man sicherlich, wenn man für jeden Wert eine (globale) Skriptvariale hat, mit der verglichen wird, bevor sie aktualisiert und der Datenpunkt geändert wird.

        Oh, ich denke ich hab mich zu ungenau ausgedrückt. Es geht hier natürlich um die Entwicklung eines eigenen Adapters, dort gibt es nicht setState() sondern eben "adapter.setState()" genauso wie "adapter.getState()" und das verhält sich leider auch etwas anders, denn es ist immer asynchron sodass sowas z.B. nicht zu funktionieren scheint:

        for(var i=0; i < 100; i++) {
          var newval = i;
          var stateName = "test." + i;
          adapter.getState(stateName, function(err, state) {
            if(state.val != newval)
              adapter.setState(stateName, {ack: true, val: newval);
          });
        }
        
        

        Das Problem hierbei ist, wie gesagt, das adapter.getState() asynchron ist und somit "newval" und "stateName" innerhalb der anyonmen Funktion die an adapter.getState() übergeben wird zur Ausführungszeit leider die falschen werte hat. Zumindest ist das hier gerade der Fall.

        RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

        1 Antwort Letzte Antwort
        0
        • jens.mausJ Offline
          jens.mausJ Offline
          jens.maus
          schrieb am zuletzt editiert von
          #7

          @apollon77:

          Am Ende ist halt die Frage was das für Werte sind und welche Dinge die Nutzer damit anstellen. Vllt ist es ja interessant auch "nicht geänderte Werte" getriggert zu bekommen. Das geht dann nicht mehr wenn Du Sie nur bei Änderungen schreibst. Aber bei "Pull-Szenarien" (also regelmäßiges abholen) ist das wohl eher nicht so relevant. `

          Ich denke auch das das nicht wirklich relevant ist für solche Pull-Szenarien. Hier würde es auch eher von Vorteil sein das nicht jedes adapter.setState() das an ioBroker abgesetzt wird darin endet dass dieser mit dem setzen der Werte und dem publisher an alle Interessenten beschäftigt ist. Das macht IMHO nur unnötigen Aufwand. Meiner Meinung nach wäre es sicherlich sinnvoll zusätzlich zu adapter.setState() eine Art adapter.setStateNotChanged() Funktion ode reinen zusätzlichen Parameter bei setState() einzuführen der erlaubt zu definieren ob ioBroker vor setzen des Wertes prüfen soll ob der Wert nicht ohnehin schon auf diesen Wert steht.

          RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

          1 Antwort Letzte Antwort
          0
          • BluefoxB Offline
            BluefoxB Offline
            Bluefox
            schrieb am zuletzt editiert von
            #8

            @jens.maus:

            @paul53:

            @jens.maus:

            mittels eines Konstruktes aus "if(getState() != val) setState()" ? Denn auch das erscheint mir unnötiger Overhead auf der Adapter-Seite zu sein, Den geringsten Overhead hat man sicherlich, wenn man für jeden Wert eine (globale) Skriptvariale hat, mit der verglichen wird, bevor sie aktualisiert und der Datenpunkt geändert wird.

            Oh, ich denke ich hab mich zu ungenau ausgedrückt. Es geht hier natürlich um die Entwicklung eines eigenen Adapters, dort gibt es nicht setState() sondern eben "adapter.setState()" genauso wie "adapter.getState()" und das verhält sich leider auch etwas anders, denn es ist immer asynchron sodass sowas z.B. nicht zu funktionieren scheint:

            for(var i=0; i < 100; i++) {
              var newval = i;
              var stateName = "test." + i;
              adapter.getState(stateName, function(err, state) {
                if(state.val != newval)
                  adapter.setState(stateName, {ack: true, val: newval);
              });
            }
            
            

            Das Problem hierbei ist, wie gesagt, das adapter.getState() asynchron ist und somit "newval" und "stateName" innerhalb der anyonmen Funktion die an adapter.getState() übergeben wird zur Ausführungszeit leider die falschen werte hat. Zumindest ist das hier gerade der Fall. `
            Das macht man einbisschen anders:

            function setStates(_states, callback) {
            	if (!_states || !_states.length) {
            		if (typeof callback === 'function') callback();
            		return;
            	}
            	var newState = _states.shift();
            	adapter.getState(newState.name, function (err, oldState) {
            		if (newState.val != oldState.val) {
            			adapter.setState(newState.name, {ack: true, val: newState.val}, function () {
            				setTimeout(setStates, 0, _states, callback);
            			});
            		} else {
            			setTimeout(setStates, 0, _states, callback);
            		}
            	});
            }
            
            var states = [];
            for (var i = 0; i < 100; i++) {
            	var newval = i;
            	var stateName = 'test.' + i;
            	states.push({name: stateName, val: newval};
            }
            
            setStates(states, function () {
            	console.log('finished');
            });
            
            

            Falls die Werte nicht zu gross sind (ein Wert unter 1kb) ich empfehle dir alle 1000 Werte in RAM im Adapter zu halten.

            1 Antwort Letzte Antwort
            0
            • apollon77A Offline
              apollon77A Offline
              apollon77
              schrieb am zuletzt editiert von
              #9

              @jens.maus:

              Meiner Meinung nach wäre es sicherlich sinnvoll zusätzlich zu adapter.setState() eine Art adapter.setStateNotChanged() Funktion ode reinen zusätzlichen Parameter bei setState() einzuführen der erlaubt zu definieren ob ioBroker vor setzen des Wertes prüfen soll ob der Wert nicht ohnehin schon auf diesen Wert steht. `

              Meines WIssens macht die "setState" Logik das schon. Wenn der Wert nicht geändert ist wird der "lc" (=lastchanged") Timestamp nicht geändert sondern nur "ts" (Timestamp"). Also die Erkennungslogik ist da schon drin.

              Und bei den Triggern kann man "ne" als "not equal" angeben, sodass man nur bei Änderungen notifiziert wird …

              Beitrag hat geholfen? Votet rechts unten im Beitrag :-) https://paypal.me/Apollon77 / https://github.com/sponsors/Apollon77

              • Debug-Log für Instanz einschalten? Admin -> Instanzen -> Expertenmodus -> Instanz aufklappen - Loglevel ändern
              • Logfiles auf Platte /opt/iobroker/log/… nutzen, Admin schneidet Zeilen ab
              1 Antwort Letzte Antwort
              0
              • jens.mausJ Offline
                jens.mausJ Offline
                jens.maus
                schrieb am zuletzt editiert von
                #10

                @apollon77:

                Meines WIssens macht die "setState" Logik das schon. Wenn der Wert nicht geändert ist wird der "lc" (=lastchanged") Timestamp nicht geändert sondern nur "ts" (Timestamp"). Also die Erkennungslogik ist da schon drin.

                Und bei den Triggern kann man "ne" als "not equal" angeben, sodass man nur bei Änderungen notifiziert wird … `

                Nun, dann ist aber doch immer noch der Overhead da das der normale "ts"-Timestamp angepasst werden muss von ioBroker. Des Weiteren sehe ich zumindest im admin adapter das alle state zur selben zeit immer grün aufleuchten, d.h. also eine änderung/anpassung anzeigen immer genau dann wenn mein adapter wieder Intervall-basiert die Werte mit setState() einfach blind setzt.

                RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

                1 Antwort Letzte Antwort
                0
                • apollon77A Offline
                  apollon77A Offline
                  apollon77
                  schrieb am zuletzt editiert von
                  #11

                  Korrekt. Auch wenn sich nur "ts" ändern ist das eine Änderung und wird an alle Subscriber notifiziert die das wissen wollen … Und ich denke Admin will alles wissen :-)

                  So oder so: Ja bei Pull-Szenarien macht es Sinn nicht jede "Nicht-Änderung" per setState zu senden sondern nur Änderungen.

                  Also lokal die Werte Speichern (geht übrigens auch für mehr als 1000 Datensätze noch ... wird halt irgendwann zur Speicherverbrauchsfrage.

                  Ingo F

                  Beitrag hat geholfen? Votet rechts unten im Beitrag :-) https://paypal.me/Apollon77 / https://github.com/sponsors/Apollon77

                  • Debug-Log für Instanz einschalten? Admin -> Instanzen -> Expertenmodus -> Instanz aufklappen - Loglevel ändern
                  • Logfiles auf Platte /opt/iobroker/log/… nutzen, Admin schneidet Zeilen ab
                  1 Antwort Letzte Antwort
                  0
                  • jens.mausJ Offline
                    jens.mausJ Offline
                    jens.maus
                    schrieb am zuletzt editiert von
                    #12

                    @apollon77:

                    Korrekt. Auch wenn sich nur "ts" ändern ist das eine Änderung und wird an alle Subscriber notifiziert die das wissen wollen … Und ich denke Admin will alles wissen :-) `

                    Das stimmt wohl, aber IMHO sollte Admin zumindest keine Änderung der States anzeigen (mit grünem Aufflackern) wenn sich nichts am Wert geändert hat. Vielleicht könnte man das ja im admin adapter mal anpassen/ändern?!?

                    Auch wäre es sicherlich sinnvoll wenn man dem Subscribe Befehl eine Option/Möglichkeit hinzufügen könnte nur auf Wertänderungen zu reagieren und nicht auf allgemeine Änderungen (z.b. anpassen der 'ts'), dann würde sich auch hier der overhead für alle subscriber sicherlich weiter reduzieren denn mit jedem weiteren Adapter wird das system ja dann nicht unnötig jeden adapter bei jeder Anpassung an einen state benachrichtigen sondern nur eben die die wirklich auch auf reine ts Änderungen reagieren wollen (was sicherlich die wenigstens wirklich wollen).

                    @apollon77:

                    So oder so: Ja bei Pull-Szenarien macht es Sinn nicht jede "Nicht-Änderung" per setState zu senden sondern nur Änderungen. `

                    Genau deshalb argumentiere ich ja für diese Szenarien den adapter.setState() befehl dahingehend zu erweitern das man ihm mitteilen kann das er nur den State anpassen soll wenn der Wert des State wirklich unterschiedlich ist. Das könnte man ja IMHO ähnlich wie mit dem "ack=true/false" machen in dem man hier sowas wie folgendes implementiert:

                    adapter.setState(state, {val: 1, ack=true, forceChange=false});
                    
                    

                    In dem falle würde dann bei "forceChange=false" der setState Befehl eben selbst überprüfen ob sich "val" wirklich ändert und dann eben nur im falle einer Änderung wirklich weitermachen. Und forceChange würde natürlich per default auf true stehen zwecks rückwärts-kompatibilität. Denn wenn diese Möglichkeit geschaffen würde, dann müssten eben genau die Adapter die reine Pull-Szenarien bedienen nicht immer selbst solche recht komplexen Dinge wie Bluefox sie gezeigt hat selbst implementieren.

                    Denkst du das macht Sinn? Wenn ja könnte ich mir das mal anschauen und ggf. euch einen PullRequest dazu schicken wenn ich die Stelle finde und entsprechend angepasst bekomme?!?!

                    @apollon77:

                    Also lokal die Werte Speichern (geht übrigens auch für mehr als 1000 Datensätze noch … wird halt irgendwann zur Speicherverbrauchsfrage. `

                    Naja, ich muss ja nicht wirklich mir die Daten merken sondern kann Sie eben per getState() wie von Bluefox gezeigt vorher abholen und selbst vergleichen, zumindest hab ich das hier so vor zu tun. Chicer wäre natürlich eben besagte "forceChange=false" Anpassungen an setState() :)

                    RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

                    1 Antwort Letzte Antwort
                    0
                    • apollon77A Offline
                      apollon77A Offline
                      apollon77
                      schrieb am zuletzt editiert von
                      #13

                      @jens.maus:

                      Auch wäre es sicherlich sinnvoll wenn man dem Subscribe Befehl eine Option/Möglichkeit hinzufügen könnte nur auf Wertänderungen zu reagieren und nicht auf allgemeine Änderungen (z.b. anpassen der 'ts') `

                      Der JavaScript-Adapter macht das schon so: https://github.com/ioBroker/ioBroker.ja ... some-state

                      Zu der setState-Idee müsste Bluefox was sagen :-)

                      Ingo F

                      Beitrag hat geholfen? Votet rechts unten im Beitrag :-) https://paypal.me/Apollon77 / https://github.com/sponsors/Apollon77

                      • Debug-Log für Instanz einschalten? Admin -> Instanzen -> Expertenmodus -> Instanz aufklappen - Loglevel ändern
                      • Logfiles auf Platte /opt/iobroker/log/… nutzen, Admin schneidet Zeilen ab
                      1 Antwort Letzte Antwort
                      0
                      • jens.mausJ Offline
                        jens.mausJ Offline
                        jens.maus
                        schrieb am zuletzt editiert von
                        #14

                        @apollon77:

                        @jens.maus:

                        Auch wäre es sicherlich sinnvoll wenn man dem Subscribe Befehl eine Option/Möglichkeit hinzufügen könnte nur auf Wertänderungen zu reagieren und nicht auf allgemeine Änderungen (z.b. anpassen der 'ts') `

                        Der JavaScript-Adapter macht das schon so: https://github.com/ioBroker/ioBroker.ja ... some-state `

                        Na dann sollte doch IMHO der adapter.subscribeStates() Methode die gleiche Funktionalität spendiert werden ;-)

                        @apollon77:

                        Zu der setState-Idee müsste Bluefox was sagen :-) `

                        Na dann hoffe ich mal er liest hier aufmerksam mit. :) Gerne kann ich auch (um die Verständigung zu verbessern) das ganze nochmal in Englisch verfassen wenn das helfen sollte.

                        RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

                        1 Antwort Letzte Antwort
                        0
                        • apollon77A Offline
                          apollon77A Offline
                          apollon77
                          schrieb am zuletzt editiert von
                          #15

                          Denke Deutsch passt :-)

                          Beitrag hat geholfen? Votet rechts unten im Beitrag :-) https://paypal.me/Apollon77 / https://github.com/sponsors/Apollon77

                          • Debug-Log für Instanz einschalten? Admin -> Instanzen -> Expertenmodus -> Instanz aufklappen - Loglevel ändern
                          • Logfiles auf Platte /opt/iobroker/log/… nutzen, Admin schneidet Zeilen ab
                          1 Antwort Letzte Antwort
                          0
                          • jens.mausJ Offline
                            jens.mausJ Offline
                            jens.maus
                            schrieb am zuletzt editiert von
                            #16

                            Hier noch ein Argument dafür eine setState() option zu schaffen bei der nur bei Änderungen des val wertes wirklich das setState durchkommt:

                            2017-01-20 14:01:49.187  - info: admin.0 Unsubscribe from all states, except system's, because over 3 seconds the number of events is over 60 (in last second 0)
                            2017-01-20 14:02:20.636  - info: admin.0 Subscribe on all states again
                            
                            

                            Dies passiert bei mir jetzt bei jedem Abholen der Datenwerte (jede X Minuten). Hab zwar nun die Methode die Bluefox hier beschrieben hat implementiert und das klappt auch gut, trotzdem denke ich eine Erweiterung der setState() method könnte nicht schaden.

                            RaspberryMatic @ PromoxVE mit ~190 HomeMatic Geräten + ioBroker – GitHub – GitHub Sponsors / PayPal

                            1 Antwort Letzte Antwort
                            0
                            • AlCalzoneA Offline
                              AlCalzoneA Offline
                              AlCalzone
                              Developer
                              schrieb am zuletzt editiert von
                              #17

                              @jens.maus:

                              Es geht hier natürlich um die Entwicklung eines eigenen Adapters, dort gibt es nicht setState() sondern eben "adapter.setState()" genauso wie "adapter.getState()" und das verhält sich leider auch etwas anders, denn es ist immer asynchron sodass sowas z.B. nicht zu funktionieren scheint:

                              for(var i=0; i < 100; i++) {
                                var newval = i;
                                var stateName = "test." + i;
                                adapter.getState(stateName, function(err, state) {
                                  if(state.val != newval)
                                    adapter.setState(stateName, {ack: true, val: newval);
                                });
                              }
                              
                              

                              Das Problem hierbei ist, wie gesagt, das adapter.getState() asynchron ist und somit "newval" und "stateName" innerhalb der anyonmen Funktion die an adapter.getState() übergeben wird zur Ausführungszeit leider die falschen werte hat. Zumindest ist das hier gerade der Fall. `

                              Bin ein bisschen spät mit der Antwort, aber vielleicht hilft es ja noch zum Verständnis. Bluefox hat dir eine recht elegante Version geschrieben, die sequentiell abläuft. Man kann das Problem aber auch lösen, indem man innerhalb der Schleife eine Funktion definiert, die die Schleifenvariable kapselt -> Stichwort Closure.

                              for(var i=0; i < 100; i++) {
                                // Hier beginnt die umhüllende Funktion
                                (function(i) {
                                  // Der Wert von i ändert sich innerhalb dieser Funktion nicht mehr, er ist gekapselt
                                  var newval = i;
                                  var stateName = "test." + i;
                                  adapter.getState(stateName, function(err, state) {
                                    if(state.val != newval)
                                      adapter.setState(stateName, {ack: true, val: newval);
                                  });
                                // und hier wird die Funktion aufgerufen und der aktuelle Wert der Schleifenvariable übergeben
                                })(i);
                              }
                              
                              

                              Der Code ist ungetestet, sollte aber laufen. Ich hoffe, ich habe mich jetzt nicht vertippt.

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

                              1 Antwort Letzte Antwort
                              0
                              Antworten
                              • In einem neuen Thema antworten
                              Anmelden zum Antworten
                              • Älteste zuerst
                              • Neuste zuerst
                              • Meiste Stimmen


                              Support us

                              ioBroker
                              Community Adapters
                              Donate

                              910

                              Online

                              32.5k

                              Benutzer

                              81.9k

                              Themen

                              1.3m

                              Beiträge
                              Community
                              Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                              ioBroker Community 2014-2025
                              logo
                              • Anmelden

                              • Du hast noch kein Konto? Registrieren

                              • Anmelden oder registrieren, um zu suchen
                              • Erster Beitrag
                                Letzter Beitrag
                              0
                              • Home
                              • Aktuell
                              • Tags
                              • Ungelesen 0
                              • Kategorien
                              • Unreplied
                              • Beliebt
                              • GitHub
                              • Docu
                              • Hilfe