Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. HowTo: Zusatz-Programme fuer jarvis v3

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    HowTo: Zusatz-Programme fuer jarvis v3

    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      Meikie @MCU last edited by

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

      M 1 Reply Last reply Reply Quote 0
      • M
        MCU @Meikie last edited by MCU

        @meikie Irgendwelche Meldungen im ioBroker-LOG?

        Stelle mal Dein Programm komplett rein.

        M 1 Reply Last reply Reply Quote 0
        • M
          Meikie @MCU last edited by

          @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 Reply Quote 0
          • M
            Meikie @Meikie last edited by

            @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 Reply Quote 0
            • M
              MCU @Meikie last edited by MCU

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

              M 1 Reply Last reply Reply Quote 0
              • M
                Meikie @MCU last edited by

                // *********************************
                // 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 Reply Quote 0
                • M
                  MCU @Meikie last edited by 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 1 Reply Last reply Reply Quote 0
                  • M
                    Meikie @MCU last edited by

                    @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 Reply Quote 0
                    • M
                      MCU @Meikie last edited by 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 1 Reply Last reply Reply Quote 0
                      • M
                        Meikie @MCU last edited by 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 1 Reply Last reply Reply Quote 0
                        • M
                          MCU @Meikie last edited by MCU

                          @meikie Nach ca 3 Sekunden sollte jetzt wenigstens TEST auftauchen

                          M 1 Reply Last reply Reply Quote 0
                          • M
                            Meikie @MCU last edited by

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

                            Nein da passiert nix.

                            M 1 Reply Last reply Reply Quote 0
                            • M
                              MCU @Meikie last edited by

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

                              M 1 Reply Last reply Reply Quote 0
                              • M
                                Meikie @MCU last edited by

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

                                M 1 Reply Last reply Reply Quote 0
                                • M
                                  MCU @Meikie last edited by

                                  @meikie Wie soll das auch funktionieren?

                                  M 1 Reply Last reply Reply Quote 0
                                  • M
                                    MCU @MCU last edited by 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 1 Reply Last reply Reply Quote 0
                                    • M
                                      Meikie @MCU last edited by 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 2 Replies Last reply Reply Quote 0
                                      • M
                                        MCU @Meikie last edited by

                                        @meikie Ich sehe den tibberConnect nicht
                                        f29c377f-61b5-45b0-bf15-0e6df9a18e92-image.png

                                        1 Reply Last reply Reply Quote 0
                                        • M
                                          MCU @Meikie last edited by MCU

                                          @meikie Sofort raus damit.
                                          Das Bild raus! Da ist Deine ID drin.
                                          Woher hast du den tibberConnect?

                                          M 1 Reply Last reply Reply Quote 0
                                          • M
                                            Meikie @MCU last edited by Meikie

                                            @mcu
                                            Habe es jetzt installiert. War unter Beta zu finden.

                                            M 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            935
                                            Online

                                            31.9k
                                            Users

                                            80.1k
                                            Topics

                                            1.3m
                                            Posts

                                            javascript
                                            31
                                            864
                                            175290
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo