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. Skripten / Logik
  4. JavaScript
  5. [gelöst] History per script auslesen: Wie warten auf Daten?

NEWS

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

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

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

[gelöst] History per script auslesen: Wie warten auf Daten?

Geplant Angeheftet Gesperrt Verschoben JavaScript
10 Beiträge 4 Kommentatoren 785 Aufrufe 2 Watching
  • Ä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.
  • D Offline
    D Offline
    Delphinis
    schrieb am zuletzt editiert von Delphinis
    #1

    Hallo,
    ich möchte eine Tabelle mit Daten aus der History befüllen.
    Dazu frage ich die Daten mit

    sendTo('history.0', 'getHistory', {
        id: Ereignisdp,
        options: {
            end:       Date.now(),
            count:     20,
        }
    }, function (result) {
    }
    

    ab.
    Nun ist meine "Abfüllung" der Daten fertig, bevor ich die Daten von sendTo zurückbekomme. Offenbar läuft das asynchron. Wie kann ich warten, bis ich die Daten bekomme?

    D OliverIOO 2 Antworten Letzte Antwort
    0
    • D Delphinis

      Hallo,
      ich möchte eine Tabelle mit Daten aus der History befüllen.
      Dazu frage ich die Daten mit

      sendTo('history.0', 'getHistory', {
          id: Ereignisdp,
          options: {
              end:       Date.now(),
              count:     20,
          }
      }, function (result) {
      }
      

      ab.
      Nun ist meine "Abfüllung" der Daten fertig, bevor ich die Daten von sendTo zurückbekomme. Offenbar läuft das asynchron. Wie kann ich warten, bis ich die Daten bekomme?

      D Offline
      D Offline
      Delphinis
      schrieb am zuletzt editiert von Delphinis
      #2

      @delphinis
      Hab einen Weg gefunden:
      Ich fülle meine Daten am Ende der Funktion (noch im callback, anstatt ausserhalb) ab.
      Es würde mich trotzdem für andere Fälle interessieren, wie man auf eine Antwort der History warten kann....

      F 2 Antworten Letzte Antwort
      0
      • D Delphinis

        @delphinis
        Hab einen Weg gefunden:
        Ich fülle meine Daten am Ende der Funktion (noch im callback, anstatt ausserhalb) ab.
        Es würde mich trotzdem für andere Fälle interessieren, wie man auf eine Antwort der History warten kann....

        F Offline
        F Offline
        fastfoot
        schrieb am zuletzt editiert von fastfoot
        #3

        @delphinis nimm

        async function history(){
          let result = await sendToAsync('history.0', 'getHistory', {
            id: Ereignisdp,
            options: {
                end:       Date.now(),
                count:     20,
            }
          }
          return result 
        }
        
        async function test(){
           let result = await history();
           mach_was_mit_result(result) 
        }
        
        test();
        

        iobroker läuft unter Docker auf QNAP TS-451+
        SkriptRecovery: https://forum.iobroker.net/post/930558

        D 1 Antwort Letzte Antwort
        1
        • D Delphinis

          @delphinis
          Hab einen Weg gefunden:
          Ich fülle meine Daten am Ende der Funktion (noch im callback, anstatt ausserhalb) ab.
          Es würde mich trotzdem für andere Fälle interessieren, wie man auf eine Antwort der History warten kann....

          F Offline
          F Offline
          fastfoot
          schrieb am zuletzt editiert von
          #4

          @delphinis bitte den geänderten Beitrag beachten, da fehlte noch was Entscheidendes!

          iobroker läuft unter Docker auf QNAP TS-451+
          SkriptRecovery: https://forum.iobroker.net/post/930558

          1 Antwort Letzte Antwort
          0
          • D Delphinis

            Hallo,
            ich möchte eine Tabelle mit Daten aus der History befüllen.
            Dazu frage ich die Daten mit

            sendTo('history.0', 'getHistory', {
                id: Ereignisdp,
                options: {
                    end:       Date.now(),
                    count:     20,
                }
            }, function (result) {
            }
            

            ab.
            Nun ist meine "Abfüllung" der Daten fertig, bevor ich die Daten von sendTo zurückbekomme. Offenbar läuft das asynchron. Wie kann ich warten, bis ich die Daten bekomme?

            OliverIOO Offline
            OliverIOO Offline
            OliverIO
            schrieb am zuletzt editiert von
            #5

            @delphinis said in History per script auslesen: Wie warten auf Daten?:

            sendTo('history.0', 'getHistory', {
                id: Ereignisdp,
                options: {
                    end:       Date.now(),
                    count:     20,
                }
            }, function (result) {
              // ab hier callback
            }
            

            Der Befehl sendTo hat 4 Parameter

            1. Die Adapterinstanz an die was gesendet werden soll
            2. der Befehl der ausgeführt werden soll
            3. evtl Parameter
            4. Eine Callback Funktion die aufgerufen wird, wenn der andere Adapter alles ausgeführt hat.

            Daher, wenn ich deine eigene Antwort richtig interpretiere, hast du das schon selbst herausgefunden.

            Fastfoot hat noch auf eine weitere Variante von sendTo hingewiesen.
            sendToAsync ist die Promise-Version der Funktion. da kann dann mit await darauf gewartet werden. Der Einsatz von promises kann einen Programmablauf klarer darstellen, da ansonsten bei mehreren aufeinander gestaffelten Callback-Funktionen es schnell unübersichtlich wird.

            Meine Adapter und Widgets
            TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
            Links im Profil

            1 Antwort Letzte Antwort
            2
            • F fastfoot

              @delphinis nimm

              async function history(){
                let result = await sendToAsync('history.0', 'getHistory', {
                  id: Ereignisdp,
                  options: {
                      end:       Date.now(),
                      count:     20,
                  }
                }
                return result 
              }
              
              async function test(){
                 let result = await history();
                 mach_was_mit_result(result) 
              }
              
              test();
              
              D Offline
              D Offline
              Delphinis
              schrieb am zuletzt editiert von Delphinis
              #6

              @fastfoot
              Hallo, ich hab das mal versucht, bin aber nicht weitergekommen und hab's mal zurückgestellt. Nun hab ich wieder etwas Zeit und möchte dort weiterkommen.
              Das Problem ist nun, dass ich nicht wirklich an die Daten komme, weil die Struktur offenbar verschachtelt ist und in der Test Funktion nicht mehr bekannt ist. Ich kann also nicht mit result.result die Daten abfragen:
              87a9a95e-5971-43e2-9e89-4ab796e9d9c7-grafik.png

              Hier nochmal mein Code:

              const Ereignisdp = 'alias.0.TH-OutNO.Temp';
              async function history(){
                let result = await sendToAsync('history.0', 'getHistory', {
                  id: Ereignisdp,
                  options: {
                      end:       Date.now(),
                      count:     20,
                  }
                });
                return result 
              }
              
              async function test(){
                 let result = await history();
                 for (var i = 0; i < result.result.length; i++) {
                  console.log(new Data(result.result[i].ts + ', ' + result.result[i].val));
                 }                    
              }
              
              test();
              

              Vielleicht ist die Struktur je nach Resultat auch nicht immer gleich?
              Ich arbeite übrigens wenn es geht mit Typescript weil ich das von anderen Sprachen gewohnt bin. Wenn ich also wüsste wie die Klasse aufgebaut ist, könnte mir das ev. weiterhelfen.
              In der Doku konnte ich das nicht finden, und typeof(result) liefert mir auch nur "object"
              Eine Lösung in Javascript ist mir aber auch recht.

              T 1 Antwort Letzte Antwort
              0
              • D Delphinis

                @fastfoot
                Hallo, ich hab das mal versucht, bin aber nicht weitergekommen und hab's mal zurückgestellt. Nun hab ich wieder etwas Zeit und möchte dort weiterkommen.
                Das Problem ist nun, dass ich nicht wirklich an die Daten komme, weil die Struktur offenbar verschachtelt ist und in der Test Funktion nicht mehr bekannt ist. Ich kann also nicht mit result.result die Daten abfragen:
                87a9a95e-5971-43e2-9e89-4ab796e9d9c7-grafik.png

                Hier nochmal mein Code:

                const Ereignisdp = 'alias.0.TH-OutNO.Temp';
                async function history(){
                  let result = await sendToAsync('history.0', 'getHistory', {
                    id: Ereignisdp,
                    options: {
                        end:       Date.now(),
                        count:     20,
                    }
                  });
                  return result 
                }
                
                async function test(){
                   let result = await history();
                   for (var i = 0; i < result.result.length; i++) {
                    console.log(new Data(result.result[i].ts + ', ' + result.result[i].val));
                   }                    
                }
                
                test();
                

                Vielleicht ist die Struktur je nach Resultat auch nicht immer gleich?
                Ich arbeite übrigens wenn es geht mit Typescript weil ich das von anderen Sprachen gewohnt bin. Wenn ich also wüsste wie die Klasse aufgebaut ist, könnte mir das ev. weiterhelfen.
                In der Doku konnte ich das nicht finden, und typeof(result) liefert mir auch nur "object"
                Eine Lösung in Javascript ist mir aber auch recht.

                T Nicht stören
                T Nicht stören
                ticaki
                schrieb am zuletzt editiert von ticaki
                #7

                @delphinis

                a)

                async function history(){
                  let result = await sendToAsync('history.0', 'getHistory', {
                    id: Ereignisdp,
                    options: {
                        end:       Date.now(),
                        count:     20,
                    }
                  });
                  log(JSON.stringify(result)
                }
                

                Dann hier aus der Antwort einen type bauen lassen und dem mit:
                a.1)
                mein Favorit: (KA ob das im JS-Adapter geht)

                // typen sind nur beispiele haben nix mit der wirklichen Antwort von history.0 zu tun
                type IconScaleElement = {
                    val_min: number;
                    val_max: number;
                    val_best?: number;
                    log10?: 'max' | 'min';
                    mode?: 'mixed' | 'hue' | 'cie';
                };
                
                // hier validieren dass die Daten deinen Typenannahmen entsprechen
                function isIconScaleElement(F: any): F is IconScaleElement {
                    return F && 'val_min' in (F as IconScaleElement) && 'val_max' in (F as IconScaleElement);
                }
                
                async function history(): IconScaleElement{
                  let result:any = await sendToAsync('history.0', 'getHistory', {
                    id: Ereignisdp,
                    options: {
                        end:       Date.now(),
                        count:     20,
                    }
                  });
                  if (isIconScaleElement(result)
                    return result;
                  else 
                    throw new Error('ups something goes wrong!');
                }
                

                a.2)

                async function history(): myType {
                  let result = await sendToAsync('history.0', 'getHistory', {
                    id: Ereignisdp,
                    options: {
                        end:       Date.now(),
                        count:     20,
                    }
                  });
                 return result as myType;
                }
                

                verwenden.

                b)

                async function history(): any{
                  let result:any = await sendToAsync('history.0', 'getHistory', {
                    id: Ereignisdp,
                    options: {
                        end:       Date.now(),
                        count:     20,
                    }
                  });
                  return result // ka ob hier auch noch ein as any hin muß
                }
                

                Weather-Warnings Espresense NSPanel-Lovelace-ui Tagesschau

                Spenden

                D 1 Antwort Letzte Antwort
                1
                • T ticaki

                  @delphinis

                  a)

                  async function history(){
                    let result = await sendToAsync('history.0', 'getHistory', {
                      id: Ereignisdp,
                      options: {
                          end:       Date.now(),
                          count:     20,
                      }
                    });
                    log(JSON.stringify(result)
                  }
                  

                  Dann hier aus der Antwort einen type bauen lassen und dem mit:
                  a.1)
                  mein Favorit: (KA ob das im JS-Adapter geht)

                  // typen sind nur beispiele haben nix mit der wirklichen Antwort von history.0 zu tun
                  type IconScaleElement = {
                      val_min: number;
                      val_max: number;
                      val_best?: number;
                      log10?: 'max' | 'min';
                      mode?: 'mixed' | 'hue' | 'cie';
                  };
                  
                  // hier validieren dass die Daten deinen Typenannahmen entsprechen
                  function isIconScaleElement(F: any): F is IconScaleElement {
                      return F && 'val_min' in (F as IconScaleElement) && 'val_max' in (F as IconScaleElement);
                  }
                  
                  async function history(): IconScaleElement{
                    let result:any = await sendToAsync('history.0', 'getHistory', {
                      id: Ereignisdp,
                      options: {
                          end:       Date.now(),
                          count:     20,
                      }
                    });
                    if (isIconScaleElement(result)
                      return result;
                    else 
                      throw new Error('ups something goes wrong!');
                  }
                  

                  a.2)

                  async function history(): myType {
                    let result = await sendToAsync('history.0', 'getHistory', {
                      id: Ereignisdp,
                      options: {
                          end:       Date.now(),
                          count:     20,
                      }
                    });
                   return result as myType;
                  }
                  

                  verwenden.

                  b)

                  async function history(): any{
                    let result:any = await sendToAsync('history.0', 'getHistory', {
                      id: Ereignisdp,
                      options: {
                          end:       Date.now(),
                          count:     20,
                      }
                    });
                    return result // ka ob hier auch noch ein as any hin muß
                  }
                  
                  D Offline
                  D Offline
                  Delphinis
                  schrieb am zuletzt editiert von Delphinis
                  #8

                  @ticaki
                  Danke für den Hinweis mit log(JSON.stringify(result)
                  so kann ich da Daten nun schon in der funktion getHistory abholen. Das Abfüllen funktioniert eigentlich, aber das mit dem await nicht:

                  class Data {
                      ts: number;
                      value: any;
                      constructor(ts:number, value:any) {
                          this.ts = ts;
                          this.value = value;
                      }
                  }
                  
                  async function getHistoryData(from:number, to:number, DP:string, resArray:Array<Data>) {
                      let startTime = Date.now();
                      sendTo('history.0', 'getHistory', {
                          id: DP,
                          options: {
                              start:      from,
                              end:        to,
                              aggregate: 'onchange'
                          }
                      }, function (result) { 
                          console.log('Zeit für History-Daten holen: ' + (Date.now() - startTime) + 'ms');
                          let count = 0;
                          for (var i = 0; i < result.result.length; i++) {
                              resArray.push(new Data(result.result[i].ts, result.result[i].val));
                              ++count;                  
                          }
                          console.log('Anzahl in getHistory:' + count);
                      });
                  }
                  
                  async function get(){
                      await getHistoryData(new Date('2024-06-23 00:00').getTime(), new Date('2024-06-23 23:59:59').getTime(), 'alias.0.TH-OutNO.Temp', dataNO);
                  
                      // hier sind die Daten noch nicht vorhanden!
                  
                      dataNO.forEach(function (data) {
                          console.log(data.ts + '; ' + data.value);
                      });
                  }
                  
                  let dataNO:Array<Data> = [];
                  get();
                  

                  Aber was ich nicht begreife ist: Eigentlich sollte doch mit await getHistoryData auf das abarbeiten gewartet werden. die Daten sind aber nach diesem Aufruf noch nicht da. Man müsste das noch abwarten. Ich dachte await sei genau dazu da, oder verstehe ich das falsch?
                  Hab dazu folgendes gefunden:
                  "The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or at the top level of a module."
                  Ich wollte dem Funktionsaufruf get() auch noch ein await voranstellen um zu testen, ob es daran liegt, aber das gibt mir einen Interpreter-Fehler:
                  "
                  'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module.(1375)
                  "
                  "
                  Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher.(1378)
                  "
                  Ich weiss jetzt nicht ob das überhaupt etwas bringen würde, aber ich wüsste nun auch nicht wo man 'module' option so setzen kann.

                  PS: ich brauche die Daten aber ausserhalb der Funktion getHistoryData(), da ich sie mit anderen History-Daten, welche auch geholt werden müssen, verrechnen kann.
                  Ich hab's mal mit await sleep(50); versucht. Tatsächlich sind die Daten danach vorhanden, obwohl auch hier auf top level dieser Interpreter-Fehler kommt?!
                  Nur ist das lediglich für einen Versuch gut, denn das Holen dauert mal 40, mal 100ms...

                  T 1 Antwort Letzte Antwort
                  0
                  • D Delphinis

                    @ticaki
                    Danke für den Hinweis mit log(JSON.stringify(result)
                    so kann ich da Daten nun schon in der funktion getHistory abholen. Das Abfüllen funktioniert eigentlich, aber das mit dem await nicht:

                    class Data {
                        ts: number;
                        value: any;
                        constructor(ts:number, value:any) {
                            this.ts = ts;
                            this.value = value;
                        }
                    }
                    
                    async function getHistoryData(from:number, to:number, DP:string, resArray:Array<Data>) {
                        let startTime = Date.now();
                        sendTo('history.0', 'getHistory', {
                            id: DP,
                            options: {
                                start:      from,
                                end:        to,
                                aggregate: 'onchange'
                            }
                        }, function (result) { 
                            console.log('Zeit für History-Daten holen: ' + (Date.now() - startTime) + 'ms');
                            let count = 0;
                            for (var i = 0; i < result.result.length; i++) {
                                resArray.push(new Data(result.result[i].ts, result.result[i].val));
                                ++count;                  
                            }
                            console.log('Anzahl in getHistory:' + count);
                        });
                    }
                    
                    async function get(){
                        await getHistoryData(new Date('2024-06-23 00:00').getTime(), new Date('2024-06-23 23:59:59').getTime(), 'alias.0.TH-OutNO.Temp', dataNO);
                    
                        // hier sind die Daten noch nicht vorhanden!
                    
                        dataNO.forEach(function (data) {
                            console.log(data.ts + '; ' + data.value);
                        });
                    }
                    
                    let dataNO:Array<Data> = [];
                    get();
                    

                    Aber was ich nicht begreife ist: Eigentlich sollte doch mit await getHistoryData auf das abarbeiten gewartet werden. die Daten sind aber nach diesem Aufruf noch nicht da. Man müsste das noch abwarten. Ich dachte await sei genau dazu da, oder verstehe ich das falsch?
                    Hab dazu folgendes gefunden:
                    "The await operator is used to wait for a Promise and get its fulfillment value. It can only be used inside an async function or at the top level of a module."
                    Ich wollte dem Funktionsaufruf get() auch noch ein await voranstellen um zu testen, ob es daran liegt, aber das gibt mir einen Interpreter-Fehler:
                    "
                    'await' expressions are only allowed at the top level of a file when that file is a module, but this file has no imports or exports. Consider adding an empty 'export {}' to make this file a module.(1375)
                    "
                    "
                    Top-level 'await' expressions are only allowed when the 'module' option is set to 'es2022', 'esnext', 'system', or 'nodenext', and the 'target' option is set to 'es2017' or higher.(1378)
                    "
                    Ich weiss jetzt nicht ob das überhaupt etwas bringen würde, aber ich wüsste nun auch nicht wo man 'module' option so setzen kann.

                    PS: ich brauche die Daten aber ausserhalb der Funktion getHistoryData(), da ich sie mit anderen History-Daten, welche auch geholt werden müssen, verrechnen kann.
                    Ich hab's mal mit await sleep(50); versucht. Tatsächlich sind die Daten danach vorhanden, obwohl auch hier auf top level dieser Interpreter-Fehler kommt?!
                    Nur ist das lediglich für einen Versuch gut, denn das Holen dauert mal 40, mal 100ms...

                    T Nicht stören
                    T Nicht stören
                    ticaki
                    schrieb am zuletzt editiert von ticaki
                    #9

                    @delphinis
                    Du benutzt sendTo() das ist eine Funktion mit callback. Dann könntest du mit Promise arbeiten. Einfach ist es aber ohne callback mit const result = await sendToAsync()

                    Wieso sollte man await auf der oberen Ebene benutzen. kannst doch einfach alles in async main(){} packen und am ende vom skript ein main()

                    Weather-Warnings Espresense NSPanel-Lovelace-ui Tagesschau

                    Spenden

                    D 1 Antwort Letzte Antwort
                    1
                    • T ticaki

                      @delphinis
                      Du benutzt sendTo() das ist eine Funktion mit callback. Dann könntest du mit Promise arbeiten. Einfach ist es aber ohne callback mit const result = await sendToAsync()

                      Wieso sollte man await auf der oberen Ebene benutzen. kannst doch einfach alles in async main(){} packen und am ende vom skript ein main()

                      D Offline
                      D Offline
                      Delphinis
                      schrieb am zuletzt editiert von
                      #10

                      @ticaki
                      Super. Das scheint zu funktionieren. Besten dank!

                      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

                      360

                      Online

                      32.4k

                      Benutzer

                      81.5k

                      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