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

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. HowTo: Zusatz-Programme fuer jarvis v3

NEWS

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

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

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

HowTo: Zusatz-Programme fuer jarvis v3

Geplant Angeheftet Gesperrt Verschoben JavaScript
javascript
889 Beiträge 33 Kommentatoren 214.3k Aufrufe 37 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • M MCU

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

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

      @meikie Es werden sofort die HTML ermittelt.

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

      if(logging){
         log(tibberLink);
      }
      

      NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
      Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

      M 1 Antwort Letzte Antwort
      0
      • M MCU

        @meikie Es werden sofort die HTML ermittelt.

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

        if(logging){
           log(tibberLink);
        }
        
        M Offline
        M Offline
        Meikie
        schrieb am zuletzt editiert von
        #405

        @mcu

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

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

        M 1 Antwort Letzte Antwort
        0
        • M Meikie

          @mcu

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

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

          M Offline
          M Offline
          MCU
          schrieb am zuletzt editiert von MCU
          #406

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

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

          NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
          Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

          M 1 Antwort Letzte Antwort
          0
          • M MCU

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

            let tibberLink = $('tibberlink.'+tibberInst+'.Homes.*.PricesToday.json')
            if(logging){
               log('TEST');
               log(tibberLink);
            }
            
            M Offline
            M Offline
            Meikie
            schrieb am zuletzt editiert von Meikie
            #407

            @mcu

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

              @mcu

              00:45:54.312	info	javascript.0 (933464) Stop script script.js.Strom.tibberHTML
              00:45:54.496	info	javascript.0 (933464) Start javascript script.js.Strom.tibberHTML
              00:45:54.537	info	javascript.0 (933464) script.js.Strom.tibberHTML: registered 16 subscriptions, 1 schedule, 0 messages, 0 logs and 0 file subscriptions
              
              M Offline
              M Offline
              MCU
              schrieb am zuletzt editiert von MCU
              #408

              @meikie Nach ca 3 Sekunden sollte jetzt wenigstens TEST auftauchen

              NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
              Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

              M 1 Antwort Letzte Antwort
              0
              • M MCU

                @meikie Nach ca 3 Sekunden sollte jetzt wenigstens TEST auftauchen

                M Offline
                M Offline
                Meikie
                schrieb am zuletzt editiert von
                #409

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

                Nein da passiert nix.

                M 1 Antwort Letzte Antwort
                0
                • M Meikie

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

                  Nein da passiert nix.

                  M Offline
                  M Offline
                  MCU
                  schrieb am zuletzt editiert von
                  #410

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

                  NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                  Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                  M 1 Antwort Letzte Antwort
                  0
                  • M MCU

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

                    M Offline
                    M Offline
                    Meikie
                    schrieb am zuletzt editiert von
                    #411

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

                    M 1 Antwort Letzte Antwort
                    0
                    • M Meikie

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

                      M Offline
                      M Offline
                      MCU
                      schrieb am zuletzt editiert von
                      #412

                      @meikie Wie soll das auch funktionieren?

                      NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                      Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                      M 1 Antwort Letzte Antwort
                      0
                      • M MCU

                        @meikie Wie soll das auch funktionieren?

                        M Offline
                        M Offline
                        MCU
                        schrieb am zuletzt editiert von MCU
                        #413

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

                        NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                        Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                        M 1 Antwort Letzte Antwort
                        0
                        • M MCU

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

                          M Offline
                          M Offline
                          Meikie
                          schrieb am zuletzt editiert von Meikie
                          #414

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

                          M 2 Antworten Letzte Antwort
                          0
                          • M Meikie

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

                            M Offline
                            M Offline
                            MCU
                            schrieb am zuletzt editiert von
                            #415

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

                            NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                            Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                            1 Antwort Letzte Antwort
                            0
                            • M Meikie

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

                              M Offline
                              M Offline
                              MCU
                              schrieb am zuletzt editiert von MCU
                              #416

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

                              NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                              Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                              M 1 Antwort Letzte Antwort
                              0
                              • M MCU

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

                                M Offline
                                M Offline
                                Meikie
                                schrieb am zuletzt editiert von Meikie
                                #417

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

                                M 1 Antwort Letzte Antwort
                                0
                                • M Meikie

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

                                  M Offline
                                  M Offline
                                  Meikie
                                  schrieb am zuletzt editiert von
                                  #418

                                  @meikie Okay, jetzt ist was drin. Scheint zu funktionieren. Aber leider immer noch keine Graphen in Jarvis.

                                  M 1 Antwort Letzte Antwort
                                  0
                                  • M Meikie

                                    @meikie Okay, jetzt ist was drin. Scheint zu funktionieren. Aber leider immer noch keine Graphen in Jarvis.

                                    M Offline
                                    M Offline
                                    MCU
                                    schrieb am zuletzt editiert von MCU
                                    #419

                                    @meikie Nimm das Log raus da ist deine Id drin.
                                    Die Fehler sind sehr wahrscheinlich da, weil bestimmte Daten jetzt nicht verfügbar sind und erst ab 14:00 Uhr eingestellt werden.
                                    Melde Dich heute Nachmittag, wie es da aussieht.

                                    NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                                    Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                    M 1 Antwort Letzte Antwort
                                    1
                                    • icebearI icebear

                                      @mcu said in HowTo: Zusatz-Programme fuer jarvis v3:

                                      Ich dachte nur die Kurven mit der Soll-temp-Einstellung.

                                      Ah ich verstehe, ja so wär es eigentlich für mich perfekt.

                                      Und beim Klick auf die Gauge kommt dann
                                      details.png

                                      M Offline
                                      M Offline
                                      MCU
                                      schrieb am zuletzt editiert von
                                      #420

                                      @icebear So ein Schritt weiter
                                      Für FritzDect
                                      b109649a-6167-471c-a20c-7e693bcaca57-image.png

                                      Für hm-rpc
                                      3067cbee-e5e1-4b5b-8f59-8af505745b89-image.png

                                      NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                                      Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                      icebearI 1 Antwort Letzte Antwort
                                      1
                                      • M MCU

                                        @icebear So ein Schritt weiter
                                        Für FritzDect
                                        b109649a-6167-471c-a20c-7e693bcaca57-image.png

                                        Für hm-rpc
                                        3067cbee-e5e1-4b5b-8f59-8af505745b89-image.png

                                        icebearI Online
                                        icebearI Online
                                        icebear
                                        schrieb am zuletzt editiert von
                                        #421

                                        @mcu

                                        Das sieht ja schonmal vielversprechend aus

                                        M 1 Antwort Letzte Antwort
                                        0
                                        • icebearI icebear

                                          @mcu

                                          Das sieht ja schonmal vielversprechend aus

                                          M Offline
                                          M Offline
                                          MCU
                                          schrieb am zuletzt editiert von
                                          #422

                                          @icebear Wann ist die Batterie leer?

                                          Voll: 3,0 V
                                          Leer: 1,5V

                                          NUC i7 64GB mit Proxmox ---- Jarvis Infos Aktualisierungen der Doku auf Instagram verfolgen -> mcuiobroker Instagram
                                          Wenn Euch mein Vorschlag geholfen hat, bitte rechts "^" klicken.

                                          1 Antwort Letzte Antwort
                                          0
                                          Antworten
                                          • In einem neuen Thema antworten
                                          Anmelden zum Antworten
                                          • Älteste zuerst
                                          • Neuste zuerst
                                          • Meiste Stimmen


                                          Support us

                                          ioBroker
                                          Community Adapters
                                          Donate

                                          900

                                          Online

                                          32.4k

                                          Benutzer

                                          81.5k

                                          Themen

                                          1.3m

                                          Beiträge
                                          Community
                                          Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                          ioBroker Community 2014-2025
                                          logo
                                          • Anmelden

                                          • Du hast noch kein Konto? Registrieren

                                          • Anmelden oder registrieren, um zu suchen
                                          • Erster Beitrag
                                            Letzter Beitrag
                                          0
                                          • Home
                                          • Aktuell
                                          • Tags
                                          • Ungelesen 0
                                          • Kategorien
                                          • Unreplied
                                          • Beliebt
                                          • GitHub
                                          • Docu
                                          • Hilfe