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

  • Default (No Skin)
  • No Skin
Collapse
Logo
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. HowTo: Zusatz-Programme fuer jarvis v3

NEWS

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

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

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

HowTo: Zusatz-Programme fuer jarvis v3

Scheduled Pinned Locked Moved JavaScript
javascript
889 Posts 33 Posters 211.2k Views 37 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.
  • M Offline
    M Offline
    Meikie
    wrote on last edited by
    #394

    tibberHTML

    Hi, ich bin gerade dabei die tibber-tools zu installieren. Bei tibberHTMl habe ich alles nach Anleitung umgesetzt.
    Lediglich im Script habe ich alle User-Ordner geändert in

    0_userdata.0.Strom.tibberHistory
    

    Das hat auch funktioniert. Also in der Ordnerstruktur ist alles so vorhanden, wie es sein soll. Auch unter Jarvis habe ich unter Berücksichtigung meiner eigenen Ordnerstruktur die Geräte eingefügt.

    Mein Problem ist, dass mir die Diagramme nicht angezeigt bekomme. Im Ordner sind auch die 2 Dateien htmltoday und htmltomorrow leer.

    Was könnte ich falsch gemacht haben?

    Vielen Dank.

    PS:das Script habe ich in der App Skripte eingefügt.

    M 1 Reply Last reply
    0
    • M Meikie

      tibberHTML

      Hi, ich bin gerade dabei die tibber-tools zu installieren. Bei tibberHTMl habe ich alles nach Anleitung umgesetzt.
      Lediglich im Script habe ich alle User-Ordner geändert in

      0_userdata.0.Strom.tibberHistory
      

      Das hat auch funktioniert. Also in der Ordnerstruktur ist alles so vorhanden, wie es sein soll. Auch unter Jarvis habe ich unter Berücksichtigung meiner eigenen Ordnerstruktur die Geräte eingefügt.

      Mein Problem ist, dass mir die Diagramme nicht angezeigt bekomme. Im Ordner sind auch die 2 Dateien htmltoday und htmltomorrow leer.

      Was könnte ich falsch gemacht haben?

      Vielen Dank.

      PS:das Script habe ich in der App Skripte eingefügt.

      M Online
      M Online
      MCU
      wrote on last edited by MCU
      #395

      @meikie Das Programm nutzt die vorgegebene Struktur, da muss ich mal anpassen.
      8ce22f5f-c1ca-4d4a-acec-1ef20b392371-image.png
      Bezieht sich aber nur auf VIS.
      Ich habe es jetzt auch so eingestellt und funktioniert.

      Zeig mal die Bilder von den Objekten.
      2ecbbfa6-4a3c-4963-9735-b2469cf268dc-image.png

      a7a597c7-a247-46d0-abcf-25ccbfc3bab7-image.png

      NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
      Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Meikie
        wrote on last edited by
        #396

        Also ich habe im Skript auch den Punkt angepasst.

        // createHtmlFile();
        async function createHtmlFile(name) {
            let dp = '';
            let file = '';
            if(name == 'PricesToday'){
                dp = '0_userdata.0.Strom.tibberHistory.htmlToday';
                file = 'today';
            }else{
                dp = '0_userdata.0.Strom.tibberHistory.htmlTomorrow';
                file = 'tomorrow';
            }
        
        M 1 Reply Last reply
        0
        • M Meikie

          Also ich habe im Skript auch den Punkt angepasst.

          // createHtmlFile();
          async function createHtmlFile(name) {
              let dp = '';
              let file = '';
              if(name == 'PricesToday'){
                  dp = '0_userdata.0.Strom.tibberHistory.htmlToday';
                  file = 'today';
              }else{
                  dp = '0_userdata.0.Strom.tibberHistory.htmlTomorrow';
                  file = 'tomorrow';
              }
          
          M Online
          M Online
          MCU
          wrote on last edited by
          #397

          @meikie Zeig bitte die Objekte.

          NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
          Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

          M 1 Reply Last reply
          0
          • M MCU

            @meikie Zeig bitte die Objekte.

            M Offline
            M Offline
            Meikie
            wrote on last edited by
            #398

            @mcu Bildschirmfoto 2024-01-05 um 23.43.56.png Bildschirmfoto 2024-01-05 um 23.43.09.png

            M 1 Reply Last reply
            0
            • M Meikie

              @mcu Bildschirmfoto 2024-01-05 um 23.43.56.png Bildschirmfoto 2024-01-05 um 23.43.09.png

              M Online
              M Online
              MCU
              wrote on last edited by MCU
              #399

              @meikie Irgendwelche Meldungen im ioBroker-LOG?

              Stelle mal Dein Programm komplett rein.

              NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
              Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

              M 1 Reply Last reply
              0
              • M MCU

                @meikie Irgendwelche Meldungen im ioBroker-LOG?

                Stelle mal Dein Programm komplett rein.

                M Offline
                M Offline
                Meikie
                wrote on last edited by
                #400

                @mcu admin.0
                2024-01-05 23:47:34.290 info <== Disconnect system.user.admin from ::ffff:192.168.178.51 javascript

                Das Einzige.

                M M 2 Replies Last reply
                0
                • M Meikie

                  @mcu admin.0
                  2024-01-05 23:47:34.290 info <== Disconnect system.user.admin from ::ffff:192.168.178.51 javascript

                  Das Einzige.

                  M Offline
                  M Offline
                  Meikie
                  wrote on last edited by
                  #401

                  @meikie ```
                  // *********************************
                  // tibberHTML v1.0.24
                  // *********************************
                  // Copyright ©MCU
                  // v1.0.1 - Erweiterung Umschaltung Line/bar im Graph, Anzeige der Werte in Tabelle
                  // v1.0.2 - Vis Auswahl -> fete Breite für VIS, darkMode
                  // v1.0.3 - Min,max,avg kleiner, untereinander, rechts Breite kleiner
                  // v1.0.4 - ShowMinMaxAvgTexte optional
                  // v1.0.5 - toolBox -Speichern mit Namen+Datum
                  // v1.0.6 - y-Skala auf beiden Kurven gleich
                  // v1.0.7 - splitNumber auf 10 vorher 3, grid rechts 10 statt 30, visualMap - mobile optimiert
                  // v1.0.8 - CurveArea optional, Korrektur wenn tomorrow.mim = 0 -> graphMin =0
                  // v1.0.9 - graphMax angepasst auf nächste 0.01
                  // v1.0.10- graphMin angepassz auf nächste 0.01
                  // v1.0.11- Label optional, falls man schon Widget-Title nutzt
                  // v1.0.12 - Trennung Label Today und Tomorrow
                  // v1.0.13 - optionaler Text für Tomorrow Wait
                  // v1.0.14 - automatischer Reload bei Umschaltung wait-Text Tomorrow
                  // v1.0.15 - aktuelle Zeit highlightCurrentHour
                  // v1.0.16 - Symbol für Line aktuelle Stunde angepasst
                  // v1.0.17 - stepped line hinzugefügt, Korrekturen graphMin
                  // v1.0.18 - Korrektur showwait
                  // v1.0.19 - Korrektur showwait
                  // v1.0.20 - Abschaltung Anzeige Graph, wenn leer, Korrektur highlightPoint
                  // v1.0.21 - Korrektur dataNull für visualMapPieces
                  // v1.0.22 - Inhalt von DPs als Datei speichern
                  // v1.0.23 - Korrektur 1.Farbelement lte > maxValue
                  // v1.0.24 - Korrektur 1. Farbelement Umstellung Linie, falsche Berechnung
                  // ToDo
                  // - optionale Zeit vor günstiger Stunde telegram senden, alexa info, pushOver senden
                  // - Ersparnis in Prozent -> Tabelle / Anzeige?
                  // - Stunden erweitern für steppedLine?

                  let logging = true;
                  let tibberDP = '0_userdata.0.Strom.tibberHistory';
                  let dbHistoryDP = tibberDP + '.historyDB';
                  let tibberGraphTypeDP = tibberDP + '.graphTyp'; // bar oder line
                  let tibberInstDP = tibberDP + '.instanz'; // 0
                  let tibberColorDP = tibberDP + '.colorJSON'; // visualMapPieces [ {gt: 0, lte: 0.15, color: "lightgreen"},]
                  let tibberHTMLTodayDP = tibberDP + '.htmlToday';
                  let tibberHTMLTomorrowDP = tibberDP + '.htmlTomorrow';
                  let tibberShowTaxEnergyDP = tibberDP + '.showTaxEnergy'; // boolean
                  let tibberShowMinMaxAvgDP = tibberDP + '.showMinMaxAvg'; // boolean
                  let visDP = tibberDP + '.vis';
                  let darkModeDP = tibberDP + '.darkMode';
                  let tibberShowMinMaxAvgTextDP = tibberDP + '.showMinMaxAvgText';
                  let tibberAreaDP = tibberDP + '.curveArea';
                  let tibberShowLabelTodayDP = tibberDP + '.showLabelToday';
                  let tibberLabelTodayDP = tibberDP + '.labelToday';
                  let tibberShowLabelTomorrowDP = tibberDP + '.showLabelTomorrow';
                  let tibberLabelTomorrowDP = tibberDP + '.labelTomorrow';
                  let tibberWaitTomorrowTextDP = tibberDP + '.labelTomorrowWait';
                  let tibberShowWaitLabelTomorrowDP = tibberDP + '.showLabelTomorrowWait';
                  let tibberHighlightCurrentHourDP = tibberDP +'.highlightCurrentHour';
                  let tibberHighlightColorDarkDP = tibberDP + '.highlightColorDark';
                  let tibberHighlightColorLightDP = tibberDP + '.highlightColorLight';
                  let tibberSteppedLineDP = tibberDP + '.steppedLine';
                  let tibberShowGraphIfEmptyDP = tibberDP + '.showGraphIfEmpty';

                  let dpArray = [];

                  createStateAsync(tibberHTMLTodayDP, {read: true, write: true, name: "Tibber HTML für Heute", desc:"HTML-DP", type: "string", role: "", def: "" });
                  createStateAsync(tibberHTMLTomorrowDP, {read: true, write: true, name: "Tibber HTML für Morgen", desc:"HTML-DP", type: "string", role: "", def: "" });
                  createStateAsync(tibberColorDP, {read: true, write: true, name: "Farbdefinition für Balken", desc:"JSON-DP", type: "string", role: "",
                  def: JSON.stringify([{ 'gt': 0,'lte': 0.15, 'color': 'lightgreen' },
                  {'gt': 0.15,'lte': 0.22,'color': 'green'},
                  {'gt': 0.22,'lte': 0.29,'color': 'yellow'},
                  {'gt': 0.29,'lte': 0.35,'color': 'orange'},
                  {'gt': 0.35,'color': 'red'}]) });
                  createStateAsync(tibberGraphTypeDP, {read: true, write: true, name: "Tibber Graph Typ Auswahl", desc:"GraphType-DP", type: "string", role: "", states: {"bar":"bar","line":"line"} ,def: "bar" });
                  createStateAsync(tibberInstDP, {read: true, write: true, name: "Tibber Instanz", desc:"Instanz-DP", type: "string", role: "", def: "0" });
                  createStateAsync(tibberShowTaxEnergyDP, {read: true, write: true, name: "Tax und Energy anzeigen bei Hover", desc:"Show-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberShowMinMaxAvgDP, {read: true, write: true, name: "Min, Max und Mittelwert anzeigen", desc:"Show-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberShowMinMaxAvgTextDP, {read: true, write: true, name: "Min, Max und Mittelwert Texte anzeigen", desc:"ShowText-DP", type: "boolean", role: "", def: false });
                  createStateAsync(visDP, {read: true, write: true, name: "Welche VIS soll genutzt werden?", desc:"VIS-DP", type: "string", role: "",states: {"jarvis":"jarvis","VIS":"VIS"} , def: "jarvis" });
                  createStateAsync(darkModeDP, {read: true, write: true, name: "DarkMode an?", desc:"DarkMode-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberAreaDP, {read: true, write: true, name: "Fläche unter Kurve?", desc:"CurveArea-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberShowLabelTodayDP, {read: true, write: true, name: "Label Today anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberLabelTodayDP, {read: true, write: true, name: "Label Today für das Chart", desc:"Label-DP", type: "string", role: "", def: "Today-Tageswerte" });
                  createStateAsync(tibberShowLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Tomorrow-Tageswerte" });
                  createStateAsync(tibberShowWaitLabelTomorrowDP, {read: true, write: true, name: "Label Wait Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberWaitTomorrowTextDP, {read: true, write: true, name: "Label Wait Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Werte erst ab 14.00 Uhr verfügbar" });
                  createStateAsync(tibberHighlightCurrentHourDP, {read: true, write: true, name: "Aktuelle Stunde markieren?", desc:"HighlightAktHour-DP", type: "boolean", role: "", def: false });
                  createStateAsync(tibberHighlightColorDarkDP, {read: true, write: true, name: "HighLight Color DarkMode", desc:"HighLight Dark-DP", type: "string", role: "", def: "white" });
                  createStateAsync(tibberHighlightColorLightDP, {read: true, write: true, name: "HighLight Color LightMode", desc:"HighLight Light-DP", type: "string", role: "", def: "grey" });
                  createStateAsync(tibberSteppedLineDP, {read: true, write: true, name: "Gestufte Linie?", desc:"SteppedLine-DP", type: "boolean", role: "", def: false });

                  createStateAsync(tibberShowGraphIfEmptyDP, {read: true, write: true, name: "Graph anzeigen ohne Daten?", desc:"showGraph-DP", type: "boolean", role: "", def: false });

                  // getHistoryAdapter();

                  // setDPs('0'); // -> dpArray

                  setTimeout(function(){
                  getTibberData(dpArray);
                  let inst = getState(tibberInstDP).val;
                  $('tibberlink.'+inst+'.Homes.*.PricesTomorrow.json').on(function(obj) {
                  setTimeout(function(){
                  getTibberData(dpArray);
                  },3000)
                  });

                  $('tibberlink.'+inst+'.Homes.*.PricesToday.json').on(function(obj) {
                      setTimeout(function(){
                          getTibberData(dpArray);
                      },3000);
                  });
                  

                  },3000);

                  let scheduleId ;
                  if(getState(tibberHighlightColorDarkDP).val){
                  scheduleId = schedule('00 * * * *', () => {

                      getTibberData(dpArray);
                  })
                  

                  }

                  on({id: tibberHighlightCurrentHourDP, change: "any"}, function (obj) {
                  let value = obj.state.val;
                  if(value){
                  getTibberData(dpArray);
                  clearSchedule(scheduleId);
                  scheduleId = schedule('00 * * * *', () => {
                  getTibberData(dpArray);
                  })
                  }else{
                  clearSchedule(scheduleId);
                  getTibberData(dpArray);
                  }
                  })
                  on({id: tibberShowTaxEnergyDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberColorDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  on({id: tibberShowMinMaxAvgDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberShowMinMaxAvgTextDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  on({id: tibberGraphTypeDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: darkModeDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberAreaDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberShowLabelTodayDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberShowLabelTomorrowDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  on({id: tibberShowWaitLabelTomorrowDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  on({id: tibberHighlightColorDarkDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  on({id: tibberHighlightColorLightDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberSteppedLineDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });
                  on({id: tibberShowGraphIfEmptyDP, change: "any"}, function (obj) {
                  getTibberData(dpArray);
                  });

                  function getTibberData(arr){
                  // arr wird nur für eCharts benötigt

                  // tibberDataDP selbst ermitteln
                  let tibberInst = getState(tibberInstDP).val;
                  let priceArr = ['PricesToday','PricesTomorrow'];
                  for(let x=0;x< priceArr.length;x++){
                      let tibberData = [];
                      let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.'+priceArr[x]+'.json')
                      if(tibberLink[0] != undefined){
                          let tblLevel = levelObject(tibberLink[0]);
                          let dpLeveltbl = getDPLevel(tblLevel,4);
                          let tibberJSON = JSON.parse(getState(dpLeveltbl+'.json').val);
                          // tibberJSON
                          for(let i=0;i<tibberJSON.length;i++){
                              let obj = {};
                              obj.hour     = parseInt(tibberJSON[i].startsAt.substring(11,13));
                              obj.start   = tibberJSON[i].startsAt
                              obj.startTS = new Date(obj.start).getTime();
                              obj.value   = tibberJSON[i].total;
                              obj.energy   = tibberJSON[i].energy;
                              obj.tax   = tibberJSON[i].tax;
                              obj.min = false;
                              obj.max = false;
                              obj.average = false;
                              obj.level = tibberJSON[i].level;
                              tibberData.push(obj);
                          }
                          // average, minium, maximum direkt holen
                          
                          let eleArr = ['average','minimum','maximum'];
                          for(let i=0;i<eleArr.length;i++){
                              let obj = {};
                              switch (eleArr[i]) {
                                      case 'average':
                                          obj.hour     = 'non'
                                          obj.start   = ''
                                          obj.startTS = 0;
                                          obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                          obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                          obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                          obj.min = false;
                                          obj.max = false;
                                          obj.average = true;
                                          obj.level = '';
                                          tibberData.push(obj);
                                          break;
                                      case 'minimum':
                                          obj.hour    = 'non';
                                          obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                          obj.startTS = new Date(obj.start).getTime();
                                          obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                          obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                          obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                          obj.min = true;
                                          obj.max = false;
                                          obj.average = false;
                                          tibberData.push(obj);
                                          break;
                                      case 'maximum':
                                          obj.hour    = 'non';
                                          obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                          obj.startTS = new Date(obj.start).getTime();
                                          obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                          obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                          obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                          obj.min = false;
                                          obj.max = true;
                                          obj.average = false;
                                          tibberData.push(obj);
                                          break;
                                      default: 
                                          break;
                                  }
                          }
                          // log(tibberData);
                          let setechart = false;
                          if(setechart){
                              for(let i=0;i<dpArray.length;i++){
                                  setHistoryData(dpArray[i],tibberObj[levelObject(dpArray[i])[3]]);
                              }
                              seteChartsDP(dpArray);
                          }
                          // log('setHTML');
                          setHTML(tibberData,priceArr[x]);
                          if(getState(visDP).val=='VIS'){
                              createHtmlFile(priceArr[x])
                          }
                      }
                      
                  }
                  

                  }
                  // createHtmlFile();
                  async function createHtmlFile(name) {
                  let dp = '';
                  let file = '';
                  if(name == 'PricesToday'){
                  dp = '0_userdata.0.Strom.tibberHistory.htmlToday';
                  file = 'today';
                  }else{
                  dp = '0_userdata.0.Strom.tibberHistory.htmlTomorrow';
                  file = 'tomorrow';
                  }
                  const htmlContent = getState(dp).val;
                  writeFile('vis.0', '/tibber/'+file+'.html',htmlContent, (err) => {
                  if (err) {
                  console.error('Fehler beim Speichern der HTML-Datei, tibber-Verzeichnis angelegt?', err);
                  } else {
                  console.log('HTML-Datei '+file+'.html erfolgreich gespeichert');
                  }
                  });
                  }

                  function setHTML(origData,priceDP){
                  let data = [];
                  let dataMin = '';
                  let dataMinTime = '';
                  let dataMax = '';
                  let dataMaxTime = '';
                  let dataAvg = '';
                  let dataNull = false;
                  // log(priceDP);
                  let tibberInst = getState(tibberInstDP).val;
                  let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                  let tblLevel = levelObject(tibberLink[0]);
                  let dpLeveltbl = getDPLevel(tblLevel,3);

                  let minToday = getState(dpLeveltbl + '.PricesToday.minimum.total').val;
                  //minToday = minToday-(Math.trunc(minToday*0.1))
                  // log(minToday)
                  let maxToday = getState(dpLeveltbl + '.PricesToday.maximum.total').val
                  let minTomorrow = getState(dpLeveltbl + '.PricesTomorrow.minimum.total').val
                  //minTomorrow = minTomorrow-(Math.trunc(minTomorrow*0.1))
                  let maxTomorrow = getState(dpLeveltbl + '.PricesTomorrow.maximum.total').val
                  let jsonTomorrow = JSON.parse(getState(dpLeveltbl + '.PricesTomorrow.json').val);
                  
                  let graphMin = 0;
                  if(minToday >= minTomorrow){
                      if(minTomorrow != 0){
                          graphMin = minTomorrow;
                      }else{
                          graphMin = minToday;
                      }
                  }else{
                      graphMin = minToday;
                  }
                  let graphMax = 0;
                  if(maxToday >= maxTomorrow){
                      graphMax = maxToday;
                  }else{
                      graphMax = maxTomorrow;
                  }
                  // graphMax = Math.round((graphMax + parseFloat((graphMax / 20).toFixed(2))) * 100) / 100;
                  // graphMax = Math.max(Math.ceil(graphMax * 100) / 100, 0.35);
                  if(jsonTomorrow.length ==0 ){
                      graphMin = minToday;
                      graphMax = maxToday
                  }
                  graphMin = Math.ceil(graphMin * 50) / 50 - 0.02;
                  graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                  //log(graphMin)
                  
                  for(let i=0;i<origData.length;i++){
                      if(origData[i].min){
                          dataMin = origData[i].value;
                          //log(dataMin);
                          dataMinTime =origData[i].startTS;
                          //log(dataMinTime)
                      }
                      if(origData[i].max){
                          dataMax = origData[i].value;
                          dataMaxTime =origData[i].startTS;
                      }
                      if(origData[i].average){
                          dataAvg = origData[i].value;
                      }
                  }
                  if(origData.length>3){
                      for(let i=0;i<origData.length;i++){
                          if(!origData[i].average && !origData[i].max && !origData[i].min ){
                              if( origData[i].value < dataAvg){ 
                                  if(origData[i].level == 'NORMAL' ){
                                      data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level})//, color: 'rgba(0,255,0,0.2)', border: levelColor(origData[i].level)
                                  }else{
                                      data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy,level: origData[i].level}) //,  color: levelColor(origData[i].level), border: 'lime'
                                  }
                              }else{
                                  data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level}) //,color: levelColor(origData[i].level), border: 'red'
                              }
                          }else{
                              if(origData[i].min){
                                  dataMin = origData[i].value;
                                  dataMinTime =origData[i].startTS;
                              }
                              if(origData[i].max){
                                  //log(origData[i]);
                                  dataMax = origData[i].value;
                                  dataMaxTime =origData[i].startTS;
                                  //log(dataMaxTime);
                              }
                              if(origData[i].average){
                                  dataAvg = origData[i].value;
                              }
                          }
                          
                      }
                      // log('oben '+graphMin)
                  }else{
                      dataNull = true;
                      //dataMin = String(graphMin);
                      //dataMax = String(graphMax);
                      //dataMax = "0";
                      //dataAvg = '0.01';
                      //graphMin = minToday;
                      //graphMax = maxToday;
                      //graphMin = Math.ceil(graphMin * 50) / 50 - 0.01;
                      //graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                  }
                  // Werte holen
                  let showTaxEnergy = getState(tibberShowTaxEnergyDP).val;
                  let minMaxAvg = getState(tibberShowMinMaxAvgDP).val;
                  let colorJSON = getState(tibberColorDP).val;
                  
                  let html = '';
                  html += '<!DOCTYPE html>';
                  html += '<html lang="en">';
                  html += '<head>';
                  html += '<meta charset="UTF-8">';
                  html += '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
                  html += '<title>Tibber-Tageswert</title>';
                  html += '<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>';
                  html += '<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>';
                  html += '</head>';
                  html += '<body>'
                  if(getState(visDP).val == 'VIS'){
                      html += '<div id="chart-container" style="width: 600px; height:400px;"></div>';
                  }else{
                      html += '<div id="chart-container" style="width: 100%; height:400px;"></div>';
                  }
                  //log(data);
                  html += '<script>'
                  html += '    var data = '+JSON.stringify(data)+';';
                  html += '    var chartContainer = document.getElementById("chart-container");'
                  html += '    var myChart = echarts.init(chartContainer);';
                  
                  
                  html += '    function formatTime(time) {';
                  html += '        return moment(time).format("HH");'
                  html += '    }';
                  html += '    function calculateArrowPosition(hour){'
                  //html += '       console.log((hour) * (100 / 24) + "%");'
                  html += '       return (hour / 24) * 100 +1 + "%";'
                  html += '    }'
                  html += '    function updateChart() {';
                  html += '        var minValue = Math.min.apply(null, data.map(function (item) {';
                  html += '          return item.value;';
                  html += '        }));';
                  //html += '        console.log(minValue);'
                  // html += '        var yAxisMin = minValue - (minValue/10);'
                  html += '        var yAxisMin = '+graphMin+';';
                  html += '        var maxValue = '+dataMax+';'
                  //html += '        var maxValue = '+graphMax+';'
                  //html += '        console.log(maxValue);'
                  // html += '        var yAxisMax = maxValue + (maxValue/10);'
                  html += '        let avgValue = '+dataAvg+';'
                  html += '        var visualMapPieces =' + colorJSON +';';
                  html += '        var values = data.map(item => (item.value-minValue).toFixed(2));'
                  html += '        var maxLineValue = Math.max.apply(null, values);'
                  html += '        var maxLineIndex = values.indexOf(maxLineValue);'
                  html += '        var maxLineData = {time:'+dataMaxTime+',value:'+dataMax+'};'
                  html += '        var currentHour = new Date().getHours() ;'
                  // html += '        console.log(currentHour);'
                  //html += '        console.log(maxLineData.time);'
                  // html += '        var maxV = parseFloat((Math.max(...values)));'
                  //html += '        console.log(maxV);'
                  //html += '        let pro = values.map((value) => (value/maxV).toFixed(2));'
                  //html += '        console.log(values);'
                  //html += '        console.log(pro);'
                  html += '        var colorStops = [];'
                  //html += '        console.log(yAxisMin +" "+maxValue);'
                  if(!dataNull){
                  html += '        visualMapPieces.map(piece => {'
                  html += '          if(piece["lte"] >=yAxisMin && piece["gt"]<=maxValue){ '
                  //html += '            console.log(piece["lte"] + " "+maxValue + " "+ yAxisMin);'
                  html += '            if(piece["gt"]>=yAxisMin){'
                  //html += '             console.log(piece["gt"] +" gt gesetzt " +yAxisMin);'
                  html += '             colorStops.push({'
                  html += '              offset:  ((piece["gt"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                  html += '              color: piece.color'
                  html += '             });'
                  html += '            }'
                  html += '            if(piece["lte"]<=maxValue){'
                  //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                  html += '             colorStops.push({'
                  html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                  html += '              color: piece.color'
                  html += '             });'
                  html += '            }'
                  html += '            if(piece["lte"]>maxValue ){'
                  //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                  html += '            colorStops.push({'
                  html += '              offset:  1,'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                  html += '              color: piece.color'
                  html += '             });'
                  //html += '            }'
                  html += '           };'
                  html += '          }else{'
                  //html += '            console.log(piece["lte"] + " " + piece["gt"]);'
                  html += '           if(piece["lte"]>=maxValue && piece["gt"]<=maxValue ){'
                  //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                  html += '            colorStops.push({'
                  html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                  html += '              color: piece.color'
                  html += '            });'
                  
                  html += '           }else if(piece["lte"]>=maxValue && piece["gt"] <= maxValue){'
                  // html += '            console.log("Drin");'
                  html += '            colorStops.push({'
                  html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                  html += '              color: piece.color'
                  html += '            });'
                  html += '           }'
                  html += '          }; ' 
                  html += '        });'
                  //html += '        console.log(colorStops);'
                  //html += '        console.log(colorStops[colorStops.length-1].color);'
                  html += '        colorStops.push({'
                  html += '            offset: 1,' //visualMapPieces[visualMapPieces.length - 1]["gt"]
                  html += '            color: colorStops[colorStops.length-1].color'// visualMapPieces[visualMapPieces.length - 1].color'
                  html += '        });'
                  //html += '        console.log(colorStops);'
                  html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                  //html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                  //html += '        colorStops.splice(2, 0, {offset: colorStops[1].offset,color:colorStops[2].color});'
                  //html += '        colorStops.splice(4, 0, {offset: colorStops[3].offset,color:colorStops[4].color});'
                  //html += '        console.log(colorStops);'
                  }
                  if(dataNull && !getState(tibberShowGraphIfEmptyDP).val){
                      html += '        myChart.setOption({';
                  html += '            title: {';
                  if(priceDP== 'PricesToday'){
                      html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                      if(getState(tibberShowLabelTodayDP).val){
                          html += '            show: true'
                      }else{
                          html += '            show: false'
                      }
                  }else{
                      if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                            html += '          textAlign: "auto", '
                            html += '          textStyle: { '
                            html += '             color: "red"'
                            html += '          },'
                            html += '          left: "50px",'
                            html += '          text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                      }else{
                          html += '            text: "'+getState(tibberLabelTomorrowDP).val+'",';
                          if(getState(tibberShowLabelTomorrowDP).val){
                              html += '        show: true,'
                          }else{
                              html += '        show: false,'        
                          }
                      }
                      
                      
                  }
                  
                  html += '                 },});';
                  }else{
                  
                  html += '        myChart.setOption({';
                  html += '            title: {';
                  if(priceDP== 'PricesToday'){
                      html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                      if(getState(tibberShowLabelTodayDP).val){
                          html += '                show: true'
                      }else{
                          html += '                show: false'
                      }
                  }else{
                      if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                            html += '            textAlign: "auto", '
                            html += '            textStyle: { '
                            html += '               color: "red"'
                            html += '            },'
                            html += '            left: "50px",'
                            html += '            text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                      }else{
                          html += '                text: "'+getState(tibberLabelTomorrowDP).val+'",';
                          if(getState(tibberShowLabelTomorrowDP).val){
                              html += '                show: true,'
                          }else{
                              html += '                show: false,'        
                          }
                      }
                      
                      
                  }
                  
                  html += '            },';
                  html += '            visualMap: {';
                  html += '              type: "piecewise",'
                  html += '              pieces: visualMapPieces,'
                  html += '              dimension: 1,' // Mapping to the 'value' dimension'
                  html += '              showLabel: true,'
                  html += '              precision: 2,'
                  html += '              itemWidth: 6,'
                  html += '              orient: "horizontal",'
                  html += '              left: "center", calculable: true,selectedMode: "multiple",'
                  html += '              bottom: 10,'
                  html += '              text: ["High", "Low"],'
                  html += '              textStyle: {'
                  if(getState(darkModeDP).val){
                      html += '                color: "white"'
                  }else{
                      html += '                color: "black"'
                  }
                  html += '              },'
                  //html += '              inRange: {'
                  //html += '                color: colorStops.map(stop => stop.color)';//visualMapPieces.map(piece => piece.color)'
                  //html += '              },'
                  /* bringt nichts
                  html += '              itemStyle:{'
                  html += '                 symbol:"pin",'
                  html += '                 symbolSize: 30,'
                  html += '                 markPoint: {'
                  html += '                   data: [{'
                  html += '                    symbol: "circle",'
                  html += '                       coord: [data.time, data.value], itemStyle:{ color:"red"}'
                  html += '                    }]'
                  html += '                 },'
                  html += '               }'
                  */
                  html += '            },'
                  
                  if(minMaxAvg){
                      html += '            grid: {';
                      if(getState(tibberShowMinMaxAvgTextDP).val){
                          html += '              right: 50,'; // Vergrößern Sie diesen Wert nach Bedarf
                      }else{
                          html += '              right: 10,';
                      }
                      html += '              left: 10,';
                      html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                      html += '            },';
                  }else{
                      html += '            grid: {';
                      html += '              right: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                      html += '              left: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                      html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                      html += '            },';
                  }
                  html += '            areaStyle: {'
                  html += '              color: colorStops';//"red"'; visualMapPieces.map(piece => piece.color)'
                  //html += '              color: "blue", '
                  html += '            },'
                  // Option für Pfeil unter Kurve
                  /*
                  if(!dataNull && getState(tibberHighlightCurrentHourDP).val){
                  html += 'graphic: [{'
                  html += '    type: "image",'
                  html += '    id: "arrow",'
                  html += '    bounding: "all",'
                  html += '    z:100,'
                  //html += '    origin: [calculateArrowPosition(currentHour), "10%"],'
                  //html += '    origin: [0.5, 0],'  // Koordinaten für den Pfeil
                  html += '    bottom: "10%", '
                  html += '    left: calculateArrowPosition(currentHour),';//"50px",'
                  html += '    '
                  html += '    style: {'
                  html += '        image: "https://api.iconify.design/mdi/arrow-up-bold.svg?width=24&height=24&color=blue", ' // Pfad zum Bild deines Pfeils
                  html += '        width: 30,'
                  html += '        height: 30,'
                  html += '    }'
                  html += '}],'
                  }
                  */
                  // ToolBox
                  html += '            toolbox: {';
                  html += '              feature: {';
                  html += '                saveAsImage: {';
                  html += '                   backgroundColor: "rgba(38, 37, 37, 1)",';
                  html += '                   title: "Speichern",';
                  let fileName = priceDP.replace('Prices','') 
                  if(fileName == 'Today'){
                      fileName += ' '+ formatDate(new Date(),'DD.MM.YYYY'); 
                  }else{
                      fileName += ' '+ formatDate(new Date().getTime()+86400000,'DD.MM.YYYY'); 
                  }
                  html += '                   name: "TibberHTML '+fileName+'"'
                  html += '                },'
                  html += '                magicType: {';
                  html += '                  type: ["line", "bar"],';
                  html += '                  title:{';
                  html += '                     line: "Line-Chart",';
                  html += '                     bar: "Bar-Chart",';
                  html += '                  }'
                  
                  html += '                },';
                  html += '                dataView: {';
                  html += '                  title: "Daten aus der Serie",';
                  html += '                  lang: ["Daten der Kurve", "Schließen", "Aktualisieren"],'
                  html += '                  optionToContent: function (opt) {';
                  html += "                      var table = '<table style=\"width:100%;\"><tbody><tr style=\"text-align: left;\"><th>Stunde</th><th>Wert</th><th>Energie</th><th>Steuer</th><th>Level</th></tr>';";
                  //html += '                      console.log(opt.series.length); '
                  //html += '                      console.log(opt.series[0].data); '
                  html += '                      for (var i = 0; i< opt.series[0].data.length;i++) {';
                  html += '                          table += "<tr>";';
                  html += '                         for(let x =0; x < opt.series[0].data[i].value.length; x++){'
                  html += '                            if(x==0){';
                  html += '                               table +=  "<td>" + ("0"+new Date(opt.series[0].data[i].value[x]).getHours()).slice(-2) + "</td>";';
                  html += '                            }else{';
                  html += '                               table +=  "<td>" + opt.series[0].data[i].value[x] + "</td>";';
                  html += '                            } '
                  html += '                         }';
                  html += '                           table += "</tr>";';
                  html += '                      }';
                  html += '                      table += "</tbody></table>";'
                  html += '                      return table;';
                  html += '                  },';
                  html += '                  readOnly: true';
                  html += '                },'
                  html += '              }';
                  html += '            },'
                  
                  html += '            xAxis: {';
                  html += '                type: "time",';
                  html += '                axisLabel: {';
                  html += '                    show: true,'
                  html += '                    formatter: function (value) {';
                  html += '                        return formatTime(value);';
                  html += '                    }';
                  html += '                },';
                  html += '                splitNumber: 10,';
                  html += '            },';
                  html += '            yAxis: {';
                  html += '                type: "value",';
                  html += '                axisLabel: {'; 
                  
                  html += '                  formatter: function (value) {';
                  html += '                     return value.toFixed(3) + " €";';
                  html += '                  }';
                  
                  html += '                },';
                  
                  html += '               min: '+graphMin+','; //
                  html += '               max: '+graphMax+',' //yAxisMax
                  html += '            },';
                  
                  
                  
                  
                  
                  html += '            series: [{';
                  
                  html += '                data: data.map(function (item) {';
                  html += '                    var hour = new Date(item.time).getHours();'
                  html += '                    return {';
                  html += '                       value: [item.time, item.value, item.energy, item.tax, item.level],';
                  //html += '                       lineStyle: {width: hour === currentHour ? 10:null},'
                  
                  // Symbol für Line einstellen
                  
                  html += '                        symbol: "circle",'
                  
                  if(getState(tibberHighlightCurrentHourDP).val && priceDP == 'PricesToday'){
                      html += '                    symbolSize: hour === currentHour ? 10:null, '
                      html += '                    itemStyle: {'
                         
                      if(getState(darkModeDP).val){
                          //html += '                           backgroundColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                          html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                          html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                          html += '                           borderWidth: hour === currentHour ? 2:null,'
                          html += '                           shadowBlur: hour === currentHour ? 20:null,'
                      }else{
                          html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                          html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                          html += '                           borderWidth: hour === currentHour ? 1:null,'
                          html += '                           shadowBlur: hour === currentHour ? 10:null,'
                      }
                      //html += '                           borderWidth: hour === currentHour ? 1:null,'
                      //html += '                           shadowBlur: hour === currentHour ? 10:null,'
                      
                      html += '                     },'
                      
                  }
                  // Aria für Schraffierung
                  //html += 'aria: {'
                  //html +='    enabled: true,'
                  //html += '   decal: {'
                  //html +='        show: hour === currentHour'
                  //html += '   }'
                  //html +='},'
                  html += '                        emphasis: {';
                  html += '                          itemStyle: {';
                  html += '                            color: "white" '; // Füge die Farbe in die Betonung ein
                  html += '                          },';
                  html += '                          label: {';
                  html += '                            show: true,';
                  html += '                            formatter: function (params) {';
                  html += '                               return params.data.value[1].toFixed(3) + " €";'; //console.log(params);
                  html += '                            },';
                  html += '                            color: "black",';
                  html += '                            fontWeight: "bold", ';
                  html += '                            backgroundColor: "white"';
                  html += '                          }';
                  html += '                        }';
                  html += '                     } ';
                  html += '                }),'; // end data
                  
                  if(getState(tibberSteppedLineDP).val){
                      html += '            step: "end",'
                  }
                  // ItemStyle
                  //html += '                itemStyle:{'
                  //html += '                  color: function (params) {'
                              // Färbe den Balken der aktuellen Stunde anders ein
                  //html += '                    console.log(new Date(params.value[0]).getHours());'
                  //html += '                    console.log(currentHour);'
                  //html += 'console.log(new Date(params.value[0]).getHours() === currentHour ? "red" : "blue");'
                  //html += '                    return new Date(params.value[0]).getHours() === currentHour ? "red" : "blue";'
                  //html += '                  }'
                  //html += '                },'
                  if(getState(tibberAreaDP).val){
                  html += '                areaStyle:{'
                  html += '                    color: new echarts.graphic.LinearGradient(0, 1, 0, 0, colorStops),' ;
                  
                  //html += '                    color:  colorStops,'
                  // html += '                    max: maxValue, '
                  /*
                  html += '                    color: function (params) {'
                  html += '                       console.log(params);'
                  html += '                       var wert = params.data.value[1];'
                  html += '                       var col = "red";'
                  html += '                       for (var i = 0; i < visualMapPieces.length; i++) {'
                  html += '                           var piece = visualMapPieces[i];'
                  html += '                           if (wert >= piece.gt && wert <= piece.lte) {'
                  html += '                               col = piece.color;'
                  html += '                               break;'
                  html += '                           }'
                  html += '                       }'
                  html += '                       return col;'
                  html += '                   },'
                  */
                  html += '                },'
                  }
                  html += '                type: "'+getState(tibberGraphTypeDP).val+'",';
                  //html += '               markArea: {'
                  //html += '                   silent: true,'
                  //html += '                   data: ['
                  //html += '                       [{'
                  //html += '                           xAxis: "min",'
                  //html += '                           itemStyle: {'
                  //html += '                               color: "rgba(0, 0, 0, 0.7)"'
                  //html += '                           }'
                  //html += '                           }, {'
                  //html += '                               xAxis: "max",'
                  //html += '                       }]'
                  //html += '                   ]'
                  //html += '               },'
                  
                  if(minMaxAvg){
                      html += '                markLine: {';
                      html += '                  symbol: "none",';  // Kein Symbol für die Markierungslinie
                      html += '                  lineStyle: {';
                      html += '                    color: "red",';   // Farbe der Markierungslinie
                      html += '                    type: "dashed"';  // Art der Linie (gestrichelt)
                      html += '                  },';
                      
                      if(getState(tibberShowMinMaxAvgTextDP).val){ //coord: [maxLineData.time, maxLineData.value] ,)
                          if(!dataNull){
                          html += '                  data: [';
                          html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: true, position: "end", formatter: "Min\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                          html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: true, position: "end", formatter: "Max\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                          html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: true, position: "end", formatter: "Avg\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                          html += '                  ], '
                          }
                      }else{
                          if(!dataNull){
                          html += '                  data: [';
                          // funktioniert nicht !,tooltip: {show: true,formatter: "Min\\n\\n" + params.value.toFixed(3) + " €",textStyle: {fontSize: 12,fontWeight: "bold",color: "white"}}  ,formatter: "Min " + minValue.toFixed(3) + " €"
                          html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: false, position: "end", formatter: "Min\\n\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                          html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: false, position: "end", formatter: "Max\\n\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                          html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: false, position: "end", formatter: "Avg\\n\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                          html += '                  ], '    
                          }    
                      }
                      html += '                }';
                  }
                  html += '            }],'; // Ende Series
                  
                  
                  
                  
                  html += '            tooltip: {';
                  html += '              trigger: "axis",';
                  html += '              axisPointer: {';
                  html += '               type: "shadow"';
                  html += '              },';
                  html += '              textStyle: {';
                  html += '                fontFamily: "Courier",';
                  html += '                fontWeight: "bold"'; // Hinzugefügt
                  html += '              },'
                  html += '              formatter: function (params) {';
                  html += '                let time = "Start ab: "+ moment(params[0].axisValue).format("HH:mm")+ " Uhr";';
                  html += '                let value = "Preis:&nbsp&nbsp&nbsp&nbsp"+params[0].value[1].toFixed(4) + " €";';
                  if(showTaxEnergy){
                      html += '            let energy = "Energie:&nbsp&nbsp"+params[0].value[2].toFixed(4) + " €";'
                      html += '            let tax    = "Steuer:&nbsp&nbsp&nbsp"+params[0].value[3].toFixed(4) + " €";'
                      html += '            let lev    = "Level:&nbsp&nbsp&nbsp&nbsp"+ params[0].value[4];'
                      html += "            return  `${time}<br/>${value}<br/>${energy}<br/>${tax}<br/>${lev}` ;";
                  }else{
                      //html += "            return `<span style=\"font-family: 'Arial'; font-weight: 'bold';\" >${time}<br/>${value}</span>` ;";
                      html += "            return `${time}<br/>${value}` ;";
                  }
                  
                  html += '              }';
                  html += '            },';
                  
                  html += '        }) ';// end setOption
                  }
                  html += '    }'; 
                  
                  
                  html += '    updateChart(); ';
                  html +='     var updateInterval = setInterval(updateChart, 3600000);'
                  html += '</script>';
                  html += '</body>';
                  html += '</html>';
                  
                  // log(html);
                  if(priceDP == 'PricesToday'){
                      setState(tibberHTMLTodayDP,html);
                  }else{
                      setState(tibberHTMLTomorrowDP,html);
                  }
                  

                  }

                  function sortByName(x, y) {
                  // Wenn x oder y nicht-numerisch sind, setze sie an das Ende
                  if (isNaN(x.hour) || isNaN(y.hour)) {
                  return isNaN(x.hour) ? 1 : -1;
                  }

                  // Vergleiche numerische Werte
                  return x.hour - y.hour;
                  

                  }

                  on({id: dbHistoryDP, change: "any"}, function (obj) {
                  let value = obj.state.val;
                  // history für die DPs aktiv?
                  if (value!=''){
                  if (getState('system.adapter.'+value+'.alive').val){
                  if (isHistoryActiveAllDPs(dpArray)){
                  if(logging){
                  log('History-Future-DPs sind angelegt und History aktiviert!');
                  }
                  // getPVData(dpArray);
                  //runScript();
                  }else{
                  if(logging){
                  log('History wird angelegt für die future-DPs!');
                  }
                  activateDPsHistory(dpArray);
                  setTimeout(function(){
                  deleteAllHistoryDPs(dpArray);
                  // log('gelöscht');
                  // getPVData(dpArray);
                  },3000)
                  //runScript();
                  }
                  }else{
                  log('Der History-Adapter ist nicht gestartet! -> Es werden keine DPs mit History aktiviert','warn');
                  }
                  }
                  });

                  function setDPs(tibberInst){
                  // Ist der Adapter aktiv
                  //
                  //let pvAliveDP = 'system.adapter.pvForecast.'+tibberInst+'.alive';
                  //if(existsState(pvAliveDP)){
                  // if(getState(pvAliveDP).val){
                  // Adapter ist gestartet
                  let tibberKeys = ['Value','Tax','Energy']
                  for(let i=0;i<tibberKeys.length;i++){
                  dpArray.push(tibberDP+'.future'+tibberKeys[i]);
                  }

                  //    }else{
                  //        log('Der Adapter tibberlink.'+tibberInst+' ist nicht gestartet!');
                  //    }
                  //}else{
                  //    log('Der Adapter pvForecast ist nicht installiert')
                  //}
                  // Alte erst löschen
                  // Nur löschen, wenn sich die DPs geändert haben
                  let delItems = false;
                  if(dpArray.length >0){
                      // delDPs(dpArray);
                      
                      for(let i=0;i<dpArray.length;i++){
                          if(existsState(dpArray[i])){
                  
                          }else{
                              delItems = true;
                              delDPs(dpArray);
                              break;
                          }
                      }
                  }
                  if(delItems){
                      setTimeout(function() {
                          if(dpArray.length >0){
                              createDPs(dpArray);
                          }
                      },3000);
                  }else{
                      createDPs(dpArray);
                  }
                  

                  }

                  function delDPs(arr){
                  for(let i=0; i<arr.length;i++){
                  if(existsState(arr[i])){
                  deleteStateAsync(arr[i]);
                  }
                  }
                  }
                  // createStateAsync(futureTempDP, {read: true, write: false, name: "daswetter temperature", type: "number", role: "", def: 0 });

                  function createDPs(arr){
                  for(let i=0; i<arr.length;i++){
                  // 0_userdata.0.pvForecastHistory.historyDB
                  let name = levelObject(arr[i])[3];
                  createStateAsync(arr[i], {read: true, write: false, name: "tibber"+name, type: "number", role: "", def: 0 });
                  }
                  }

                  function seteChartsDP(dpArray){
                  let startDT = getDateObject('00:00').getTime(); // heute 00:00
                  // pvForecast hat nur 2 Tage im Array
                  let endDT = startDT + 24160601000;
                  // start_time, end_time, start, end, timeType
                  for(let i=0;i<dpArray.length;i++){
                  let echartDP = 'echarts.0.tibber'+levelObject(dpArray[i])[3];
                  let obj;
                  if (existsObject(echartDP)){
                  obj = getObject(echartDP);
                  //log(obj);
                  if (obj.native.data.timeType == 'static'){
                  obj.native.data.start = formatDate(startDT,'YYYY-MM-DD');
                  obj.native.data.end = formatDate(endDT,'YYYY-MM-DD');
                  obj.native.data.start_time = '00:00';
                  obj.native.data.end_time = '00:00';
                  setObject(echartDP,obj);
                  }
                  }
                  }
                  }

                  function isHistoryActiveAllDPs(dpArray){
                  // dparray automatisch gesetzt
                  let active = false;
                  let dbHistory = getState(dbHistoryDP).val;
                  if (dbHistory != ''){
                  for(let i= 0;i<dpArray.length;i++){
                  let dpPara = levelObject(dpArray[i])[3];
                  // log('dpPara: '+dpPara);
                  // log(pvForecastDP+'.future'+dpPara);
                  // setActiveHistory(pvForecastDP+'.future'+dpPara);
                  active = isHistoryActive(tibberDP+'.'+dpPara,dbHistory);
                  if(active == false){
                  return false;
                  }
                  }

                      log('Tibber-DPs History aktiv');
                      return true;
                  }else{
                      log('DB Auswahl fehlt');
                      return false;
                  }
                  

                  }

                  function isHistoryActive(dp,db){
                  let obj = getObject(dp);
                  if (obj.common.custom != undefined){
                  //log(obj.common.custom);
                  let custom = obj.common.custom;

                      for (let key in custom){
                          //log(key);
                          if (key.indexOf(db)>=0){  //'history'
                              return true;
                          }
                      }
                  }
                  return false;
                  

                  }

                  function activateDPsHistory(dpArray){
                  let historyDB = getState(dbHistoryDP).val;
                  //log('HistoryDB: '+historyDB);
                  if (historyDB != ''){
                  if (getState('system.adapter.'+historyDB+'.alive').val){

                          if (historyDB!=''){
                              for(let i= 0;i<dpArray.length;i++){
                                  //log('DParray[i]: '+dpArray[i]);
                                  let dpPara = levelObject(dpArray[i])[3];
                                  //log('dpPara: '+dpPara);
                                  //log(pvForecastDP+'.'+dpPara);
                                  setActiveHistory(tibberDP+'.'+dpPara);
                                  setTimeout(function(){
                                      deleteAllHistoryData(tibberDP+'.'+dpPara);
                                  },2000)
                              }
                              log('Future-DPs History aktiviert');
                          }else{
                              log('Es wurde keine DB für Future-History ausgewählt!','warn');
                          }
                      }else{
                          log('Der Adapter ist nicht gestartet! -> keine Aktivierung möglich','warn');
                      }
                  }else{
                      log('Aktivierung der DPs für die DB erst möglich, wenn man eine DB ausgewählt hat!','warn');
                  }
                  

                  }

                  // deleteAllHistoryDPs();

                  function deleteAllHistoryDPs(dpArray){
                  let dbHistory = getState(dbHistoryDP).val;
                  if (getState('system.adapter.'+dbHistory+'.alive').val){
                  log('History DPs dpArray löschen!');
                  for(let i= 0;i<dpArray.length;i++){
                  //log('DParray[i]: '+dpArray[i]);
                  let dpPara = levelObject(dpArray[i])[3];
                  //log('dpPara: '+dpPara);
                  //log(pvForecastDP+'.'+dpPara);
                  deleteAllHistoryData(tibberDP+'.'+dpPara);

                      }
                      log('Future-DPs History gelöscht');
                  }else{
                      log('Adapter nicht gestartet!');
                  }
                  

                  }

                  function deleteAllHistoryData(dp){
                  let dbHistory = getState(dbHistoryDP).val;
                  if (dbHistory!=''){
                  //let dtStart= getDateObject('00:00').getTime(); // heute 00:00 Uhr
                  //let dtStop = dtStart + 24660601000;
                  sendTo(dbHistory, 'deleteAll', [ // 'history.0' 'deleteRange'
                  {id: dp}//, start: dtStart, end: dtStop

                      ], result => {//console.log('deleted')
                      });
                  }else{
                      log('Löschen nicht durchgeführt, da keine HistoryDB festgelegt');
                  }
                  

                  }

                  function getHistoryAdapter(){
                  // history, influxdb, sql
                  log('Einlesen der vorhandenen History-DBs.');
                  let histArr = ['history','influxdb','sql'];
                  let arr =[];
                  for (let i=0; i<histArr.length;i++){
                  let dp = $('system.adapter.'+histArr[i]+'.*.alive');
                  //log(dp);
                  for(let x=0;x<dp.length;x++){
                  //log(dp[x]);
                  let dpID = dp[x];

                          if (getObject(dpID).common != undefined){
                              //log(getState(dpID).val);
                              if (getState(dpID).val != null && getState(dpID).val){
                                  dp[x] = dp[x].substring(15,dp[x].length-6);
                                  // log(dp[x]);
                                  arr.push(dp[x]);
                              }
                              if (getState(dpID).val == null){
                                  log('History-Adapter ist fehlerhaft: '+dp[x] +' -> alive auf false setzen');
                              }
                          }
                      }
                  
                  }
                  let devStates = {'':'keine Auswahl'};
                  for (let i=0; i< arr.length;i++){
                      devStates[arr[i]] = arr[i];
                  }
                  //log(devStates);
                  if (existsState(dbHistoryDP)){
                      let obj = getObject(dbHistoryDP);
                      obj.common.states = devStates;
                      setObject(dbHistoryDP,obj);
                  }else{
                      createStateAsync(dbHistoryDP, {read: true, write: true, name: "DB-Auswahl", type: "string", role: "", def: '',states:devStates });    
                  }
                  

                  }

                  function setActiveHistory(dp){
                  let dbHistory = getState(dbHistoryDP).val;
                  //log('dbHistory setActive: '+dbHistory);
                  if (dbHistory !=''){
                  sendTo(dbHistory, 'enableHistory', { // 'history.0'
                  id: dp, // 'system.adapter.history.0.memRss'
                  options: {
                  changesOnly: true,
                  debounce: 0,
                  retention: 31536000,
                  maxLength: 3,
                  changesMinDelta: 0,
                  //ignoreZero: true,
                  aliasId: '',
                  enabled: true,
                  debounceTime: 0,
                  blockTime: 0,
                  changesRelogInterval: "0",
                  ignoreBelowNumber: "",
                  disableSkippedValueLogging: false,
                  customRetentionDuration: 365,
                  enableDebugLogs: false

                          }
                      }, function (result) {
                          if (result.error) {
                              console.log(result.error);
                          }
                          if (result.success) {
                              //successfull enabled
                              //log(dp +' wurde in history aktiviert');
                          }
                      });
                  }
                  

                  }

                  // setHistoryData(futureHumidityDP,dpValueArr);

                  function setHistoryData(dp,states){
                  let dbHistory = getState(dbHistoryDP).val;
                  if (dbHistory!=''){
                  sendTo(dbHistory, 'storeState', { // 'history.0'
                  id: dp,
                  state: states
                  }, result => {
                  // console.log('added')
                  });
                  }
                  }

                  function levelObject(id){
                  // 0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff
                  let idArr=id.split('.');
                  return idArr; //log(idArr[10]);
                  }

                  // log(getDPLevel(levelObject('0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff'),9));
                  function getDPLevel(idArr,level){
                  let id ='';
                  for (let i=0;i<=level;i++){
                  id += idArr[i] +'.'
                  }
                  id = id.substr(0,id.length-1); // letzten Punkt wegnehmen
                  return id;
                  }

                  1 Reply Last reply
                  0
                  • M Meikie

                    @mcu admin.0
                    2024-01-05 23:47:34.290 info <== Disconnect system.user.admin from ::ffff:192.168.178.51 javascript

                    Das Einzige.

                    M Online
                    M Online
                    MCU
                    wrote on last edited by MCU
                    #402

                    @meikie Die kommt ja nur, wenn man den javascript TAB schließt.
                    Bitte in CODE-TAG.
                    oder in ein txt-Datei

                    NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                    Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                    M 1 Reply Last reply
                    0
                    • M MCU

                      @meikie Die kommt ja nur, wenn man den javascript TAB schließt.
                      Bitte in CODE-TAG.
                      oder in ein txt-Datei

                      M Offline
                      M Offline
                      Meikie
                      wrote on last edited by
                      #403
                      // *********************************
                      // tibberHTML v1.0.24
                      // *********************************
                      // Copyright ©MCU
                      // v1.0.1 - Erweiterung Umschaltung Line/bar im Graph, Anzeige der Werte in Tabelle
                      // v1.0.2 - Vis Auswahl -> fete Breite für VIS, darkMode
                      // v1.0.3 - Min,max,avg kleiner, untereinander, rechts Breite kleiner
                      // v1.0.4 - ShowMinMaxAvgTexte optional
                      // v1.0.5 - toolBox -Speichern mit Namen+Datum
                      // v1.0.6 - y-Skala auf beiden Kurven gleich 
                      // v1.0.7 - splitNumber auf 10 vorher 3, grid rechts 10 statt 30, visualMap - mobile optimiert
                      // v1.0.8 - CurveArea optional, Korrektur wenn tomorrow.mim = 0 -> graphMin =0
                      // v1.0.9 - graphMax angepasst auf nächste 0.01
                      // v1.0.10- graphMin angepassz auf nächste 0.01
                      // v1.0.11- Label optional, falls man schon Widget-Title nutzt 
                      // v1.0.12 - Trennung Label Today und Tomorrow
                      // v1.0.13 - optionaler Text für Tomorrow Wait
                      // v1.0.14 - automatischer Reload bei Umschaltung wait-Text Tomorrow
                      // v1.0.15 - aktuelle Zeit highlightCurrentHour
                      // v1.0.16 - Symbol für Line aktuelle Stunde angepasst
                      // v1.0.17 - stepped line hinzugefügt, Korrekturen graphMin
                      // v1.0.18 - Korrektur showwait
                      // v1.0.19 - Korrektur showwait
                      // v1.0.20 - Abschaltung Anzeige Graph, wenn leer, Korrektur highlightPoint
                      // v1.0.21 - Korrektur dataNull für visualMapPieces
                      // v1.0.22 - Inhalt von DPs als Datei speichern
                      // v1.0.23 - Korrektur 1.Farbelement lte > maxValue
                      // v1.0.24 - Korrektur 1. Farbelement Umstellung Linie, falsche Berechnung
                      // ToDo
                      // - optionale Zeit vor günstiger Stunde telegram senden, alexa info, pushOver senden
                      // - Ersparnis in Prozent -> Tabelle / Anzeige?
                      // - Stunden erweitern für steppedLine?
                      
                      let logging                     = true;
                      let tibberDP                    = '0_userdata.0.Strom.tibberHistory';
                      let dbHistoryDP                 = tibberDP + '.historyDB';
                      let tibberGraphTypeDP           = tibberDP + '.graphTyp'; // bar  oder line
                      let tibberInstDP                = tibberDP + '.instanz'; // 0
                      let tibberColorDP               = tibberDP + '.colorJSON'; // visualMapPieces [ {gt: 0, lte: 0.15, color: "lightgreen"},]
                      let tibberHTMLTodayDP           = tibberDP + '.htmlToday';
                      let tibberHTMLTomorrowDP        = tibberDP + '.htmlTomorrow';
                      let tibberShowTaxEnergyDP       = tibberDP + '.showTaxEnergy'; // boolean
                      let tibberShowMinMaxAvgDP       = tibberDP + '.showMinMaxAvg'; // boolean
                      let visDP                       = tibberDP + '.vis';
                      let darkModeDP                  = tibberDP + '.darkMode';
                      let tibberShowMinMaxAvgTextDP   = tibberDP + '.showMinMaxAvgText';
                      let tibberAreaDP                = tibberDP + '.curveArea';
                      let tibberShowLabelTodayDP      = tibberDP + '.showLabelToday';
                      let tibberLabelTodayDP          = tibberDP + '.labelToday';
                      let tibberShowLabelTomorrowDP   = tibberDP + '.showLabelTomorrow';
                      let tibberLabelTomorrowDP       = tibberDP + '.labelTomorrow';
                      let tibberWaitTomorrowTextDP    = tibberDP + '.labelTomorrowWait';
                      let tibberShowWaitLabelTomorrowDP = tibberDP + '.showLabelTomorrowWait';
                      let tibberHighlightCurrentHourDP = tibberDP +'.highlightCurrentHour';
                      let tibberHighlightColorDarkDP   = tibberDP + '.highlightColorDark';
                      let tibberHighlightColorLightDP  = tibberDP + '.highlightColorLight';
                      let tibberSteppedLineDP         = tibberDP + '.steppedLine';
                      let tibberShowGraphIfEmptyDP    = tibberDP + '.showGraphIfEmpty';
                      
                      let dpArray                 = [];
                      
                      createStateAsync(tibberHTMLTodayDP, {read: true, write: true, name: "Tibber HTML für Heute", desc:"HTML-DP", type: "string", role: "", def: "" });
                      createStateAsync(tibberHTMLTomorrowDP, {read: true, write: true, name: "Tibber HTML für Morgen", desc:"HTML-DP", type: "string", role: "", def: "" });
                      createStateAsync(tibberColorDP, {read: true, write: true, name: "Farbdefinition für Balken", desc:"JSON-DP", type: "string", role: "", 
                      def: JSON.stringify([{ 'gt': 0,'lte': 0.15, 'color': 'lightgreen' },
                                          {'gt': 0.15,'lte': 0.22,'color': 'green'},
                                          {'gt': 0.22,'lte': 0.29,'color': 'yellow'},
                                          {'gt': 0.29,'lte': 0.35,'color': 'orange'},
                                          {'gt': 0.35,'color': 'red'}]) });
                      createStateAsync(tibberGraphTypeDP, {read: true, write: true, name: "Tibber Graph Typ Auswahl", desc:"GraphType-DP", type: "string", role: "", states: {"bar":"bar","line":"line"} ,def: "bar" });
                      createStateAsync(tibberInstDP, {read: true, write: true, name: "Tibber Instanz", desc:"Instanz-DP", type: "string", role: "", def: "0" });
                      createStateAsync(tibberShowTaxEnergyDP, {read: true, write: true, name: "Tax und Energy anzeigen bei Hover", desc:"Show-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberShowMinMaxAvgDP, {read: true, write: true, name: "Min, Max und Mittelwert anzeigen", desc:"Show-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberShowMinMaxAvgTextDP, {read: true, write: true, name: "Min, Max und Mittelwert Texte anzeigen", desc:"ShowText-DP", type: "boolean", role: "", def: false });
                      createStateAsync(visDP, {read: true, write: true, name: "Welche VIS soll genutzt werden?", desc:"VIS-DP", type: "string", role: "",states: {"jarvis":"jarvis","VIS":"VIS"} , def: "jarvis" });
                      createStateAsync(darkModeDP, {read: true, write: true, name: "DarkMode an?", desc:"DarkMode-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberAreaDP, {read: true, write: true, name: "Fläche unter Kurve?", desc:"CurveArea-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberShowLabelTodayDP, {read: true, write: true, name: "Label Today anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberLabelTodayDP, {read: true, write: true, name: "Label Today für das Chart", desc:"Label-DP", type: "string", role: "", def: "Today-Tageswerte" });
                      createStateAsync(tibberShowLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Tomorrow-Tageswerte" });
                      createStateAsync(tibberShowWaitLabelTomorrowDP, {read: true, write: true, name: "Label Wait Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberWaitTomorrowTextDP, {read: true, write: true, name: "Label Wait Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Werte erst ab 14.00 Uhr verfügbar" });
                      createStateAsync(tibberHighlightCurrentHourDP, {read: true, write: true, name: "Aktuelle Stunde markieren?", desc:"HighlightAktHour-DP", type: "boolean", role: "", def: false });
                      createStateAsync(tibberHighlightColorDarkDP, {read: true, write: true, name: "HighLight Color DarkMode", desc:"HighLight Dark-DP", type: "string", role: "", def: "white" });
                      createStateAsync(tibberHighlightColorLightDP, {read: true, write: true, name: "HighLight Color LightMode", desc:"HighLight Light-DP", type: "string", role: "", def: "grey" });
                      createStateAsync(tibberSteppedLineDP, {read: true, write: true, name: "Gestufte Linie?", desc:"SteppedLine-DP", type: "boolean", role: "", def: false });
                      
                      createStateAsync(tibberShowGraphIfEmptyDP, {read: true, write: true, name: "Graph anzeigen ohne Daten?", desc:"showGraph-DP", type: "boolean", role: "", def: false });
                      
                      // getHistoryAdapter();
                      
                      // setDPs('0'); // -> dpArray 
                      
                      setTimeout(function(){
                          getTibberData(dpArray);
                          let inst = getState(tibberInstDP).val;
                          $('tibberlink.'+inst+'.Homes.*.PricesTomorrow.json').on(function(obj) {
                              setTimeout(function(){
                                  getTibberData(dpArray);
                              },3000)
                          });
                      
                          $('tibberlink.'+inst+'.Homes.*.PricesToday.json').on(function(obj) {
                              setTimeout(function(){
                                  getTibberData(dpArray);
                              },3000);
                          });
                      
                      },3000);
                      
                      let scheduleId ;
                      if(getState(tibberHighlightColorDarkDP).val){
                          scheduleId = schedule('00 * * * *', () => {
                                      
                              getTibberData(dpArray);
                          })
                      }
                      
                      on({id: tibberHighlightCurrentHourDP, change: "any"}, function (obj) {
                          let value = obj.state.val;
                          if(value){
                              getTibberData(dpArray);
                              clearSchedule(scheduleId);
                              scheduleId = schedule('00 * * * *', () => {
                                  getTibberData(dpArray);
                              })
                          }else{
                              clearSchedule(scheduleId);
                              getTibberData(dpArray);
                          }
                      })
                      on({id: tibberShowTaxEnergyDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberColorDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      on({id: tibberShowMinMaxAvgDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberShowMinMaxAvgTextDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      on({id: tibberGraphTypeDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: darkModeDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberAreaDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberShowLabelTodayDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberShowLabelTomorrowDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      on({id: tibberShowWaitLabelTomorrowDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      on({id: tibberHighlightColorDarkDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      on({id: tibberHighlightColorLightDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberSteppedLineDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      on({id: tibberShowGraphIfEmptyDP, change: "any"}, function (obj) {
                          getTibberData(dpArray);
                      });
                      
                      
                      function getTibberData(arr){
                          // arr wird nur für eCharts benötigt
                          
                          // tibberDataDP selbst ermitteln
                          let tibberInst = getState(tibberInstDP).val;
                          let priceArr = ['PricesToday','PricesTomorrow'];
                          for(let x=0;x< priceArr.length;x++){
                              let tibberData = [];
                              let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.'+priceArr[x]+'.json')
                              if(tibberLink[0] != undefined){
                                  let tblLevel = levelObject(tibberLink[0]);
                                  let dpLeveltbl = getDPLevel(tblLevel,4);
                                  let tibberJSON = JSON.parse(getState(dpLeveltbl+'.json').val);
                                  // tibberJSON
                                  for(let i=0;i<tibberJSON.length;i++){
                                      let obj = {};
                                      obj.hour     = parseInt(tibberJSON[i].startsAt.substring(11,13));
                                      obj.start   = tibberJSON[i].startsAt
                                      obj.startTS = new Date(obj.start).getTime();
                                      obj.value   = tibberJSON[i].total;
                                      obj.energy   = tibberJSON[i].energy;
                                      obj.tax   = tibberJSON[i].tax;
                                      obj.min = false;
                                      obj.max = false;
                                      obj.average = false;
                                      obj.level = tibberJSON[i].level;
                                      tibberData.push(obj);
                                  }
                                  // average, minium, maximum direkt holen
                                  
                                  let eleArr = ['average','minimum','maximum'];
                                  for(let i=0;i<eleArr.length;i++){
                                      let obj = {};
                                      switch (eleArr[i]) {
                                              case 'average':
                                                  obj.hour     = 'non'
                                                  obj.start   = ''
                                                  obj.startTS = 0;
                                                  obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                  obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                  obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                  obj.min = false;
                                                  obj.max = false;
                                                  obj.average = true;
                                                  obj.level = '';
                                                  tibberData.push(obj);
                                                  break;
                                              case 'minimum':
                                                  obj.hour    = 'non';
                                                  obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                                  obj.startTS = new Date(obj.start).getTime();
                                                  obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                  obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                  obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                  obj.min = true;
                                                  obj.max = false;
                                                  obj.average = false;
                                                  tibberData.push(obj);
                                                  break;
                                              case 'maximum':
                                                  obj.hour    = 'non';
                                                  obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                                  obj.startTS = new Date(obj.start).getTime();
                                                  obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                  obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                  obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                  obj.min = false;
                                                  obj.max = true;
                                                  obj.average = false;
                                                  tibberData.push(obj);
                                                  break;
                                              default: 
                                                  break;
                                          }
                                  }
                                  // log(tibberData);
                                  let setechart = false;
                                  if(setechart){
                                      for(let i=0;i<dpArray.length;i++){
                                          setHistoryData(dpArray[i],tibberObj[levelObject(dpArray[i])[3]]);
                                      }
                                      seteChartsDP(dpArray);
                                  }
                                  // log('setHTML');
                                  setHTML(tibberData,priceArr[x]);
                                  if(getState(visDP).val=='VIS'){
                                      createHtmlFile(priceArr[x])
                                  }
                              }
                              
                          }
                          
                      }
                      // createHtmlFile();
                      async function createHtmlFile(name) {
                          let dp = '';
                          let file = '';
                          if(name == 'PricesToday'){
                              dp = '0_userdata.0.Strom.tibberHistory.htmlToday';
                              file = 'today';
                          }else{
                              dp = '0_userdata.0.Strom.tibberHistory.htmlTomorrow';
                              file = 'tomorrow';
                          }
                          const htmlContent = getState(dp).val;
                          writeFile('vis.0', '/tibber/'+file+'.html',htmlContent, (err) => {
                              if (err) {
                              console.error('Fehler beim Speichern der HTML-Datei, tibber-Verzeichnis angelegt?', err);
                              } else {
                              console.log('HTML-Datei '+file+'.html erfolgreich gespeichert');
                              }
                          });
                      }
                      
                      
                      
                      function setHTML(origData,priceDP){
                          let data = [];
                          let dataMin = '';
                          let dataMinTime = '';
                          let dataMax = '';
                          let dataMaxTime = '';
                          let dataAvg = '';
                          let dataNull = false;
                          // log(priceDP);
                          let tibberInst = getState(tibberInstDP).val;
                          let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                          let tblLevel = levelObject(tibberLink[0]);
                          let dpLeveltbl = getDPLevel(tblLevel,3);
                          
                          let minToday = getState(dpLeveltbl + '.PricesToday.minimum.total').val;
                          //minToday = minToday-(Math.trunc(minToday*0.1))
                          // log(minToday)
                          let maxToday = getState(dpLeveltbl + '.PricesToday.maximum.total').val
                          let minTomorrow = getState(dpLeveltbl + '.PricesTomorrow.minimum.total').val
                          //minTomorrow = minTomorrow-(Math.trunc(minTomorrow*0.1))
                          let maxTomorrow = getState(dpLeveltbl + '.PricesTomorrow.maximum.total').val
                          let jsonTomorrow = JSON.parse(getState(dpLeveltbl + '.PricesTomorrow.json').val);
                          
                          let graphMin = 0;
                          if(minToday >= minTomorrow){
                              if(minTomorrow != 0){
                                  graphMin = minTomorrow;
                              }else{
                                  graphMin = minToday;
                              }
                          }else{
                              graphMin = minToday;
                          }
                          let graphMax = 0;
                          if(maxToday >= maxTomorrow){
                              graphMax = maxToday;
                          }else{
                              graphMax = maxTomorrow;
                          }
                          // graphMax = Math.round((graphMax + parseFloat((graphMax / 20).toFixed(2))) * 100) / 100;
                          // graphMax = Math.max(Math.ceil(graphMax * 100) / 100, 0.35);
                          if(jsonTomorrow.length ==0 ){
                              graphMin = minToday;
                              graphMax = maxToday
                          }
                          graphMin = Math.ceil(graphMin * 50) / 50 - 0.02;
                          graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                          //log(graphMin)
                      
                          for(let i=0;i<origData.length;i++){
                              if(origData[i].min){
                                  dataMin = origData[i].value;
                                  //log(dataMin);
                                  dataMinTime =origData[i].startTS;
                                  //log(dataMinTime)
                              }
                              if(origData[i].max){
                                  dataMax = origData[i].value;
                                  dataMaxTime =origData[i].startTS;
                              }
                              if(origData[i].average){
                                  dataAvg = origData[i].value;
                              }
                          }
                          if(origData.length>3){
                              for(let i=0;i<origData.length;i++){
                                  if(!origData[i].average && !origData[i].max && !origData[i].min ){
                                      if( origData[i].value < dataAvg){ 
                                          if(origData[i].level == 'NORMAL' ){
                                              data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level})//, color: 'rgba(0,255,0,0.2)', border: levelColor(origData[i].level)
                                          }else{
                                              data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy,level: origData[i].level}) //,  color: levelColor(origData[i].level), border: 'lime'
                                          }
                                      }else{
                                          data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level}) //,color: levelColor(origData[i].level), border: 'red'
                                      }
                                  }else{
                                      if(origData[i].min){
                                          dataMin = origData[i].value;
                                          dataMinTime =origData[i].startTS;
                                      }
                                      if(origData[i].max){
                                          //log(origData[i]);
                                          dataMax = origData[i].value;
                                          dataMaxTime =origData[i].startTS;
                                          //log(dataMaxTime);
                                      }
                                      if(origData[i].average){
                                          dataAvg = origData[i].value;
                                      }
                                  }
                                  
                              }
                              // log('oben '+graphMin)
                          }else{
                              dataNull = true;
                              //dataMin = String(graphMin);
                              //dataMax = String(graphMax);
                              //dataMax = "0";
                              //dataAvg = '0.01';
                              //graphMin = minToday;
                              //graphMax = maxToday;
                              //graphMin = Math.ceil(graphMin * 50) / 50 - 0.01;
                              //graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                          }
                          // Werte holen
                          let showTaxEnergy = getState(tibberShowTaxEnergyDP).val;
                          let minMaxAvg = getState(tibberShowMinMaxAvgDP).val;
                          let colorJSON = getState(tibberColorDP).val;
                      
                          let html = '';
                          html += '<!DOCTYPE html>';
                          html += '<html lang="en">';
                          html += '<head>';
                          html += '<meta charset="UTF-8">';
                          html += '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
                          html += '<title>Tibber-Tageswert</title>';
                          html += '<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>';
                          html += '<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>';
                          html += '</head>';
                          html += '<body>'
                          if(getState(visDP).val == 'VIS'){
                              html += '<div id="chart-container" style="width: 600px; height:400px;"></div>';
                          }else{
                              html += '<div id="chart-container" style="width: 100%; height:400px;"></div>';
                          }
                          //log(data);
                          html += '<script>'
                          html += '    var data = '+JSON.stringify(data)+';';
                          html += '    var chartContainer = document.getElementById("chart-container");'
                          html += '    var myChart = echarts.init(chartContainer);';
                      
                         
                          html += '    function formatTime(time) {';
                          html += '        return moment(time).format("HH");'
                          html += '    }';
                          html += '    function calculateArrowPosition(hour){'
                          //html += '       console.log((hour) * (100 / 24) + "%");'
                          html += '       return (hour / 24) * 100 +1 + "%";'
                          html += '    }'
                          html += '    function updateChart() {';
                          html += '        var minValue = Math.min.apply(null, data.map(function (item) {';
                          html += '          return item.value;';
                          html += '        }));';
                          //html += '        console.log(minValue);'
                          // html += '        var yAxisMin = minValue - (minValue/10);'
                          html += '        var yAxisMin = '+graphMin+';';
                          html += '        var maxValue = '+dataMax+';'
                          //html += '        var maxValue = '+graphMax+';'
                          //html += '        console.log(maxValue);'
                          // html += '        var yAxisMax = maxValue + (maxValue/10);'
                          html += '        let avgValue = '+dataAvg+';'
                          html += '        var visualMapPieces =' + colorJSON +';';
                          html += '        var values = data.map(item => (item.value-minValue).toFixed(2));'
                          html += '        var maxLineValue = Math.max.apply(null, values);'
                          html += '        var maxLineIndex = values.indexOf(maxLineValue);'
                          html += '        var maxLineData = {time:'+dataMaxTime+',value:'+dataMax+'};'
                          html += '        var currentHour = new Date().getHours() ;'
                          // html += '        console.log(currentHour);'
                          //html += '        console.log(maxLineData.time);'
                          // html += '        var maxV = parseFloat((Math.max(...values)));'
                          //html += '        console.log(maxV);'
                          //html += '        let pro = values.map((value) => (value/maxV).toFixed(2));'
                          //html += '        console.log(values);'
                          //html += '        console.log(pro);'
                          html += '        var colorStops = [];'
                          //html += '        console.log(yAxisMin +" "+maxValue);'
                          if(!dataNull){
                          html += '        visualMapPieces.map(piece => {'
                          html += '          if(piece["lte"] >=yAxisMin && piece["gt"]<=maxValue){ '
                          //html += '            console.log(piece["lte"] + " "+maxValue + " "+ yAxisMin);'
                          html += '            if(piece["gt"]>=yAxisMin){'
                          //html += '             console.log(piece["gt"] +" gt gesetzt " +yAxisMin);'
                          html += '             colorStops.push({'
                          html += '              offset:  ((piece["gt"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                          html += '              color: piece.color'
                          html += '             });'
                          html += '            }'
                          html += '            if(piece["lte"]<=maxValue){'
                          //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                          html += '             colorStops.push({'
                          html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                          html += '              color: piece.color'
                          html += '             });'
                          html += '            }'
                          html += '            if(piece["lte"]>maxValue ){'
                          //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                          html += '            colorStops.push({'
                          html += '              offset:  1,'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                          html += '              color: piece.color'
                          html += '             });'
                          //html += '            }'
                          html += '           };'
                          html += '          }else{'
                          //html += '            console.log(piece["lte"] + " " + piece["gt"]);'
                          html += '           if(piece["lte"]>=maxValue && piece["gt"]<=maxValue ){'
                          //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                          html += '            colorStops.push({'
                          html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                          html += '              color: piece.color'
                          html += '            });'
                      
                          html += '           }else if(piece["lte"]>=maxValue && piece["gt"] <= maxValue){'
                          // html += '            console.log("Drin");'
                          html += '            colorStops.push({'
                          html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                          html += '              color: piece.color'
                          html += '            });'
                          html += '           }'
                          html += '          }; ' 
                          html += '        });'
                          //html += '        console.log(colorStops);'
                          //html += '        console.log(colorStops[colorStops.length-1].color);'
                          html += '        colorStops.push({'
                          html += '            offset: 1,' //visualMapPieces[visualMapPieces.length - 1]["gt"]
                          html += '            color: colorStops[colorStops.length-1].color'// visualMapPieces[visualMapPieces.length - 1].color'
                          html += '        });'
                          //html += '        console.log(colorStops);'
                          html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                          //html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                          //html += '        colorStops.splice(2, 0, {offset: colorStops[1].offset,color:colorStops[2].color});'
                          //html += '        colorStops.splice(4, 0, {offset: colorStops[3].offset,color:colorStops[4].color});'
                          //html += '        console.log(colorStops);'
                          }
                          if(dataNull && !getState(tibberShowGraphIfEmptyDP).val){
                              html += '        myChart.setOption({';
                          html += '            title: {';
                          if(priceDP== 'PricesToday'){
                              html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                              if(getState(tibberShowLabelTodayDP).val){
                                  html += '            show: true'
                              }else{
                                  html += '            show: false'
                              }
                          }else{
                              if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                                    html += '          textAlign: "auto", '
                                    html += '          textStyle: { '
                                    html += '             color: "red"'
                                    html += '          },'
                                    html += '          left: "50px",'
                                    html += '          text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                              }else{
                                  html += '            text: "'+getState(tibberLabelTomorrowDP).val+'",';
                                  if(getState(tibberShowLabelTomorrowDP).val){
                                      html += '        show: true,'
                                  }else{
                                      html += '        show: false,'        
                                  }
                              }
                              
                              
                          }
                          
                          html += '                 },});';
                          }else{
                      
                          html += '        myChart.setOption({';
                          html += '            title: {';
                          if(priceDP== 'PricesToday'){
                              html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                              if(getState(tibberShowLabelTodayDP).val){
                                  html += '                show: true'
                              }else{
                                  html += '                show: false'
                              }
                          }else{
                              if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                                    html += '            textAlign: "auto", '
                                    html += '            textStyle: { '
                                    html += '               color: "red"'
                                    html += '            },'
                                    html += '            left: "50px",'
                                    html += '            text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                              }else{
                                  html += '                text: "'+getState(tibberLabelTomorrowDP).val+'",';
                                  if(getState(tibberShowLabelTomorrowDP).val){
                                      html += '                show: true,'
                                  }else{
                                      html += '                show: false,'        
                                  }
                              }
                              
                              
                          }
                          
                          html += '            },';
                          html += '            visualMap: {';
                          html += '              type: "piecewise",'
                          html += '              pieces: visualMapPieces,'
                          html += '              dimension: 1,' // Mapping to the 'value' dimension'
                          html += '              showLabel: true,'
                          html += '              precision: 2,'
                          html += '              itemWidth: 6,'
                          html += '              orient: "horizontal",'
                          html += '              left: "center", calculable: true,selectedMode: "multiple",'
                          html += '              bottom: 10,'
                          html += '              text: ["High", "Low"],'
                          html += '              textStyle: {'
                          if(getState(darkModeDP).val){
                              html += '                color: "white"'
                          }else{
                              html += '                color: "black"'
                          }
                          html += '              },'
                          //html += '              inRange: {'
                          //html += '                color: colorStops.map(stop => stop.color)';//visualMapPieces.map(piece => piece.color)'
                          //html += '              },'
                          /* bringt nichts
                          html += '              itemStyle:{'
                          html += '                 symbol:"pin",'
                          html += '                 symbolSize: 30,'
                          html += '                 markPoint: {'
                          html += '                   data: [{'
                          html += '                    symbol: "circle",'
                          html += '                       coord: [data.time, data.value], itemStyle:{ color:"red"}'
                          html += '                    }]'
                          html += '                 },'
                          html += '               }'
                          */
                          html += '            },'
                          
                          if(minMaxAvg){
                              html += '            grid: {';
                              if(getState(tibberShowMinMaxAvgTextDP).val){
                                  html += '              right: 50,'; // Vergrößern Sie diesen Wert nach Bedarf
                              }else{
                                  html += '              right: 10,';
                              }
                              html += '              left: 10,';
                              html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                              html += '            },';
                          }else{
                              html += '            grid: {';
                              html += '              right: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                              html += '              left: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                              html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                              html += '            },';
                          }
                          html += '            areaStyle: {'
                          html += '              color: colorStops';//"red"'; visualMapPieces.map(piece => piece.color)'
                          //html += '              color: "blue", '
                          html += '            },'
                          // Option für Pfeil unter Kurve
                          /*
                          if(!dataNull && getState(tibberHighlightCurrentHourDP).val){
                          html += 'graphic: [{'
                          html += '    type: "image",'
                          html += '    id: "arrow",'
                          html += '    bounding: "all",'
                          html += '    z:100,'
                          //html += '    origin: [calculateArrowPosition(currentHour), "10%"],'
                          //html += '    origin: [0.5, 0],'  // Koordinaten für den Pfeil
                          html += '    bottom: "10%", '
                          html += '    left: calculateArrowPosition(currentHour),';//"50px",'
                          html += '    '
                          html += '    style: {'
                          html += '        image: "https://api.iconify.design/mdi/arrow-up-bold.svg?width=24&height=24&color=blue", ' // Pfad zum Bild deines Pfeils
                          html += '        width: 30,'
                          html += '        height: 30,'
                          html += '    }'
                          html += '}],'
                          }
                          */
                          // ToolBox
                          html += '            toolbox: {';
                          html += '              feature: {';
                          html += '                saveAsImage: {';
                          html += '                   backgroundColor: "rgba(38, 37, 37, 1)",';
                          html += '                   title: "Speichern",';
                          let fileName = priceDP.replace('Prices','') 
                          if(fileName == 'Today'){
                              fileName += ' '+ formatDate(new Date(),'DD.MM.YYYY'); 
                          }else{
                              fileName += ' '+ formatDate(new Date().getTime()+86400000,'DD.MM.YYYY'); 
                          }
                          html += '                   name: "TibberHTML '+fileName+'"'
                          html += '                },'
                          html += '                magicType: {';
                          html += '                  type: ["line", "bar"],';
                          html += '                  title:{';
                          html += '                     line: "Line-Chart",';
                          html += '                     bar: "Bar-Chart",';
                          html += '                  }'
                          
                          html += '                },';
                          html += '                dataView: {';
                          html += '                  title: "Daten aus der Serie",';
                          html += '                  lang: ["Daten der Kurve", "Schließen", "Aktualisieren"],'
                          html += '                  optionToContent: function (opt) {';
                          html += "                      var table = '<table style=\"width:100%;\"><tbody><tr style=\"text-align: left;\"><th>Stunde</th><th>Wert</th><th>Energie</th><th>Steuer</th><th>Level</th></tr>';";
                          //html += '                      console.log(opt.series.length); '
                          //html += '                      console.log(opt.series[0].data); '
                          html += '                      for (var i = 0; i< opt.series[0].data.length;i++) {';
                          html += '                          table += "<tr>";';
                          html += '                         for(let x =0; x < opt.series[0].data[i].value.length; x++){'
                          html += '                            if(x==0){';
                          html += '                               table +=  "<td>" + ("0"+new Date(opt.series[0].data[i].value[x]).getHours()).slice(-2) + "</td>";';
                          html += '                            }else{';
                          html += '                               table +=  "<td>" + opt.series[0].data[i].value[x] + "</td>";';
                          html += '                            } '
                          html += '                         }';
                          html += '                           table += "</tr>";';
                          html += '                      }';
                          html += '                      table += "</tbody></table>";'
                          html += '                      return table;';
                          html += '                  },';
                          html += '                  readOnly: true';
                          html += '                },'
                          html += '              }';
                          html += '            },'
                          
                          html += '            xAxis: {';
                          html += '                type: "time",';
                          html += '                axisLabel: {';
                          html += '                    show: true,'
                          html += '                    formatter: function (value) {';
                          html += '                        return formatTime(value);';
                          html += '                    }';
                          html += '                },';
                          html += '                splitNumber: 10,';
                      	html += '            },';
                          html += '            yAxis: {';
                          html += '                type: "value",';
                          html += '                axisLabel: {'; 
                          
                          html += '                  formatter: function (value) {';
                          html += '                     return value.toFixed(3) + " €";';
                          html += '                  }';
                          
                          html += '                },';
                          
                          html += '               min: '+graphMin+','; //
                          html += '               max: '+graphMax+',' //yAxisMax
                          html += '            },';
                          
                          
                      
                      
                      
                          html += '            series: [{';
                          
                          html += '                data: data.map(function (item) {';
                          html += '                    var hour = new Date(item.time).getHours();'
                          html += '                    return {';
                          html += '                       value: [item.time, item.value, item.energy, item.tax, item.level],';
                          //html += '                       lineStyle: {width: hour === currentHour ? 10:null},'
                          
                          // Symbol für Line einstellen
                      
                          html += '                        symbol: "circle",'
                          
                          if(getState(tibberHighlightCurrentHourDP).val && priceDP == 'PricesToday'){
                              html += '                    symbolSize: hour === currentHour ? 10:null, '
                              html += '                    itemStyle: {'
                                 
                              if(getState(darkModeDP).val){
                                  //html += '                           backgroundColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                  html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                  html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                  html += '                           borderWidth: hour === currentHour ? 2:null,'
                                  html += '                           shadowBlur: hour === currentHour ? 20:null,'
                              }else{
                                  html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                                  html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                                  html += '                           borderWidth: hour === currentHour ? 1:null,'
                                  html += '                           shadowBlur: hour === currentHour ? 10:null,'
                              }
                              //html += '                           borderWidth: hour === currentHour ? 1:null,'
                              //html += '                           shadowBlur: hour === currentHour ? 10:null,'
                              
                              html += '                     },'
                              
                          }
                          // Aria für Schraffierung
                          //html += 'aria: {'
                          //html +='    enabled: true,'
                          //html += '   decal: {'
                          //html +='        show: hour === currentHour'
                          //html += '   }'
                          //html +='},'
                          html += '                        emphasis: {';
                          html += '                          itemStyle: {';
                          html += '                            color: "white" '; // Füge die Farbe in die Betonung ein
                          html += '                          },';
                          html += '                          label: {';
                          html += '                            show: true,';
                          html += '                            formatter: function (params) {';
                          html += '                               return params.data.value[1].toFixed(3) + " €";'; //console.log(params);
                          html += '                            },';
                          html += '                            color: "black",';
                          html += '                            fontWeight: "bold", ';
                          html += '                            backgroundColor: "white"';
                          html += '                          }';
                          html += '                        }';
                          html += '                     } ';
                          html += '                }),'; // end data
                          
                          if(getState(tibberSteppedLineDP).val){
                              html += '            step: "end",'
                          }
                          // ItemStyle
                          //html += '                itemStyle:{'
                          //html += '                  color: function (params) {'
                                      // Färbe den Balken der aktuellen Stunde anders ein
                          //html += '                    console.log(new Date(params.value[0]).getHours());'
                          //html += '                    console.log(currentHour);'
                          //html += 'console.log(new Date(params.value[0]).getHours() === currentHour ? "red" : "blue");'
                          //html += '                    return new Date(params.value[0]).getHours() === currentHour ? "red" : "blue";'
                          //html += '                  }'
                          //html += '                },'
                          if(getState(tibberAreaDP).val){
                          html += '                areaStyle:{'
                          html += '                    color: new echarts.graphic.LinearGradient(0, 1, 0, 0, colorStops),' ;
                          
                          //html += '                    color:  colorStops,'
                          // html += '                    max: maxValue, '
                          /*
                          html += '                    color: function (params) {'
                          html += '                       console.log(params);'
                          html += '                       var wert = params.data.value[1];'
                          html += '                       var col = "red";'
                          html += '                       for (var i = 0; i < visualMapPieces.length; i++) {'
                          html += '                           var piece = visualMapPieces[i];'
                          html += '                           if (wert >= piece.gt && wert <= piece.lte) {'
                          html += '                               col = piece.color;'
                          html += '                               break;'
                          html += '                           }'
                          html += '                       }'
                          html += '                       return col;'
                          html += '                   },'
                          */
                          html += '                },'
                          }
                          html += '                type: "'+getState(tibberGraphTypeDP).val+'",';
                          //html += '               markArea: {'
                          //html += '                   silent: true,'
                          //html += '                   data: ['
                          //html += '                       [{'
                          //html += '                           xAxis: "min",'
                          //html += '                           itemStyle: {'
                          //html += '                               color: "rgba(0, 0, 0, 0.7)"'
                          //html += '                           }'
                          //html += '                           }, {'
                          //html += '                               xAxis: "max",'
                          //html += '                       }]'
                          //html += '                   ]'
                          //html += '               },'
                          
                          if(minMaxAvg){
                              html += '                markLine: {';
                              html += '                  symbol: "none",';  // Kein Symbol für die Markierungslinie
                              html += '                  lineStyle: {';
                              html += '                    color: "red",';   // Farbe der Markierungslinie
                              html += '                    type: "dashed"';  // Art der Linie (gestrichelt)
                              html += '                  },';
                              
                              if(getState(tibberShowMinMaxAvgTextDP).val){ //coord: [maxLineData.time, maxLineData.value] ,)
                                  if(!dataNull){
                                  html += '                  data: [';
                                  html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: true, position: "end", formatter: "Min\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                                  html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: true, position: "end", formatter: "Max\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                                  html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: true, position: "end", formatter: "Avg\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                                  html += '                  ], '
                                  }
                              }else{
                                  if(!dataNull){
                                  html += '                  data: [';
                                  // funktioniert nicht !,tooltip: {show: true,formatter: "Min\\n\\n" + params.value.toFixed(3) + " €",textStyle: {fontSize: 12,fontWeight: "bold",color: "white"}}  ,formatter: "Min " + minValue.toFixed(3) + " €"
                                  html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: false, position: "end", formatter: "Min\\n\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                                  html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: false, position: "end", formatter: "Max\\n\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                                  html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: false, position: "end", formatter: "Avg\\n\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                                  html += '                  ], '    
                                  }    
                              }
                              html += '                }';
                          }
                          html += '            }],'; // Ende Series
                      
                      
                          
                      
                          html += '            tooltip: {';
                          html += '              trigger: "axis",';
                          html += '              axisPointer: {';
                          html += '               type: "shadow"';
                          html += '              },';
                          html += '              textStyle: {';
                          html += '                fontFamily: "Courier",';
                          html += '                fontWeight: "bold"'; // Hinzugefügt
                          html += '              },'
                          html += '              formatter: function (params) {';
                          html += '                let time = "Start ab: "+ moment(params[0].axisValue).format("HH:mm")+ " Uhr";';
                          html += '                let value = "Preis:&nbsp&nbsp&nbsp&nbsp"+params[0].value[1].toFixed(4) + " €";';
                          if(showTaxEnergy){
                              html += '            let energy = "Energie:&nbsp&nbsp"+params[0].value[2].toFixed(4) + " €";'
                              html += '            let tax    = "Steuer:&nbsp&nbsp&nbsp"+params[0].value[3].toFixed(4) + " €";'
                              html += '            let lev    = "Level:&nbsp&nbsp&nbsp&nbsp"+ params[0].value[4];'
                              html += "            return  `${time}<br/>${value}<br/>${energy}<br/>${tax}<br/>${lev}` ;";
                          }else{
                              //html += "            return `<span style=\"font-family: 'Arial'; font-weight: 'bold';\" >${time}<br/>${value}</span>` ;";
                              html += "            return `${time}<br/>${value}` ;";
                          }
                          
                          html += '              }';
                          html += '            },';
                          
                          html += '        }) ';// end setOption
                          }
                          html += '    }'; 
                          
                      
                          html += '    updateChart(); ';
                          html +='     var updateInterval = setInterval(updateChart, 3600000);'
                          html += '</script>';
                          html += '</body>';
                          html += '</html>';
                      
                          // log(html);
                          if(priceDP == 'PricesToday'){
                              setState(tibberHTMLTodayDP,html);
                          }else{
                              setState(tibberHTMLTomorrowDP,html);
                          }
                      }
                      
                      
                      
                      function sortByName(x, y) {
                          // Wenn x oder y nicht-numerisch sind, setze sie an das Ende
                          if (isNaN(x.hour) || isNaN(y.hour)) {
                              return isNaN(x.hour) ? 1 : -1;
                          }
                          
                          // Vergleiche numerische Werte
                          return x.hour - y.hour;
                      }
                      
                      
                      
                      on({id: dbHistoryDP, change: "any"}, function (obj) {
                          let value = obj.state.val;
                          // history für die DPs aktiv?
                          if (value!=''){
                              if (getState('system.adapter.'+value+'.alive').val){
                                  if (isHistoryActiveAllDPs(dpArray)){
                                      if(logging){
                                          log('History-Future-DPs sind angelegt und History aktiviert!');
                                      }
                                      // getPVData(dpArray);
                                      //runScript();
                                  }else{
                                      if(logging){
                                          log('History wird angelegt für die future-DPs!');
                                      }
                                      activateDPsHistory(dpArray);
                                      setTimeout(function(){
                                          deleteAllHistoryDPs(dpArray);
                                          // log('gelöscht');
                                          // getPVData(dpArray);
                                      },3000)
                                      //runScript();
                                  }
                              }else{
                                  log('Der History-Adapter ist nicht gestartet! -> Es werden keine DPs mit History aktiviert','warn');
                              }
                          }
                      });
                      
                      
                      function setDPs(tibberInst){
                          // Ist der Adapter aktiv
                          // 
                          //let pvAliveDP = 'system.adapter.pvForecast.'+tibberInst+'.alive';
                          //if(existsState(pvAliveDP)){
                          //    if(getState(pvAliveDP).val){
                                  // Adapter ist gestartet
                                  let tibberKeys = ['Value','Tax','Energy']
                                  for(let i=0;i<tibberKeys.length;i++){
                                          dpArray.push(tibberDP+'.future'+tibberKeys[i]);
                                  }
                                  
                          //    }else{
                          //        log('Der Adapter tibberlink.'+tibberInst+' ist nicht gestartet!');
                          //    }
                          //}else{
                          //    log('Der Adapter pvForecast ist nicht installiert')
                          //}
                          // Alte erst löschen
                          // Nur löschen, wenn sich die DPs geändert haben
                          let delItems = false;
                          if(dpArray.length >0){
                              // delDPs(dpArray);
                              
                              for(let i=0;i<dpArray.length;i++){
                                  if(existsState(dpArray[i])){
                      
                                  }else{
                                      delItems = true;
                                      delDPs(dpArray);
                                      break;
                                  }
                              }
                          }
                          if(delItems){
                              setTimeout(function() {
                                  if(dpArray.length >0){
                                      createDPs(dpArray);
                                  }
                              },3000);
                          }else{
                              createDPs(dpArray);
                          }
                      }
                      
                      
                      function delDPs(arr){
                          for(let i=0; i<arr.length;i++){
                              if(existsState(arr[i])){
                                  deleteStateAsync(arr[i]);
                              }
                          }
                      }
                      // createStateAsync(futureTempDP, {read: true, write: false, name: "daswetter temperature", type: "number", role: "", def: 0 });
                      
                      function createDPs(arr){
                          for(let i=0; i<arr.length;i++){
                              // 0_userdata.0.pvForecastHistory.historyDB
                              let name =  levelObject(arr[i])[3];
                              createStateAsync(arr[i], {read: true, write: false, name: "tibber"+name, type: "number", role: "", def: 0 });
                          }
                      }
                      
                      
                      function seteChartsDP(dpArray){
                          let startDT = getDateObject('00:00').getTime(); // heute 00:00
                          // pvForecast hat nur 2 Tage im Array
                          let endDT = startDT + 24*1*60*60*1000;
                          // start_time, end_time, start, end, timeType
                          for(let i=0;i<dpArray.length;i++){
                              let echartDP = 'echarts.0.tibber'+levelObject(dpArray[i])[3];
                              let obj; 
                              if (existsObject(echartDP)){
                                  obj = getObject(echartDP);
                                  //log(obj);
                                  if (obj.native.data.timeType == 'static'){
                                      obj.native.data.start = formatDate(startDT,'YYYY-MM-DD');
                                      obj.native.data.end   = formatDate(endDT,'YYYY-MM-DD');
                                      obj.native.data.start_time = '00:00';
                                      obj.native.data.end_time = '00:00';
                                      setObject(echartDP,obj);
                                  }
                              }
                          }
                      }
                      
                      
                      
                      function isHistoryActiveAllDPs(dpArray){
                          // dparray automatisch gesetzt
                          let active = false;
                          let dbHistory = getState(dbHistoryDP).val;
                          if (dbHistory != ''){
                              for(let i= 0;i<dpArray.length;i++){
                                  let dpPara = levelObject(dpArray[i])[3];
                                  // log('dpPara: '+dpPara);
                                  // log(pvForecastDP+'.future'+dpPara);
                                  // setActiveHistory(pvForecastDP+'.future'+dpPara);
                                  active = isHistoryActive(tibberDP+'.'+dpPara,dbHistory);
                                  if(active == false){
                                      return false;
                                  }
                              }
                              
                              log('Tibber-DPs History aktiv');
                              return true;
                          }else{
                              log('DB Auswahl fehlt');
                              return false;
                          }
                      }
                      
                      function isHistoryActive(dp,db){
                          let obj = getObject(dp);
                          if (obj.common.custom != undefined){
                              //log(obj.common.custom);
                              let custom = obj.common.custom;
                              
                              for (let key in custom){
                                  //log(key);
                                  if (key.indexOf(db)>=0){  //'history'
                                      return true;
                                  }
                              }
                          }
                          return false;
                      }
                      
                      function activateDPsHistory(dpArray){
                          let historyDB = getState(dbHistoryDP).val;
                          //log('HistoryDB: '+historyDB);
                          if (historyDB != ''){
                              if (getState('system.adapter.'+historyDB+'.alive').val){
                      
                                  if (historyDB!=''){
                                      for(let i= 0;i<dpArray.length;i++){
                                          //log('DParray[i]: '+dpArray[i]);
                                          let dpPara = levelObject(dpArray[i])[3];
                                          //log('dpPara: '+dpPara);
                                          //log(pvForecastDP+'.'+dpPara);
                                          setActiveHistory(tibberDP+'.'+dpPara);
                                          setTimeout(function(){
                                              deleteAllHistoryData(tibberDP+'.'+dpPara);
                                          },2000)
                                      }
                                      log('Future-DPs History aktiviert');
                                  }else{
                                      log('Es wurde keine DB für Future-History ausgewählt!','warn');
                                  }
                              }else{
                                  log('Der Adapter ist nicht gestartet! -> keine Aktivierung möglich','warn');
                              }
                          }else{
                              log('Aktivierung der DPs für die DB erst möglich, wenn man eine DB ausgewählt hat!','warn');
                          }
                      }
                      
                      
                      // deleteAllHistoryDPs();
                      
                      function deleteAllHistoryDPs(dpArray){
                          let dbHistory = getState(dbHistoryDP).val;
                          if (getState('system.adapter.'+dbHistory+'.alive').val){
                              log('History DPs dpArray löschen!');
                              for(let i= 0;i<dpArray.length;i++){
                                  //log('DParray[i]: '+dpArray[i]);
                                  let dpPara = levelObject(dpArray[i])[3];
                                  //log('dpPara: '+dpPara);
                                  //log(pvForecastDP+'.'+dpPara);
                                  deleteAllHistoryData(tibberDP+'.'+dpPara);
                                  
                              }
                              log('Future-DPs History gelöscht');
                          }else{
                              log('Adapter nicht gestartet!');
                          }
                      }
                      
                      
                      function deleteAllHistoryData(dp){
                          let dbHistory = getState(dbHistoryDP).val;
                          if (dbHistory!=''){
                              //let dtStart= getDateObject('00:00').getTime(); // heute 00:00 Uhr
                              //let dtStop = dtStart + 24*6*60*60*1000;
                              sendTo(dbHistory, 'deleteAll', [       // 'history.0' 'deleteRange'
                                  {id: dp}//, start: dtStart, end: dtStop
                                  
                              ], result => {//console.log('deleted')
                              });
                          }else{
                              log('Löschen nicht durchgeführt, da keine HistoryDB festgelegt');
                          }
                      }
                      
                      
                      
                      function getHistoryAdapter(){
                          // history, influxdb, sql
                          log('Einlesen der vorhandenen History-DBs.');
                          let histArr = ['history','influxdb','sql'];
                          let arr =[];
                          for (let i=0; i<histArr.length;i++){
                              let dp = $('system.adapter.'+histArr[i]+'.*.alive');
                              //log(dp);
                              for(let x=0;x<dp.length;x++){
                                  //log(dp[x]);
                                  let dpID = dp[x];
                                 
                                  if (getObject(dpID).common != undefined){
                                      //log(getState(dpID).val);
                                      if (getState(dpID).val != null && getState(dpID).val){
                                          dp[x] = dp[x].substring(15,dp[x].length-6);
                                          // log(dp[x]);
                                          arr.push(dp[x]);
                                      }
                                      if (getState(dpID).val == null){
                                          log('History-Adapter ist fehlerhaft: '+dp[x] +' -> alive auf false setzen');
                                      }
                                  }
                              }
                      
                          }
                          let devStates = {'':'keine Auswahl'};
                          for (let i=0; i< arr.length;i++){
                              devStates[arr[i]] = arr[i];
                          }
                          //log(devStates);
                          if (existsState(dbHistoryDP)){
                              let obj = getObject(dbHistoryDP);
                              obj.common.states = devStates;
                              setObject(dbHistoryDP,obj);
                          }else{
                              createStateAsync(dbHistoryDP, {read: true, write: true, name: "DB-Auswahl", type: "string", role: "", def: '',states:devStates });    
                          }
                      }
                      
                      
                      
                      
                      function setActiveHistory(dp){
                          let dbHistory = getState(dbHistoryDP).val;
                          //log('dbHistory setActive: '+dbHistory);
                          if (dbHistory !=''){
                              sendTo(dbHistory, 'enableHistory', { // 'history.0'
                                  id: dp,  // 'system.adapter.history.0.memRss'
                                  options: {
                                      changesOnly:  true,
                                      debounce:     0,
                                      retention:    31536000,
                                      maxLength:    3,
                                      changesMinDelta: 0,
                                      //ignoreZero: true,
                                      aliasId: '',
                                      enabled: true,
                                      debounceTime: 0,
                                      blockTime: 0,
                                      changesRelogInterval: "0",
                                      ignoreBelowNumber: "",
                                      disableSkippedValueLogging: false,
                                      customRetentionDuration: 365,
                                      enableDebugLogs: false
                              
                                  }
                              }, function (result) {
                                  if (result.error) {
                                      console.log(result.error);
                                  }
                                  if (result.success) {
                                      //successfull enabled
                                      //log(dp +' wurde in history aktiviert');
                                  }
                              });
                          }
                      }
                      
                      // setHistoryData(futureHumidityDP,dpValueArr);
                      
                      function setHistoryData(dp,states){
                          let dbHistory = getState(dbHistoryDP).val;
                          if (dbHistory!=''){
                              sendTo(dbHistory, 'storeState', { // 'history.0'
                                  id: dp,
                                  state: states
                                  }, result => {
                                      // console.log('added')
                                  });
                          }
                      }
                      
                      
                      
                      function levelObject(id){
                          // 0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff
                          let idArr=id.split('.');
                          return idArr; //log(idArr[10]);
                      }
                      
                      // log(getDPLevel(levelObject('0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff'),9));
                      function getDPLevel(idArr,level){
                          let id ='';
                          for (let i=0;i<=level;i++){
                              id += idArr[i] +'.'
                          }
                          id = id.substr(0,id.length-1); // letzten Punkt wegnehmen
                          return id;
                      }
                      
                      M 1 Reply Last reply
                      0
                      • M Meikie
                        // *********************************
                        // tibberHTML v1.0.24
                        // *********************************
                        // Copyright ©MCU
                        // v1.0.1 - Erweiterung Umschaltung Line/bar im Graph, Anzeige der Werte in Tabelle
                        // v1.0.2 - Vis Auswahl -> fete Breite für VIS, darkMode
                        // v1.0.3 - Min,max,avg kleiner, untereinander, rechts Breite kleiner
                        // v1.0.4 - ShowMinMaxAvgTexte optional
                        // v1.0.5 - toolBox -Speichern mit Namen+Datum
                        // v1.0.6 - y-Skala auf beiden Kurven gleich 
                        // v1.0.7 - splitNumber auf 10 vorher 3, grid rechts 10 statt 30, visualMap - mobile optimiert
                        // v1.0.8 - CurveArea optional, Korrektur wenn tomorrow.mim = 0 -> graphMin =0
                        // v1.0.9 - graphMax angepasst auf nächste 0.01
                        // v1.0.10- graphMin angepassz auf nächste 0.01
                        // v1.0.11- Label optional, falls man schon Widget-Title nutzt 
                        // v1.0.12 - Trennung Label Today und Tomorrow
                        // v1.0.13 - optionaler Text für Tomorrow Wait
                        // v1.0.14 - automatischer Reload bei Umschaltung wait-Text Tomorrow
                        // v1.0.15 - aktuelle Zeit highlightCurrentHour
                        // v1.0.16 - Symbol für Line aktuelle Stunde angepasst
                        // v1.0.17 - stepped line hinzugefügt, Korrekturen graphMin
                        // v1.0.18 - Korrektur showwait
                        // v1.0.19 - Korrektur showwait
                        // v1.0.20 - Abschaltung Anzeige Graph, wenn leer, Korrektur highlightPoint
                        // v1.0.21 - Korrektur dataNull für visualMapPieces
                        // v1.0.22 - Inhalt von DPs als Datei speichern
                        // v1.0.23 - Korrektur 1.Farbelement lte > maxValue
                        // v1.0.24 - Korrektur 1. Farbelement Umstellung Linie, falsche Berechnung
                        // ToDo
                        // - optionale Zeit vor günstiger Stunde telegram senden, alexa info, pushOver senden
                        // - Ersparnis in Prozent -> Tabelle / Anzeige?
                        // - Stunden erweitern für steppedLine?
                        
                        let logging                     = true;
                        let tibberDP                    = '0_userdata.0.Strom.tibberHistory';
                        let dbHistoryDP                 = tibberDP + '.historyDB';
                        let tibberGraphTypeDP           = tibberDP + '.graphTyp'; // bar  oder line
                        let tibberInstDP                = tibberDP + '.instanz'; // 0
                        let tibberColorDP               = tibberDP + '.colorJSON'; // visualMapPieces [ {gt: 0, lte: 0.15, color: "lightgreen"},]
                        let tibberHTMLTodayDP           = tibberDP + '.htmlToday';
                        let tibberHTMLTomorrowDP        = tibberDP + '.htmlTomorrow';
                        let tibberShowTaxEnergyDP       = tibberDP + '.showTaxEnergy'; // boolean
                        let tibberShowMinMaxAvgDP       = tibberDP + '.showMinMaxAvg'; // boolean
                        let visDP                       = tibberDP + '.vis';
                        let darkModeDP                  = tibberDP + '.darkMode';
                        let tibberShowMinMaxAvgTextDP   = tibberDP + '.showMinMaxAvgText';
                        let tibberAreaDP                = tibberDP + '.curveArea';
                        let tibberShowLabelTodayDP      = tibberDP + '.showLabelToday';
                        let tibberLabelTodayDP          = tibberDP + '.labelToday';
                        let tibberShowLabelTomorrowDP   = tibberDP + '.showLabelTomorrow';
                        let tibberLabelTomorrowDP       = tibberDP + '.labelTomorrow';
                        let tibberWaitTomorrowTextDP    = tibberDP + '.labelTomorrowWait';
                        let tibberShowWaitLabelTomorrowDP = tibberDP + '.showLabelTomorrowWait';
                        let tibberHighlightCurrentHourDP = tibberDP +'.highlightCurrentHour';
                        let tibberHighlightColorDarkDP   = tibberDP + '.highlightColorDark';
                        let tibberHighlightColorLightDP  = tibberDP + '.highlightColorLight';
                        let tibberSteppedLineDP         = tibberDP + '.steppedLine';
                        let tibberShowGraphIfEmptyDP    = tibberDP + '.showGraphIfEmpty';
                        
                        let dpArray                 = [];
                        
                        createStateAsync(tibberHTMLTodayDP, {read: true, write: true, name: "Tibber HTML für Heute", desc:"HTML-DP", type: "string", role: "", def: "" });
                        createStateAsync(tibberHTMLTomorrowDP, {read: true, write: true, name: "Tibber HTML für Morgen", desc:"HTML-DP", type: "string", role: "", def: "" });
                        createStateAsync(tibberColorDP, {read: true, write: true, name: "Farbdefinition für Balken", desc:"JSON-DP", type: "string", role: "", 
                        def: JSON.stringify([{ 'gt': 0,'lte': 0.15, 'color': 'lightgreen' },
                                            {'gt': 0.15,'lte': 0.22,'color': 'green'},
                                            {'gt': 0.22,'lte': 0.29,'color': 'yellow'},
                                            {'gt': 0.29,'lte': 0.35,'color': 'orange'},
                                            {'gt': 0.35,'color': 'red'}]) });
                        createStateAsync(tibberGraphTypeDP, {read: true, write: true, name: "Tibber Graph Typ Auswahl", desc:"GraphType-DP", type: "string", role: "", states: {"bar":"bar","line":"line"} ,def: "bar" });
                        createStateAsync(tibberInstDP, {read: true, write: true, name: "Tibber Instanz", desc:"Instanz-DP", type: "string", role: "", def: "0" });
                        createStateAsync(tibberShowTaxEnergyDP, {read: true, write: true, name: "Tax und Energy anzeigen bei Hover", desc:"Show-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberShowMinMaxAvgDP, {read: true, write: true, name: "Min, Max und Mittelwert anzeigen", desc:"Show-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberShowMinMaxAvgTextDP, {read: true, write: true, name: "Min, Max und Mittelwert Texte anzeigen", desc:"ShowText-DP", type: "boolean", role: "", def: false });
                        createStateAsync(visDP, {read: true, write: true, name: "Welche VIS soll genutzt werden?", desc:"VIS-DP", type: "string", role: "",states: {"jarvis":"jarvis","VIS":"VIS"} , def: "jarvis" });
                        createStateAsync(darkModeDP, {read: true, write: true, name: "DarkMode an?", desc:"DarkMode-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberAreaDP, {read: true, write: true, name: "Fläche unter Kurve?", desc:"CurveArea-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberShowLabelTodayDP, {read: true, write: true, name: "Label Today anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberLabelTodayDP, {read: true, write: true, name: "Label Today für das Chart", desc:"Label-DP", type: "string", role: "", def: "Today-Tageswerte" });
                        createStateAsync(tibberShowLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberLabelTomorrowDP, {read: true, write: true, name: "Label Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Tomorrow-Tageswerte" });
                        createStateAsync(tibberShowWaitLabelTomorrowDP, {read: true, write: true, name: "Label Wait Tomorrow anzeigen?", desc:"showLabel-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberWaitTomorrowTextDP, {read: true, write: true, name: "Label Wait Tomorrow für das Chart", desc:"Label-DP", type: "string", role: "", def: "Werte erst ab 14.00 Uhr verfügbar" });
                        createStateAsync(tibberHighlightCurrentHourDP, {read: true, write: true, name: "Aktuelle Stunde markieren?", desc:"HighlightAktHour-DP", type: "boolean", role: "", def: false });
                        createStateAsync(tibberHighlightColorDarkDP, {read: true, write: true, name: "HighLight Color DarkMode", desc:"HighLight Dark-DP", type: "string", role: "", def: "white" });
                        createStateAsync(tibberHighlightColorLightDP, {read: true, write: true, name: "HighLight Color LightMode", desc:"HighLight Light-DP", type: "string", role: "", def: "grey" });
                        createStateAsync(tibberSteppedLineDP, {read: true, write: true, name: "Gestufte Linie?", desc:"SteppedLine-DP", type: "boolean", role: "", def: false });
                        
                        createStateAsync(tibberShowGraphIfEmptyDP, {read: true, write: true, name: "Graph anzeigen ohne Daten?", desc:"showGraph-DP", type: "boolean", role: "", def: false });
                        
                        // getHistoryAdapter();
                        
                        // setDPs('0'); // -> dpArray 
                        
                        setTimeout(function(){
                            getTibberData(dpArray);
                            let inst = getState(tibberInstDP).val;
                            $('tibberlink.'+inst+'.Homes.*.PricesTomorrow.json').on(function(obj) {
                                setTimeout(function(){
                                    getTibberData(dpArray);
                                },3000)
                            });
                        
                            $('tibberlink.'+inst+'.Homes.*.PricesToday.json').on(function(obj) {
                                setTimeout(function(){
                                    getTibberData(dpArray);
                                },3000);
                            });
                        
                        },3000);
                        
                        let scheduleId ;
                        if(getState(tibberHighlightColorDarkDP).val){
                            scheduleId = schedule('00 * * * *', () => {
                                        
                                getTibberData(dpArray);
                            })
                        }
                        
                        on({id: tibberHighlightCurrentHourDP, change: "any"}, function (obj) {
                            let value = obj.state.val;
                            if(value){
                                getTibberData(dpArray);
                                clearSchedule(scheduleId);
                                scheduleId = schedule('00 * * * *', () => {
                                    getTibberData(dpArray);
                                })
                            }else{
                                clearSchedule(scheduleId);
                                getTibberData(dpArray);
                            }
                        })
                        on({id: tibberShowTaxEnergyDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberColorDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        on({id: tibberShowMinMaxAvgDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberShowMinMaxAvgTextDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        on({id: tibberGraphTypeDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: darkModeDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberAreaDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberShowLabelTodayDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberShowLabelTomorrowDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        on({id: tibberShowWaitLabelTomorrowDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        on({id: tibberHighlightColorDarkDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        on({id: tibberHighlightColorLightDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberSteppedLineDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        on({id: tibberShowGraphIfEmptyDP, change: "any"}, function (obj) {
                            getTibberData(dpArray);
                        });
                        
                        
                        function getTibberData(arr){
                            // arr wird nur für eCharts benötigt
                            
                            // tibberDataDP selbst ermitteln
                            let tibberInst = getState(tibberInstDP).val;
                            let priceArr = ['PricesToday','PricesTomorrow'];
                            for(let x=0;x< priceArr.length;x++){
                                let tibberData = [];
                                let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.'+priceArr[x]+'.json')
                                if(tibberLink[0] != undefined){
                                    let tblLevel = levelObject(tibberLink[0]);
                                    let dpLeveltbl = getDPLevel(tblLevel,4);
                                    let tibberJSON = JSON.parse(getState(dpLeveltbl+'.json').val);
                                    // tibberJSON
                                    for(let i=0;i<tibberJSON.length;i++){
                                        let obj = {};
                                        obj.hour     = parseInt(tibberJSON[i].startsAt.substring(11,13));
                                        obj.start   = tibberJSON[i].startsAt
                                        obj.startTS = new Date(obj.start).getTime();
                                        obj.value   = tibberJSON[i].total;
                                        obj.energy   = tibberJSON[i].energy;
                                        obj.tax   = tibberJSON[i].tax;
                                        obj.min = false;
                                        obj.max = false;
                                        obj.average = false;
                                        obj.level = tibberJSON[i].level;
                                        tibberData.push(obj);
                                    }
                                    // average, minium, maximum direkt holen
                                    
                                    let eleArr = ['average','minimum','maximum'];
                                    for(let i=0;i<eleArr.length;i++){
                                        let obj = {};
                                        switch (eleArr[i]) {
                                                case 'average':
                                                    obj.hour     = 'non'
                                                    obj.start   = ''
                                                    obj.startTS = 0;
                                                    obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                    obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                    obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                    obj.min = false;
                                                    obj.max = false;
                                                    obj.average = true;
                                                    obj.level = '';
                                                    tibberData.push(obj);
                                                    break;
                                                case 'minimum':
                                                    obj.hour    = 'non';
                                                    obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                                    obj.startTS = new Date(obj.start).getTime();
                                                    obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                    obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                    obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                    obj.min = true;
                                                    obj.max = false;
                                                    obj.average = false;
                                                    tibberData.push(obj);
                                                    break;
                                                case 'maximum':
                                                    obj.hour    = 'non';
                                                    obj.start   = getState(dpLeveltbl+'.'+eleArr[i]+'.startsAt').val
                                                    obj.startTS = new Date(obj.start).getTime();
                                                    obj.value   = getState(dpLeveltbl+'.'+eleArr[i]+'.total').val
                                                    obj.energy   = getState(dpLeveltbl+'.'+eleArr[i]+'.energy').val
                                                    obj.tax   = getState(dpLeveltbl+'.'+eleArr[i]+'.tax').val
                                                    obj.min = false;
                                                    obj.max = true;
                                                    obj.average = false;
                                                    tibberData.push(obj);
                                                    break;
                                                default: 
                                                    break;
                                            }
                                    }
                                    // log(tibberData);
                                    let setechart = false;
                                    if(setechart){
                                        for(let i=0;i<dpArray.length;i++){
                                            setHistoryData(dpArray[i],tibberObj[levelObject(dpArray[i])[3]]);
                                        }
                                        seteChartsDP(dpArray);
                                    }
                                    // log('setHTML');
                                    setHTML(tibberData,priceArr[x]);
                                    if(getState(visDP).val=='VIS'){
                                        createHtmlFile(priceArr[x])
                                    }
                                }
                                
                            }
                            
                        }
                        // createHtmlFile();
                        async function createHtmlFile(name) {
                            let dp = '';
                            let file = '';
                            if(name == 'PricesToday'){
                                dp = '0_userdata.0.Strom.tibberHistory.htmlToday';
                                file = 'today';
                            }else{
                                dp = '0_userdata.0.Strom.tibberHistory.htmlTomorrow';
                                file = 'tomorrow';
                            }
                            const htmlContent = getState(dp).val;
                            writeFile('vis.0', '/tibber/'+file+'.html',htmlContent, (err) => {
                                if (err) {
                                console.error('Fehler beim Speichern der HTML-Datei, tibber-Verzeichnis angelegt?', err);
                                } else {
                                console.log('HTML-Datei '+file+'.html erfolgreich gespeichert');
                                }
                            });
                        }
                        
                        
                        
                        function setHTML(origData,priceDP){
                            let data = [];
                            let dataMin = '';
                            let dataMinTime = '';
                            let dataMax = '';
                            let dataMaxTime = '';
                            let dataAvg = '';
                            let dataNull = false;
                            // log(priceDP);
                            let tibberInst = getState(tibberInstDP).val;
                            let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                            let tblLevel = levelObject(tibberLink[0]);
                            let dpLeveltbl = getDPLevel(tblLevel,3);
                            
                            let minToday = getState(dpLeveltbl + '.PricesToday.minimum.total').val;
                            //minToday = minToday-(Math.trunc(minToday*0.1))
                            // log(minToday)
                            let maxToday = getState(dpLeveltbl + '.PricesToday.maximum.total').val
                            let minTomorrow = getState(dpLeveltbl + '.PricesTomorrow.minimum.total').val
                            //minTomorrow = minTomorrow-(Math.trunc(minTomorrow*0.1))
                            let maxTomorrow = getState(dpLeveltbl + '.PricesTomorrow.maximum.total').val
                            let jsonTomorrow = JSON.parse(getState(dpLeveltbl + '.PricesTomorrow.json').val);
                            
                            let graphMin = 0;
                            if(minToday >= minTomorrow){
                                if(minTomorrow != 0){
                                    graphMin = minTomorrow;
                                }else{
                                    graphMin = minToday;
                                }
                            }else{
                                graphMin = minToday;
                            }
                            let graphMax = 0;
                            if(maxToday >= maxTomorrow){
                                graphMax = maxToday;
                            }else{
                                graphMax = maxTomorrow;
                            }
                            // graphMax = Math.round((graphMax + parseFloat((graphMax / 20).toFixed(2))) * 100) / 100;
                            // graphMax = Math.max(Math.ceil(graphMax * 100) / 100, 0.35);
                            if(jsonTomorrow.length ==0 ){
                                graphMin = minToday;
                                graphMax = maxToday
                            }
                            graphMin = Math.ceil(graphMin * 50) / 50 - 0.02;
                            graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                            //log(graphMin)
                        
                            for(let i=0;i<origData.length;i++){
                                if(origData[i].min){
                                    dataMin = origData[i].value;
                                    //log(dataMin);
                                    dataMinTime =origData[i].startTS;
                                    //log(dataMinTime)
                                }
                                if(origData[i].max){
                                    dataMax = origData[i].value;
                                    dataMaxTime =origData[i].startTS;
                                }
                                if(origData[i].average){
                                    dataAvg = origData[i].value;
                                }
                            }
                            if(origData.length>3){
                                for(let i=0;i<origData.length;i++){
                                    if(!origData[i].average && !origData[i].max && !origData[i].min ){
                                        if( origData[i].value < dataAvg){ 
                                            if(origData[i].level == 'NORMAL' ){
                                                data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level})//, color: 'rgba(0,255,0,0.2)', border: levelColor(origData[i].level)
                                            }else{
                                                data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy,level: origData[i].level}) //,  color: levelColor(origData[i].level), border: 'lime'
                                            }
                                        }else{
                                            data.push({time:origData[i].startTS,value: origData[i].value,tax: origData[i].tax,energy: origData[i].energy, level: origData[i].level}) //,color: levelColor(origData[i].level), border: 'red'
                                        }
                                    }else{
                                        if(origData[i].min){
                                            dataMin = origData[i].value;
                                            dataMinTime =origData[i].startTS;
                                        }
                                        if(origData[i].max){
                                            //log(origData[i]);
                                            dataMax = origData[i].value;
                                            dataMaxTime =origData[i].startTS;
                                            //log(dataMaxTime);
                                        }
                                        if(origData[i].average){
                                            dataAvg = origData[i].value;
                                        }
                                    }
                                    
                                }
                                // log('oben '+graphMin)
                            }else{
                                dataNull = true;
                                //dataMin = String(graphMin);
                                //dataMax = String(graphMax);
                                //dataMax = "0";
                                //dataAvg = '0.01';
                                //graphMin = minToday;
                                //graphMax = maxToday;
                                //graphMin = Math.ceil(graphMin * 50) / 50 - 0.01;
                                //graphMax = Math.ceil(graphMax * 50) / 50 + 0.01;
                            }
                            // Werte holen
                            let showTaxEnergy = getState(tibberShowTaxEnergyDP).val;
                            let minMaxAvg = getState(tibberShowMinMaxAvgDP).val;
                            let colorJSON = getState(tibberColorDP).val;
                        
                            let html = '';
                            html += '<!DOCTYPE html>';
                            html += '<html lang="en">';
                            html += '<head>';
                            html += '<meta charset="UTF-8">';
                            html += '<meta name="viewport" content="width=device-width, initial-scale=1.0">';
                            html += '<title>Tibber-Tageswert</title>';
                            html += '<script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>';
                            html += '<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>';
                            html += '</head>';
                            html += '<body>'
                            if(getState(visDP).val == 'VIS'){
                                html += '<div id="chart-container" style="width: 600px; height:400px;"></div>';
                            }else{
                                html += '<div id="chart-container" style="width: 100%; height:400px;"></div>';
                            }
                            //log(data);
                            html += '<script>'
                            html += '    var data = '+JSON.stringify(data)+';';
                            html += '    var chartContainer = document.getElementById("chart-container");'
                            html += '    var myChart = echarts.init(chartContainer);';
                        
                           
                            html += '    function formatTime(time) {';
                            html += '        return moment(time).format("HH");'
                            html += '    }';
                            html += '    function calculateArrowPosition(hour){'
                            //html += '       console.log((hour) * (100 / 24) + "%");'
                            html += '       return (hour / 24) * 100 +1 + "%";'
                            html += '    }'
                            html += '    function updateChart() {';
                            html += '        var minValue = Math.min.apply(null, data.map(function (item) {';
                            html += '          return item.value;';
                            html += '        }));';
                            //html += '        console.log(minValue);'
                            // html += '        var yAxisMin = minValue - (minValue/10);'
                            html += '        var yAxisMin = '+graphMin+';';
                            html += '        var maxValue = '+dataMax+';'
                            //html += '        var maxValue = '+graphMax+';'
                            //html += '        console.log(maxValue);'
                            // html += '        var yAxisMax = maxValue + (maxValue/10);'
                            html += '        let avgValue = '+dataAvg+';'
                            html += '        var visualMapPieces =' + colorJSON +';';
                            html += '        var values = data.map(item => (item.value-minValue).toFixed(2));'
                            html += '        var maxLineValue = Math.max.apply(null, values);'
                            html += '        var maxLineIndex = values.indexOf(maxLineValue);'
                            html += '        var maxLineData = {time:'+dataMaxTime+',value:'+dataMax+'};'
                            html += '        var currentHour = new Date().getHours() ;'
                            // html += '        console.log(currentHour);'
                            //html += '        console.log(maxLineData.time);'
                            // html += '        var maxV = parseFloat((Math.max(...values)));'
                            //html += '        console.log(maxV);'
                            //html += '        let pro = values.map((value) => (value/maxV).toFixed(2));'
                            //html += '        console.log(values);'
                            //html += '        console.log(pro);'
                            html += '        var colorStops = [];'
                            //html += '        console.log(yAxisMin +" "+maxValue);'
                            if(!dataNull){
                            html += '        visualMapPieces.map(piece => {'
                            html += '          if(piece["lte"] >=yAxisMin && piece["gt"]<=maxValue){ '
                            //html += '            console.log(piece["lte"] + " "+maxValue + " "+ yAxisMin);'
                            html += '            if(piece["gt"]>=yAxisMin){'
                            //html += '             console.log(piece["gt"] +" gt gesetzt " +yAxisMin);'
                            html += '             colorStops.push({'
                            html += '              offset:  ((piece["gt"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                            html += '              color: piece.color'
                            html += '             });'
                            html += '            }'
                            html += '            if(piece["lte"]<=maxValue){'
                            //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                            html += '             colorStops.push({'
                            html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                            html += '              color: piece.color'
                            html += '             });'
                            html += '            }'
                            html += '            if(piece["lte"]>maxValue ){'
                            //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                            html += '            colorStops.push({'
                            html += '              offset:  1,'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                            html += '              color: piece.color'
                            html += '             });'
                            //html += '            }'
                            html += '           };'
                            html += '          }else{'
                            //html += '            console.log(piece["lte"] + " " + piece["gt"]);'
                            html += '           if(piece["lte"]>=maxValue && piece["gt"]<=maxValue ){'
                            //html += '            console.log(piece["lte"] +" lte gesetzt "+yAxisMin);'
                            html += '            colorStops.push({'
                            html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                            html += '              color: piece.color'
                            html += '            });'
                        
                            html += '           }else if(piece["lte"]>=maxValue && piece["gt"] <= maxValue){'
                            // html += '            console.log("Drin");'
                            html += '            colorStops.push({'
                            html += '              offset:  ((piece["lte"]-yAxisMin)/(maxValue-yAxisMin)),'//  /((maxValue-minValue)/maxValue)  /(visualMapPieces[visualMapPieces.length - 1]["gt"])
                            html += '              color: piece.color'
                            html += '            });'
                            html += '           }'
                            html += '          }; ' 
                            html += '        });'
                            //html += '        console.log(colorStops);'
                            //html += '        console.log(colorStops[colorStops.length-1].color);'
                            html += '        colorStops.push({'
                            html += '            offset: 1,' //visualMapPieces[visualMapPieces.length - 1]["gt"]
                            html += '            color: colorStops[colorStops.length-1].color'// visualMapPieces[visualMapPieces.length - 1].color'
                            html += '        });'
                            //html += '        console.log(colorStops);'
                            html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                            //html += '        colorStops.splice(0, 0, {offset: 0,color:colorStops[0].color});'
                            //html += '        colorStops.splice(2, 0, {offset: colorStops[1].offset,color:colorStops[2].color});'
                            //html += '        colorStops.splice(4, 0, {offset: colorStops[3].offset,color:colorStops[4].color});'
                            //html += '        console.log(colorStops);'
                            }
                            if(dataNull && !getState(tibberShowGraphIfEmptyDP).val){
                                html += '        myChart.setOption({';
                            html += '            title: {';
                            if(priceDP== 'PricesToday'){
                                html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                                if(getState(tibberShowLabelTodayDP).val){
                                    html += '            show: true'
                                }else{
                                    html += '            show: false'
                                }
                            }else{
                                if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                                      html += '          textAlign: "auto", '
                                      html += '          textStyle: { '
                                      html += '             color: "red"'
                                      html += '          },'
                                      html += '          left: "50px",'
                                      html += '          text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                                }else{
                                    html += '            text: "'+getState(tibberLabelTomorrowDP).val+'",';
                                    if(getState(tibberShowLabelTomorrowDP).val){
                                        html += '        show: true,'
                                    }else{
                                        html += '        show: false,'        
                                    }
                                }
                                
                                
                            }
                            
                            html += '                 },});';
                            }else{
                        
                            html += '        myChart.setOption({';
                            html += '            title: {';
                            if(priceDP== 'PricesToday'){
                                html += '                text: "'+getState(tibberLabelTodayDP).val+'",';
                                if(getState(tibberShowLabelTodayDP).val){
                                    html += '                show: true'
                                }else{
                                    html += '                show: false'
                                }
                            }else{
                                if(dataNull && getState(tibberShowWaitLabelTomorrowDP).val){
                                      html += '            textAlign: "auto", '
                                      html += '            textStyle: { '
                                      html += '               color: "red"'
                                      html += '            },'
                                      html += '            left: "50px",'
                                      html += '            text: "'+getState(tibberWaitTomorrowTextDP).val +'",';
                                }else{
                                    html += '                text: "'+getState(tibberLabelTomorrowDP).val+'",';
                                    if(getState(tibberShowLabelTomorrowDP).val){
                                        html += '                show: true,'
                                    }else{
                                        html += '                show: false,'        
                                    }
                                }
                                
                                
                            }
                            
                            html += '            },';
                            html += '            visualMap: {';
                            html += '              type: "piecewise",'
                            html += '              pieces: visualMapPieces,'
                            html += '              dimension: 1,' // Mapping to the 'value' dimension'
                            html += '              showLabel: true,'
                            html += '              precision: 2,'
                            html += '              itemWidth: 6,'
                            html += '              orient: "horizontal",'
                            html += '              left: "center", calculable: true,selectedMode: "multiple",'
                            html += '              bottom: 10,'
                            html += '              text: ["High", "Low"],'
                            html += '              textStyle: {'
                            if(getState(darkModeDP).val){
                                html += '                color: "white"'
                            }else{
                                html += '                color: "black"'
                            }
                            html += '              },'
                            //html += '              inRange: {'
                            //html += '                color: colorStops.map(stop => stop.color)';//visualMapPieces.map(piece => piece.color)'
                            //html += '              },'
                            /* bringt nichts
                            html += '              itemStyle:{'
                            html += '                 symbol:"pin",'
                            html += '                 symbolSize: 30,'
                            html += '                 markPoint: {'
                            html += '                   data: [{'
                            html += '                    symbol: "circle",'
                            html += '                       coord: [data.time, data.value], itemStyle:{ color:"red"}'
                            html += '                    }]'
                            html += '                 },'
                            html += '               }'
                            */
                            html += '            },'
                            
                            if(minMaxAvg){
                                html += '            grid: {';
                                if(getState(tibberShowMinMaxAvgTextDP).val){
                                    html += '              right: 50,'; // Vergrößern Sie diesen Wert nach Bedarf
                                }else{
                                    html += '              right: 10,';
                                }
                                html += '              left: 10,';
                                html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                                html += '            },';
                            }else{
                                html += '            grid: {';
                                html += '              right: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                                html += '              left: 10,'; // Vergrößern Sie diesen Wert nach Bedarf
                                html += '              containLabel: true'; // Stellen Sie sicher, dass das Label innerhalb des Diagramms bleibt
                                html += '            },';
                            }
                            html += '            areaStyle: {'
                            html += '              color: colorStops';//"red"'; visualMapPieces.map(piece => piece.color)'
                            //html += '              color: "blue", '
                            html += '            },'
                            // Option für Pfeil unter Kurve
                            /*
                            if(!dataNull && getState(tibberHighlightCurrentHourDP).val){
                            html += 'graphic: [{'
                            html += '    type: "image",'
                            html += '    id: "arrow",'
                            html += '    bounding: "all",'
                            html += '    z:100,'
                            //html += '    origin: [calculateArrowPosition(currentHour), "10%"],'
                            //html += '    origin: [0.5, 0],'  // Koordinaten für den Pfeil
                            html += '    bottom: "10%", '
                            html += '    left: calculateArrowPosition(currentHour),';//"50px",'
                            html += '    '
                            html += '    style: {'
                            html += '        image: "https://api.iconify.design/mdi/arrow-up-bold.svg?width=24&height=24&color=blue", ' // Pfad zum Bild deines Pfeils
                            html += '        width: 30,'
                            html += '        height: 30,'
                            html += '    }'
                            html += '}],'
                            }
                            */
                            // ToolBox
                            html += '            toolbox: {';
                            html += '              feature: {';
                            html += '                saveAsImage: {';
                            html += '                   backgroundColor: "rgba(38, 37, 37, 1)",';
                            html += '                   title: "Speichern",';
                            let fileName = priceDP.replace('Prices','') 
                            if(fileName == 'Today'){
                                fileName += ' '+ formatDate(new Date(),'DD.MM.YYYY'); 
                            }else{
                                fileName += ' '+ formatDate(new Date().getTime()+86400000,'DD.MM.YYYY'); 
                            }
                            html += '                   name: "TibberHTML '+fileName+'"'
                            html += '                },'
                            html += '                magicType: {';
                            html += '                  type: ["line", "bar"],';
                            html += '                  title:{';
                            html += '                     line: "Line-Chart",';
                            html += '                     bar: "Bar-Chart",';
                            html += '                  }'
                            
                            html += '                },';
                            html += '                dataView: {';
                            html += '                  title: "Daten aus der Serie",';
                            html += '                  lang: ["Daten der Kurve", "Schließen", "Aktualisieren"],'
                            html += '                  optionToContent: function (opt) {';
                            html += "                      var table = '<table style=\"width:100%;\"><tbody><tr style=\"text-align: left;\"><th>Stunde</th><th>Wert</th><th>Energie</th><th>Steuer</th><th>Level</th></tr>';";
                            //html += '                      console.log(opt.series.length); '
                            //html += '                      console.log(opt.series[0].data); '
                            html += '                      for (var i = 0; i< opt.series[0].data.length;i++) {';
                            html += '                          table += "<tr>";';
                            html += '                         for(let x =0; x < opt.series[0].data[i].value.length; x++){'
                            html += '                            if(x==0){';
                            html += '                               table +=  "<td>" + ("0"+new Date(opt.series[0].data[i].value[x]).getHours()).slice(-2) + "</td>";';
                            html += '                            }else{';
                            html += '                               table +=  "<td>" + opt.series[0].data[i].value[x] + "</td>";';
                            html += '                            } '
                            html += '                         }';
                            html += '                           table += "</tr>";';
                            html += '                      }';
                            html += '                      table += "</tbody></table>";'
                            html += '                      return table;';
                            html += '                  },';
                            html += '                  readOnly: true';
                            html += '                },'
                            html += '              }';
                            html += '            },'
                            
                            html += '            xAxis: {';
                            html += '                type: "time",';
                            html += '                axisLabel: {';
                            html += '                    show: true,'
                            html += '                    formatter: function (value) {';
                            html += '                        return formatTime(value);';
                            html += '                    }';
                            html += '                },';
                            html += '                splitNumber: 10,';
                        	html += '            },';
                            html += '            yAxis: {';
                            html += '                type: "value",';
                            html += '                axisLabel: {'; 
                            
                            html += '                  formatter: function (value) {';
                            html += '                     return value.toFixed(3) + " €";';
                            html += '                  }';
                            
                            html += '                },';
                            
                            html += '               min: '+graphMin+','; //
                            html += '               max: '+graphMax+',' //yAxisMax
                            html += '            },';
                            
                            
                        
                        
                        
                            html += '            series: [{';
                            
                            html += '                data: data.map(function (item) {';
                            html += '                    var hour = new Date(item.time).getHours();'
                            html += '                    return {';
                            html += '                       value: [item.time, item.value, item.energy, item.tax, item.level],';
                            //html += '                       lineStyle: {width: hour === currentHour ? 10:null},'
                            
                            // Symbol für Line einstellen
                        
                            html += '                        symbol: "circle",'
                            
                            if(getState(tibberHighlightCurrentHourDP).val && priceDP == 'PricesToday'){
                                html += '                    symbolSize: hour === currentHour ? 10:null, '
                                html += '                    itemStyle: {'
                                   
                                if(getState(darkModeDP).val){
                                    //html += '                           backgroundColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                    html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                    html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorDarkDP).val+'":null,'
                                    html += '                           borderWidth: hour === currentHour ? 2:null,'
                                    html += '                           shadowBlur: hour === currentHour ? 20:null,'
                                }else{
                                    html += '                           borderColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                                    html += '                           shadowColor: hour === currentHour ? "'+getState(tibberHighlightColorLightDP).val+'":null,'
                                    html += '                           borderWidth: hour === currentHour ? 1:null,'
                                    html += '                           shadowBlur: hour === currentHour ? 10:null,'
                                }
                                //html += '                           borderWidth: hour === currentHour ? 1:null,'
                                //html += '                           shadowBlur: hour === currentHour ? 10:null,'
                                
                                html += '                     },'
                                
                            }
                            // Aria für Schraffierung
                            //html += 'aria: {'
                            //html +='    enabled: true,'
                            //html += '   decal: {'
                            //html +='        show: hour === currentHour'
                            //html += '   }'
                            //html +='},'
                            html += '                        emphasis: {';
                            html += '                          itemStyle: {';
                            html += '                            color: "white" '; // Füge die Farbe in die Betonung ein
                            html += '                          },';
                            html += '                          label: {';
                            html += '                            show: true,';
                            html += '                            formatter: function (params) {';
                            html += '                               return params.data.value[1].toFixed(3) + " €";'; //console.log(params);
                            html += '                            },';
                            html += '                            color: "black",';
                            html += '                            fontWeight: "bold", ';
                            html += '                            backgroundColor: "white"';
                            html += '                          }';
                            html += '                        }';
                            html += '                     } ';
                            html += '                }),'; // end data
                            
                            if(getState(tibberSteppedLineDP).val){
                                html += '            step: "end",'
                            }
                            // ItemStyle
                            //html += '                itemStyle:{'
                            //html += '                  color: function (params) {'
                                        // Färbe den Balken der aktuellen Stunde anders ein
                            //html += '                    console.log(new Date(params.value[0]).getHours());'
                            //html += '                    console.log(currentHour);'
                            //html += 'console.log(new Date(params.value[0]).getHours() === currentHour ? "red" : "blue");'
                            //html += '                    return new Date(params.value[0]).getHours() === currentHour ? "red" : "blue";'
                            //html += '                  }'
                            //html += '                },'
                            if(getState(tibberAreaDP).val){
                            html += '                areaStyle:{'
                            html += '                    color: new echarts.graphic.LinearGradient(0, 1, 0, 0, colorStops),' ;
                            
                            //html += '                    color:  colorStops,'
                            // html += '                    max: maxValue, '
                            /*
                            html += '                    color: function (params) {'
                            html += '                       console.log(params);'
                            html += '                       var wert = params.data.value[1];'
                            html += '                       var col = "red";'
                            html += '                       for (var i = 0; i < visualMapPieces.length; i++) {'
                            html += '                           var piece = visualMapPieces[i];'
                            html += '                           if (wert >= piece.gt && wert <= piece.lte) {'
                            html += '                               col = piece.color;'
                            html += '                               break;'
                            html += '                           }'
                            html += '                       }'
                            html += '                       return col;'
                            html += '                   },'
                            */
                            html += '                },'
                            }
                            html += '                type: "'+getState(tibberGraphTypeDP).val+'",';
                            //html += '               markArea: {'
                            //html += '                   silent: true,'
                            //html += '                   data: ['
                            //html += '                       [{'
                            //html += '                           xAxis: "min",'
                            //html += '                           itemStyle: {'
                            //html += '                               color: "rgba(0, 0, 0, 0.7)"'
                            //html += '                           }'
                            //html += '                           }, {'
                            //html += '                               xAxis: "max",'
                            //html += '                       }]'
                            //html += '                   ]'
                            //html += '               },'
                            
                            if(minMaxAvg){
                                html += '                markLine: {';
                                html += '                  symbol: "none",';  // Kein Symbol für die Markierungslinie
                                html += '                  lineStyle: {';
                                html += '                    color: "red",';   // Farbe der Markierungslinie
                                html += '                    type: "dashed"';  // Art der Linie (gestrichelt)
                                html += '                  },';
                                
                                if(getState(tibberShowMinMaxAvgTextDP).val){ //coord: [maxLineData.time, maxLineData.value] ,)
                                    if(!dataNull){
                                    html += '                  data: [';
                                    html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: true, position: "end", formatter: "Min\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                                    html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: true, position: "end", formatter: "Max\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                                    html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: true, position: "end", formatter: "Avg\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                                    html += '                  ], '
                                    }
                                }else{
                                    if(!dataNull){
                                    html += '                  data: [';
                                    // funktioniert nicht !,tooltip: {show: true,formatter: "Min\\n\\n" + params.value.toFixed(3) + " €",textStyle: {fontSize: 12,fontWeight: "bold",color: "white"}}  ,formatter: "Min " + minValue.toFixed(3) + " €"
                                    html += '                   {yAxis: minValue ,name: "MIN", lineStyle: { color: "lime" },label: { show: false, position: "end", formatter: "Min\\n\\n"+ minValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } }  },';
                                    html += '                   {yAxis: maxValue,name: "MAX", lineStyle: { color: "red" },label: { show: false, position: "end", formatter: "Max\\n\\n"+ maxValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } },';
                                    html += '                   {yAxis: avgValue ,name: "AVG", lineStyle: { color: "blue" },label: { show: false, position: "end", formatter: "Avg\\n\\n"+ avgValue.toFixed(3)+" €",textStyle: { fontSize: 12,fontWeight: "bold", color:"white"  } } }';
                                    html += '                  ], '    
                                    }    
                                }
                                html += '                }';
                            }
                            html += '            }],'; // Ende Series
                        
                        
                            
                        
                            html += '            tooltip: {';
                            html += '              trigger: "axis",';
                            html += '              axisPointer: {';
                            html += '               type: "shadow"';
                            html += '              },';
                            html += '              textStyle: {';
                            html += '                fontFamily: "Courier",';
                            html += '                fontWeight: "bold"'; // Hinzugefügt
                            html += '              },'
                            html += '              formatter: function (params) {';
                            html += '                let time = "Start ab: "+ moment(params[0].axisValue).format("HH:mm")+ " Uhr";';
                            html += '                let value = "Preis:&nbsp&nbsp&nbsp&nbsp"+params[0].value[1].toFixed(4) + " €";';
                            if(showTaxEnergy){
                                html += '            let energy = "Energie:&nbsp&nbsp"+params[0].value[2].toFixed(4) + " €";'
                                html += '            let tax    = "Steuer:&nbsp&nbsp&nbsp"+params[0].value[3].toFixed(4) + " €";'
                                html += '            let lev    = "Level:&nbsp&nbsp&nbsp&nbsp"+ params[0].value[4];'
                                html += "            return  `${time}<br/>${value}<br/>${energy}<br/>${tax}<br/>${lev}` ;";
                            }else{
                                //html += "            return `<span style=\"font-family: 'Arial'; font-weight: 'bold';\" >${time}<br/>${value}</span>` ;";
                                html += "            return `${time}<br/>${value}` ;";
                            }
                            
                            html += '              }';
                            html += '            },';
                            
                            html += '        }) ';// end setOption
                            }
                            html += '    }'; 
                            
                        
                            html += '    updateChart(); ';
                            html +='     var updateInterval = setInterval(updateChart, 3600000);'
                            html += '</script>';
                            html += '</body>';
                            html += '</html>';
                        
                            // log(html);
                            if(priceDP == 'PricesToday'){
                                setState(tibberHTMLTodayDP,html);
                            }else{
                                setState(tibberHTMLTomorrowDP,html);
                            }
                        }
                        
                        
                        
                        function sortByName(x, y) {
                            // Wenn x oder y nicht-numerisch sind, setze sie an das Ende
                            if (isNaN(x.hour) || isNaN(y.hour)) {
                                return isNaN(x.hour) ? 1 : -1;
                            }
                            
                            // Vergleiche numerische Werte
                            return x.hour - y.hour;
                        }
                        
                        
                        
                        on({id: dbHistoryDP, change: "any"}, function (obj) {
                            let value = obj.state.val;
                            // history für die DPs aktiv?
                            if (value!=''){
                                if (getState('system.adapter.'+value+'.alive').val){
                                    if (isHistoryActiveAllDPs(dpArray)){
                                        if(logging){
                                            log('History-Future-DPs sind angelegt und History aktiviert!');
                                        }
                                        // getPVData(dpArray);
                                        //runScript();
                                    }else{
                                        if(logging){
                                            log('History wird angelegt für die future-DPs!');
                                        }
                                        activateDPsHistory(dpArray);
                                        setTimeout(function(){
                                            deleteAllHistoryDPs(dpArray);
                                            // log('gelöscht');
                                            // getPVData(dpArray);
                                        },3000)
                                        //runScript();
                                    }
                                }else{
                                    log('Der History-Adapter ist nicht gestartet! -> Es werden keine DPs mit History aktiviert','warn');
                                }
                            }
                        });
                        
                        
                        function setDPs(tibberInst){
                            // Ist der Adapter aktiv
                            // 
                            //let pvAliveDP = 'system.adapter.pvForecast.'+tibberInst+'.alive';
                            //if(existsState(pvAliveDP)){
                            //    if(getState(pvAliveDP).val){
                                    // Adapter ist gestartet
                                    let tibberKeys = ['Value','Tax','Energy']
                                    for(let i=0;i<tibberKeys.length;i++){
                                            dpArray.push(tibberDP+'.future'+tibberKeys[i]);
                                    }
                                    
                            //    }else{
                            //        log('Der Adapter tibberlink.'+tibberInst+' ist nicht gestartet!');
                            //    }
                            //}else{
                            //    log('Der Adapter pvForecast ist nicht installiert')
                            //}
                            // Alte erst löschen
                            // Nur löschen, wenn sich die DPs geändert haben
                            let delItems = false;
                            if(dpArray.length >0){
                                // delDPs(dpArray);
                                
                                for(let i=0;i<dpArray.length;i++){
                                    if(existsState(dpArray[i])){
                        
                                    }else{
                                        delItems = true;
                                        delDPs(dpArray);
                                        break;
                                    }
                                }
                            }
                            if(delItems){
                                setTimeout(function() {
                                    if(dpArray.length >0){
                                        createDPs(dpArray);
                                    }
                                },3000);
                            }else{
                                createDPs(dpArray);
                            }
                        }
                        
                        
                        function delDPs(arr){
                            for(let i=0; i<arr.length;i++){
                                if(existsState(arr[i])){
                                    deleteStateAsync(arr[i]);
                                }
                            }
                        }
                        // createStateAsync(futureTempDP, {read: true, write: false, name: "daswetter temperature", type: "number", role: "", def: 0 });
                        
                        function createDPs(arr){
                            for(let i=0; i<arr.length;i++){
                                // 0_userdata.0.pvForecastHistory.historyDB
                                let name =  levelObject(arr[i])[3];
                                createStateAsync(arr[i], {read: true, write: false, name: "tibber"+name, type: "number", role: "", def: 0 });
                            }
                        }
                        
                        
                        function seteChartsDP(dpArray){
                            let startDT = getDateObject('00:00').getTime(); // heute 00:00
                            // pvForecast hat nur 2 Tage im Array
                            let endDT = startDT + 24*1*60*60*1000;
                            // start_time, end_time, start, end, timeType
                            for(let i=0;i<dpArray.length;i++){
                                let echartDP = 'echarts.0.tibber'+levelObject(dpArray[i])[3];
                                let obj; 
                                if (existsObject(echartDP)){
                                    obj = getObject(echartDP);
                                    //log(obj);
                                    if (obj.native.data.timeType == 'static'){
                                        obj.native.data.start = formatDate(startDT,'YYYY-MM-DD');
                                        obj.native.data.end   = formatDate(endDT,'YYYY-MM-DD');
                                        obj.native.data.start_time = '00:00';
                                        obj.native.data.end_time = '00:00';
                                        setObject(echartDP,obj);
                                    }
                                }
                            }
                        }
                        
                        
                        
                        function isHistoryActiveAllDPs(dpArray){
                            // dparray automatisch gesetzt
                            let active = false;
                            let dbHistory = getState(dbHistoryDP).val;
                            if (dbHistory != ''){
                                for(let i= 0;i<dpArray.length;i++){
                                    let dpPara = levelObject(dpArray[i])[3];
                                    // log('dpPara: '+dpPara);
                                    // log(pvForecastDP+'.future'+dpPara);
                                    // setActiveHistory(pvForecastDP+'.future'+dpPara);
                                    active = isHistoryActive(tibberDP+'.'+dpPara,dbHistory);
                                    if(active == false){
                                        return false;
                                    }
                                }
                                
                                log('Tibber-DPs History aktiv');
                                return true;
                            }else{
                                log('DB Auswahl fehlt');
                                return false;
                            }
                        }
                        
                        function isHistoryActive(dp,db){
                            let obj = getObject(dp);
                            if (obj.common.custom != undefined){
                                //log(obj.common.custom);
                                let custom = obj.common.custom;
                                
                                for (let key in custom){
                                    //log(key);
                                    if (key.indexOf(db)>=0){  //'history'
                                        return true;
                                    }
                                }
                            }
                            return false;
                        }
                        
                        function activateDPsHistory(dpArray){
                            let historyDB = getState(dbHistoryDP).val;
                            //log('HistoryDB: '+historyDB);
                            if (historyDB != ''){
                                if (getState('system.adapter.'+historyDB+'.alive').val){
                        
                                    if (historyDB!=''){
                                        for(let i= 0;i<dpArray.length;i++){
                                            //log('DParray[i]: '+dpArray[i]);
                                            let dpPara = levelObject(dpArray[i])[3];
                                            //log('dpPara: '+dpPara);
                                            //log(pvForecastDP+'.'+dpPara);
                                            setActiveHistory(tibberDP+'.'+dpPara);
                                            setTimeout(function(){
                                                deleteAllHistoryData(tibberDP+'.'+dpPara);
                                            },2000)
                                        }
                                        log('Future-DPs History aktiviert');
                                    }else{
                                        log('Es wurde keine DB für Future-History ausgewählt!','warn');
                                    }
                                }else{
                                    log('Der Adapter ist nicht gestartet! -> keine Aktivierung möglich','warn');
                                }
                            }else{
                                log('Aktivierung der DPs für die DB erst möglich, wenn man eine DB ausgewählt hat!','warn');
                            }
                        }
                        
                        
                        // deleteAllHistoryDPs();
                        
                        function deleteAllHistoryDPs(dpArray){
                            let dbHistory = getState(dbHistoryDP).val;
                            if (getState('system.adapter.'+dbHistory+'.alive').val){
                                log('History DPs dpArray löschen!');
                                for(let i= 0;i<dpArray.length;i++){
                                    //log('DParray[i]: '+dpArray[i]);
                                    let dpPara = levelObject(dpArray[i])[3];
                                    //log('dpPara: '+dpPara);
                                    //log(pvForecastDP+'.'+dpPara);
                                    deleteAllHistoryData(tibberDP+'.'+dpPara);
                                    
                                }
                                log('Future-DPs History gelöscht');
                            }else{
                                log('Adapter nicht gestartet!');
                            }
                        }
                        
                        
                        function deleteAllHistoryData(dp){
                            let dbHistory = getState(dbHistoryDP).val;
                            if (dbHistory!=''){
                                //let dtStart= getDateObject('00:00').getTime(); // heute 00:00 Uhr
                                //let dtStop = dtStart + 24*6*60*60*1000;
                                sendTo(dbHistory, 'deleteAll', [       // 'history.0' 'deleteRange'
                                    {id: dp}//, start: dtStart, end: dtStop
                                    
                                ], result => {//console.log('deleted')
                                });
                            }else{
                                log('Löschen nicht durchgeführt, da keine HistoryDB festgelegt');
                            }
                        }
                        
                        
                        
                        function getHistoryAdapter(){
                            // history, influxdb, sql
                            log('Einlesen der vorhandenen History-DBs.');
                            let histArr = ['history','influxdb','sql'];
                            let arr =[];
                            for (let i=0; i<histArr.length;i++){
                                let dp = $('system.adapter.'+histArr[i]+'.*.alive');
                                //log(dp);
                                for(let x=0;x<dp.length;x++){
                                    //log(dp[x]);
                                    let dpID = dp[x];
                                   
                                    if (getObject(dpID).common != undefined){
                                        //log(getState(dpID).val);
                                        if (getState(dpID).val != null && getState(dpID).val){
                                            dp[x] = dp[x].substring(15,dp[x].length-6);
                                            // log(dp[x]);
                                            arr.push(dp[x]);
                                        }
                                        if (getState(dpID).val == null){
                                            log('History-Adapter ist fehlerhaft: '+dp[x] +' -> alive auf false setzen');
                                        }
                                    }
                                }
                        
                            }
                            let devStates = {'':'keine Auswahl'};
                            for (let i=0; i< arr.length;i++){
                                devStates[arr[i]] = arr[i];
                            }
                            //log(devStates);
                            if (existsState(dbHistoryDP)){
                                let obj = getObject(dbHistoryDP);
                                obj.common.states = devStates;
                                setObject(dbHistoryDP,obj);
                            }else{
                                createStateAsync(dbHistoryDP, {read: true, write: true, name: "DB-Auswahl", type: "string", role: "", def: '',states:devStates });    
                            }
                        }
                        
                        
                        
                        
                        function setActiveHistory(dp){
                            let dbHistory = getState(dbHistoryDP).val;
                            //log('dbHistory setActive: '+dbHistory);
                            if (dbHistory !=''){
                                sendTo(dbHistory, 'enableHistory', { // 'history.0'
                                    id: dp,  // 'system.adapter.history.0.memRss'
                                    options: {
                                        changesOnly:  true,
                                        debounce:     0,
                                        retention:    31536000,
                                        maxLength:    3,
                                        changesMinDelta: 0,
                                        //ignoreZero: true,
                                        aliasId: '',
                                        enabled: true,
                                        debounceTime: 0,
                                        blockTime: 0,
                                        changesRelogInterval: "0",
                                        ignoreBelowNumber: "",
                                        disableSkippedValueLogging: false,
                                        customRetentionDuration: 365,
                                        enableDebugLogs: false
                                
                                    }
                                }, function (result) {
                                    if (result.error) {
                                        console.log(result.error);
                                    }
                                    if (result.success) {
                                        //successfull enabled
                                        //log(dp +' wurde in history aktiviert');
                                    }
                                });
                            }
                        }
                        
                        // setHistoryData(futureHumidityDP,dpValueArr);
                        
                        function setHistoryData(dp,states){
                            let dbHistory = getState(dbHistoryDP).val;
                            if (dbHistory!=''){
                                sendTo(dbHistory, 'storeState', { // 'history.0'
                                    id: dp,
                                    state: states
                                    }, result => {
                                        // console.log('added')
                                    });
                            }
                        }
                        
                        
                        
                        function levelObject(id){
                            // 0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff
                            let idArr=id.split('.');
                            return idArr; //log(idArr[10]);
                        }
                        
                        // log(getDPLevel(levelObject('0_userdata.0.jarvis.system.tabWidgetStateEffects.0.Desktop.0.Bad.0b5dd758-8d7d-4259-8945-821b1c942960.states.0.displayOff'),9));
                        function getDPLevel(idArr,level){
                            let id ='';
                            for (let i=0;i<=level;i++){
                                id += idArr[i] +'.'
                            }
                            id = id.substr(0,id.length-1); // letzten Punkt wegnehmen
                            return id;
                        }
                        
                        M Online
                        M Online
                        MCU
                        wrote on last edited by MCU
                        #404

                        @meikie Es werden sofort die HTML ermittelt.

                        Setz mal ein LOG hier hin
                        ce7ae63f-4fca-4b51-9afb-7af3da45e7f7-image.png

                        if(logging){
                           log(tibberLink);
                        }
                        

                        NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                        Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                        M 1 Reply Last reply
                        0
                        • M MCU

                          @meikie Es werden sofort die HTML ermittelt.

                          Setz mal ein LOG hier hin
                          ce7ae63f-4fca-4b51-9afb-7af3da45e7f7-image.png

                          if(logging){
                             log(tibberLink);
                          }
                          
                          M Offline
                          M Offline
                          Meikie
                          wrote on last edited by
                          #405

                          @mcu

                             // log(priceDP);
                              let tibberInst = getState(tibberInstDP).val;
                              let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                              if(logging){
                             log(tibberLink);
                          }
                              let tblLevel = levelObject(tibberLink[0]);
                              let dpLeveltbl = getDPLevel(tblLevel,3);
                          

                          Ich finde leider keine Log. Oder wo müsste dieser zu finden sein?

                          M 1 Reply Last reply
                          0
                          • M Meikie

                            @mcu

                               // log(priceDP);
                                let tibberInst = getState(tibberInstDP).val;
                                let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                                if(logging){
                               log(tibberLink);
                            }
                                let tblLevel = levelObject(tibberLink[0]);
                                let dpLeveltbl = getDPLevel(tblLevel,3);
                            

                            Ich finde leider keine Log. Oder wo müsste dieser zu finden sein?

                            M Online
                            M Online
                            MCU
                            wrote on last edited by MCU
                            #406

                            @meikie Log wird im ioBroker-log angezeigt und unter dem script
                            sonst setz noch ein anders log davor

                            let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                            if(logging){
                               log('TEST');
                               log(tibberLink);
                            }
                            

                            NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                            Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                            M 1 Reply Last reply
                            0
                            • M MCU

                              @meikie Log wird im ioBroker-log angezeigt und unter dem script
                              sonst setz noch ein anders log davor

                              let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
                              if(logging){
                                 log('TEST');
                                 log(tibberLink);
                              }
                              
                              M Offline
                              M Offline
                              Meikie
                              wrote on last edited by Meikie
                              #407

                              @mcu

                              00:45:54.312	info	javascript.0 (933464) Stop script script.js.Strom.tibberHTML
                              00:45:54.496	info	javascript.0 (933464) Start javascript script.js.Strom.tibberHTML
                              00:45:54.537	info	javascript.0 (933464) script.js.Strom.tibberHTML: registered 16 subscriptions, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
                              
                              M 1 Reply Last reply
                              0
                              • M Meikie

                                @mcu

                                00:45:54.312	info	javascript.0 (933464) Stop script script.js.Strom.tibberHTML
                                00:45:54.496	info	javascript.0 (933464) Start javascript script.js.Strom.tibberHTML
                                00:45:54.537	info	javascript.0 (933464) script.js.Strom.tibberHTML: registered 16 subscriptions, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
                                
                                M Online
                                M Online
                                MCU
                                wrote on last edited by MCU
                                #408

                                @meikie Nach ca 3 Sekunden sollte jetzt wenigstens TEST auftauchen

                                NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                                Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                M 1 Reply Last reply
                                0
                                • M MCU

                                  @meikie Nach ca 3 Sekunden sollte jetzt wenigstens TEST auftauchen

                                  M Offline
                                  M Offline
                                  Meikie
                                  wrote on last edited by
                                  #409

                                  @mcu Da war ausersehen die 308 kopiert. Diese habe ich jetzt gelöscht. Log:

                                  Nein da passiert nix.

                                  M 1 Reply Last reply
                                  0
                                  • M Meikie

                                    @mcu Da war ausersehen die 308 kopiert. Diese habe ich jetzt gelöscht. Log:

                                    Nein da passiert nix.

                                    M Online
                                    M Online
                                    MCU
                                    wrote on last edited by
                                    #410

                                    @meikie Das ist aber in den Objekten zu sehen?
                                    ddaec8b4-a4dc-4694-a7e5-42fcb878e84e-image.png

                                    NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                                    Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                    M 1 Reply Last reply
                                    0
                                    • M MCU

                                      @meikie Das ist aber in den Objekten zu sehen?
                                      ddaec8b4-a4dc-4694-a7e5-42fcb878e84e-image.png

                                      M Offline
                                      M Offline
                                      Meikie
                                      wrote on last edited by
                                      #411

                                      @mcu Bei mir heißt der Ordner nicht tibberlink, sondern tibberconnect

                                      M 1 Reply Last reply
                                      0
                                      • M Meikie

                                        @mcu Bei mir heißt der Ordner nicht tibberlink, sondern tibberconnect

                                        M Online
                                        M Online
                                        MCU
                                        wrote on last edited by
                                        #412

                                        @meikie Wie soll das auch funktionieren?

                                        NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                                        Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                        M 1 Reply Last reply
                                        0
                                        • M MCU

                                          @meikie Wie soll das auch funktionieren?

                                          M Online
                                          M Online
                                          MCU
                                          wrote on last edited by MCU
                                          #413

                                          @Meikie Dann hast du nicht den richtigen tibberlink-adapter installiert. Das ist die Grundlage.
                                          Aber gut sind denn im tibberconnect auch die Preisdaten?

                                          NUC i7 64GB mit Proxmox ---- https://mcuiobroker.gitbook.io/jarvis-infos/ Aktualisierungen der Doku auf Instagram verfolgen -> https://www.instagram.com/mcuiobroker
                                          Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                          M 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

                                          619

                                          Online

                                          32.4k

                                          Users

                                          81.4k

                                          Topics

                                          1.3m

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

                                          • Don't have an account? Register

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