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

  • Wartung am 15.11. – Forum ab 22:00 Uhr nicht erreichbar
    BluefoxB
    Bluefox
    12
    2
    248

  • 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.7k

HowTo: Zusatz-Programme fuer jarvis v3

HowTo: Zusatz-Programme fuer jarvis v3

Scheduled Pinned Locked Moved JavaScript
javascript
889 Posts 33 Posters 211.1k 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
    #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 Offline
      M Offline
      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 Offline
          M Offline
          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 Offline
                M Offline
                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 Offline
                    M Offline
                    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 Offline
                        M Offline
                        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 Offline
                            M Offline
                            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 Offline
                                M Offline
                                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 Offline
                                    M Offline
                                    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 Offline
                                      M Offline
                                      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
                                      • M MCU

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

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

                                        @mcu Okay, bevor wir hier rumdoktern wäre es ja besser den tibberlink zu installieren. Aber unter Adapter ist der nicht zu finden.

                                        M 2 Replies Last reply
                                        0
                                        • M Meikie

                                          @mcu Okay, bevor wir hier rumdoktern wäre es ja besser den tibberlink zu installieren. Aber unter Adapter ist der nicht zu finden.

                                          M Offline
                                          M Offline
                                          MCU
                                          wrote on last edited by
                                          #415

                                          @meikie Ich sehe den tibberConnect nicht
                                          f29c377f-61b5-45b0-bf15-0e6df9a18e92-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
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          90

                                          Online

                                          32.4k

                                          Users

                                          81.3k

                                          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