Skip to content
  • Home
  • 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
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.3k

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

Scheduled Pinned Locked Moved JavaScript
10 Posts 4 Posters 786 Views 2 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.
  • D Offline
    D Offline
    Delphinis
    wrote on last edited by 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 Replies Last reply
    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
      wrote on last edited by 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 Replies Last reply
      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
        wrote on last edited by 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 Reply Last reply
        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
          wrote on last edited by
          #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 Reply Last reply
          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
            wrote on last edited by
            #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 Reply Last reply
            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
              wrote on last edited by 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 Reply Last reply
              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 Do not disturb
                T Do not disturb
                ticaki
                wrote on last edited by 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 Reply Last reply
                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
                  wrote on last edited by 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 Reply Last reply
                  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 Do not disturb
                    T Do not disturb
                    ticaki
                    wrote on last edited by 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 Reply Last reply
                    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
                      wrote on last edited by
                      #10

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

                      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

                      878

                      Online

                      32.4k

                      Users

                      81.5k

                      Topics

                      1.3m

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

                      • Don't have an account? Register

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