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. ioBroker Allgemein
  4. TibberLink Adapter

NEWS

  • Jahresrückblick 2025 – unser neuer Blogbeitrag ist online! ✨
    BluefoxB
    Bluefox
    11
    1
    72

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    11
    1
    554

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    24
    1
    1.7k

TibberLink Adapter

Geplant Angeheftet Gesperrt Verschoben ioBroker Allgemein
631 Beiträge 85 Kommentatoren 202.7k Aufrufe 78 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.
  • S Schimi

    @reblausgt also nicht zusammenhängende 15 min (30min am stück)... sondern einfach nur 2 x 15min egal wie verteilt?

    wenn ich "AmountHours" auf 0.75 stelle, dann wären es 3 x 15min?

    Habe das zuerst so verstanden, das er schaut das er (bei 0.5) 30min am stück findet die 25% günstiger als der max preis ist...

    B Online
    B Online
    bakerman23
    schrieb am zuletzt editiert von
    #612

    @schimi wie kommst du auf 25%?
    Es ist der günstigste Preis vom Tag.

    S 1 Antwort Letzte Antwort
    0
    • B bakerman23

      @schimi wie kommst du auf 25%?
      Es ist der günstigste Preis vom Tag.

      S Offline
      S Offline
      Schimi
      schrieb am zuletzt editiert von
      #613

      @bakerman23 beim "Batterie laden"-kanal?

      Dann sollte die Erklärung überarbeitet werden (vielleicht mit einem Beispiel zu den Einstellungen), habe ich dann total anders/falsch verstanden?

      1 Antwort Letzte Antwort
      0
      • S Schimi

        @reblausgt also nicht zusammenhängende 15 min (30min am stück)... sondern einfach nur 2 x 15min egal wie verteilt?

        wenn ich "AmountHours" auf 0.75 stelle, dann wären es 3 x 15min?

        Habe das zuerst so verstanden, das er schaut das er (bei 0.5) 30min am stück findet die 25% günstiger als der max preis ist...

        R Offline
        R Offline
        ReblausGT
        Developer
        schrieb am zuletzt editiert von
        #614

        @Schimi said in TibberLink Adapter:

        @reblausgt also nicht zusammenhängende 15 min (30min am stück)... sondern einfach nur 2 x 15min egal wie verteilt?

        0.75 sind die 3 besten 15 Minuten zum Laden genutzt.... Entladen wird nur in Zeiten wenn der Preis höher ist wie 1 + Wirkungsgradverlust des Stroms den du geladen hast.....

        Aus dem Source Code (hours sind jetzt 15 minuten... muss ich mal n der Doku ändern):

        	//#region *** SPECIFICATION Smart Battery Buffer ***
        	/*
        		Summary:
        			Develop a channel that categorizes hourly energy prices into three groups—cheap, normal, and expensive.
        			The categorization is based on the total price of each hour, considering a efficiency loss of a battery system.
        
        		Detailed Description:
        			The system has an algorithm to organize hourly energy prices, providing users with a clear understanding of price
        			dynamics. The algorithm follows these steps:
        			- Sort by Total Price: Sort hourly rates in ascending order based on the total price.
        			- Identify Cheap Hours: Starting with the cheapest hour, include hours in the cheap category if the total price is
        			lower than the total price of the most expensive hour minus a minimum distance (MinDelta). Hereby calculate MinDelta
        			based on the average total price of the cheap hours and a user-defined efficiency loss of a battery system. Collect
        			cheap hours up to a maximum number of maxCheapCount
        			- Determine the Most Expensive Hour Among the Cheap: Identify the hour with the highest total price among the cheap hours.
        			- Classify Normal and Expensive Hours: Hours not classified as cheap are further categorized as follows:
        				Normal Hours: Total price is lower than MinDelta plus the highest total price among the cheap hours.
        				Expensive Hours: Total price is higher than MinDelta plus the highest total price among the cheap hours.
        
        		User Customization:
        			Allow users to specify the maximum number of cheap hours they want to identify (maxCheapCount) and
        			define the efficiency loss (efficiencyLoss).
        
        		Output:
        			- Not Active - disable battery charging (OFF-1) and also disable feed into home energy system (OFF-2)
        			- Cheap Hours - enable battery charging (ON-1) and disable feed into home energy system (OFF-2)
        			- Normal Hours - disable battery charging (OFF-1) and also disable feed into home energy system (OFF-2)
        			- Expensive Hours - disable battery charging (OFF-1) and enable feed into home energy system (ON-2)
        		*/
        	//#endregion
        
        L 1 Antwort Letzte Antwort
        1
        • R ReblausGT

          @Schimi said in TibberLink Adapter:

          @reblausgt also nicht zusammenhängende 15 min (30min am stück)... sondern einfach nur 2 x 15min egal wie verteilt?

          0.75 sind die 3 besten 15 Minuten zum Laden genutzt.... Entladen wird nur in Zeiten wenn der Preis höher ist wie 1 + Wirkungsgradverlust des Stroms den du geladen hast.....

          Aus dem Source Code (hours sind jetzt 15 minuten... muss ich mal n der Doku ändern):

          	//#region *** SPECIFICATION Smart Battery Buffer ***
          	/*
          		Summary:
          			Develop a channel that categorizes hourly energy prices into three groups—cheap, normal, and expensive.
          			The categorization is based on the total price of each hour, considering a efficiency loss of a battery system.
          
          		Detailed Description:
          			The system has an algorithm to organize hourly energy prices, providing users with a clear understanding of price
          			dynamics. The algorithm follows these steps:
          			- Sort by Total Price: Sort hourly rates in ascending order based on the total price.
          			- Identify Cheap Hours: Starting with the cheapest hour, include hours in the cheap category if the total price is
          			lower than the total price of the most expensive hour minus a minimum distance (MinDelta). Hereby calculate MinDelta
          			based on the average total price of the cheap hours and a user-defined efficiency loss of a battery system. Collect
          			cheap hours up to a maximum number of maxCheapCount
          			- Determine the Most Expensive Hour Among the Cheap: Identify the hour with the highest total price among the cheap hours.
          			- Classify Normal and Expensive Hours: Hours not classified as cheap are further categorized as follows:
          				Normal Hours: Total price is lower than MinDelta plus the highest total price among the cheap hours.
          				Expensive Hours: Total price is higher than MinDelta plus the highest total price among the cheap hours.
          
          		User Customization:
          			Allow users to specify the maximum number of cheap hours they want to identify (maxCheapCount) and
          			define the efficiency loss (efficiencyLoss).
          
          		Output:
          			- Not Active - disable battery charging (OFF-1) and also disable feed into home energy system (OFF-2)
          			- Cheap Hours - enable battery charging (ON-1) and disable feed into home energy system (OFF-2)
          			- Normal Hours - disable battery charging (OFF-1) and also disable feed into home energy system (OFF-2)
          			- Expensive Hours - disable battery charging (OFF-1) and enable feed into home energy system (ON-2)
          		*/
          	//#endregion
          
          L Offline
          L Offline
          lesiflo
          Most Active
          schrieb am zuletzt editiert von lesiflo
          #615

          @ReblausGT said in TibberLink Adapter:

          Entladen wird nur in Zeiten wenn der Preis höher ist wie 1 + Wirkungsgradverlust des Stroms den du geladen hast.....

          Gelöscht

          1 Antwort Letzte Antwort
          0
          • N Offline
            N Offline
            nkoebe
            schrieb am zuletzt editiert von
            #616

            Moin,

            ich wollte mich hier ganz herzlich bedanken für den tollen Adapter und auch für die Templates der Charts. Das ist wirklich toll gemacht!
            Dank eurer Arbeit habe ich jetzt (mit ein bisschen Hilfe von AI...) für mich auch einen Chart erstellen können, wie ich ihn gerne hätte:
            4b8d7420-7f04-4ad6-90c7-573068dcc822-image.png

            Für den Chart berechne ich den 14a Gesamtpreis selbst, dazu lasse ich mir die Entgelttarife von Westnetz für 14a anzeigen und noch den Normalpreis als gestrichelte Linie.
            Dazu werden die besten (einzelnen) 4 Stunden mit Durchschnittspreis markiert.

            Vielen Dank!

            A 1 Antwort Letzte Antwort
            0
            • N nkoebe

              Moin,

              ich wollte mich hier ganz herzlich bedanken für den tollen Adapter und auch für die Templates der Charts. Das ist wirklich toll gemacht!
              Dank eurer Arbeit habe ich jetzt (mit ein bisschen Hilfe von AI...) für mich auch einen Chart erstellen können, wie ich ihn gerne hätte:
              4b8d7420-7f04-4ad6-90c7-573068dcc822-image.png

              Für den Chart berechne ich den 14a Gesamtpreis selbst, dazu lasse ich mir die Entgelttarife von Westnetz für 14a anzeigen und noch den Normalpreis als gestrichelte Linie.
              Dazu werden die besten (einzelnen) 4 Stunden mit Durchschnittspreis markiert.

              Vielen Dank!

              A Offline
              A Offline
              ArnoD
              schrieb am zuletzt editiert von
              #617

              @nkoebe
              Berücksichtigt Tibber die Netzentgelte nach § 14a EnWG nicht automatisch im Bruttopreis?

              1 Antwort Letzte Antwort
              0
              • N Offline
                N Offline
                nkoebe
                schrieb am zuletzt editiert von
                #618

                Bei der Rechnung denke ich schon (ich werde erst diesen Monat umgestellt).
                Ich bin mir aber nicht sicher, ob sie das bei der API Abfrage über den Adapter auch schon berücksichtigen.
                Wenn es soweit ist, kann ich ja berichten.
                Es sei denn, jemand hier kann das schon bestätigen...

                1 Antwort Letzte Antwort
                0
                • M Offline
                  M Offline
                  Michi_Pi
                  schrieb am zuletzt editiert von
                  #619

                  Ich sehe den normalen Preis, und bei der Monatsabrechnung wird dann die Netzentgeltreduzierung abgezogen.

                  N H A 3 Antworten Letzte Antwort
                  0
                  • M Michi_Pi

                    Ich sehe den normalen Preis, und bei der Monatsabrechnung wird dann die Netzentgeltreduzierung abgezogen.

                    N Offline
                    N Offline
                    nkoebe
                    schrieb am zuletzt editiert von
                    #620

                    @Michi_Pi

                    Danke für die Info! Das hatte ich ehrlicher Weise auch so erwartet.

                    Hier ist das JS Skript (ich hab Copilot benutzt, selber programmiert hab ich nix...):

                    // ------------------------------
                    // Konfiguration
                    // ------------------------------
                    
                    // Netzengelt (wird von Tibber-Preis abgezogen)
                    const NETZENTGELT = 11.5; // ct/kWh
                    
                    // §14a Tarifaufschläge je nach Uhrzeit
                    const TARIF = {
                       low: 1.19,       // 00–06 Uhr
                       standard: 11.88, // 06–15 Uhr & 20–24 Uhr
                       high: 17.75      // 15–20 Uhr
                    };
                    
                    // Datenquelle Tibberlink Adapter
                    const PRICE_BASE = "tibberlink.0.Homes.a51c83ea-7122-4cf7-9b33-8aa17f703c0a.PricesToday.";
                    // Zielobjekt für VIS Chart
                    const CHART_OID = "0_userdata.0.VIS.flexchartAngepassteStrompreis";
                    
                    // ------------------------------
                    // Hilfsfunktionen
                    // ------------------------------
                    
                    /**
                    * Normalisiert Rohwerte in ct/kWh.
                    * - Werte <5 werden als € interpretiert und in ct umgerechnet.
                    * - Negative oder NaN werden verworfen.
                    */
                    function normalizeToCt(baseRaw) {
                       if (isNaN(baseRaw) || baseRaw < 0) return NaN;
                       return baseRaw < 5 ? baseRaw * 100 : baseRaw;
                    }
                    
                    /**
                    * Liefert Tarifaufschlag für eine Viertelstunde (Index 0–95).
                    */
                    function getTarifAdd(q) {
                       const h = Math.floor(q / 4);
                       if (h < 6) return TARIF.low;
                       else if (h < 15) return TARIF.standard;
                       else if (h < 20) return TARIF.high;
                       else return TARIF.standard;
                    }
                    
                    /**
                    * Baut drei Linien für die Tarifzonen (Low/Standard/High).
                    */
                    function getTarifSeriesCt(xAxis) {
                       const low = new Array(96).fill(null);
                       const standard = new Array(96).fill(null);
                       const high = new Array(96).fill(null);
                    
                       for (let q = 0; q < 96; q++) {
                           const h = Math.floor(q / 4);
                           if (h < 6) low[q] = TARIF.low;
                           else if (h < 15) standard[q] = TARIF.standard;
                           else if (h < 20) high[q] = TARIF.high;
                           else standard[q] = TARIF.standard;
                       }
                    
                       return [
                           { name: "Tarif Low", type: "line", step: "end", symbol: "none", data: low,
                             lineStyle: { width: 1.5, color: "green" }, areaStyle: { color: "rgba(0,200,0,0.3)" } },
                           { name: "Tarif Standard", type: "line", step: "end", symbol: "none", data: standard,
                             lineStyle: { width: 1.5, color: "orange" }, areaStyle: { color: "rgba(255,165,0,0.3)" } },
                           { name: "Tarif High", type: "line", step: "end", symbol: "none", data: high,
                             lineStyle: { width: 1.5, color: "red" }, areaStyle: { color: "rgba(255,0,0,0.3)" } }
                       ];
                    }
                    
                    /**
                    * Liefert aktuellen Viertelstundenindex (0–95).
                    */
                    function getCurrentQuarterIndex() {
                       const now = new Date();
                       return now.getHours() * 4 + Math.floor(now.getMinutes() / 15);
                    }
                    
                    /**
                    * Berechnet angepasste Preise nach §14a (Basispreis – Netzengelt + Tarifaufschlag).
                    */
                    function getAdjustedQuarterPricesCt() {
                       const res = [];
                       for (let q = 0; q < 96; q++) {
                           const s = getState(`${PRICE_BASE}${q}.total`);
                           const baseCt = normalizeToCt(s?.val !== undefined ? Number(s.val) : NaN);
                           if (isNaN(baseCt)) { res.push(null); continue; }
                           res.push(Number((baseCt - NETZENTGELT + getTarifAdd(q)).toFixed(2)));
                       }
                       return res;
                    }
                    
                    /**
                    * Baut X-Achse mit 96 Zeitlabels (00:00, 00:15, …).
                    */
                    function buildXAxis96() {
                       const labels = [];
                       for (let q = 0; q < 96; q++) {
                           const h = Math.floor(q / 4);
                           const m = (q % 4) * 15;
                           labels.push(`${("0"+h).slice(-2)}:${("0"+m).slice(-2)}`);
                       }
                       return labels;
                    }
                    
                    /**
                    * Ermittelt die 4 günstigsten Stundenblöcke (Durchschnitt aus 4 Viertelstunden).
                    */
                    function getBest4AdjustedHourBlocks() {
                       const adjusted = getAdjustedQuarterPricesCt();
                       const hours = [];
                    
                       for (let h = 0; h < 24; h++) {
                           const start = h * 4;
                           const block = adjusted.slice(start, start + 4).filter(v => v !== null);
                           if (block.length === 4) {
                               const avg = block.reduce((a, b) => a + b, 0) / block.length;
                               hours.push({ hour: h, avg });
                           }
                       }
                    
                       return hours.sort((a, b) => a.avg - b.avg).slice(0, 4);
                    }
                    // ------------------------------
                    // Chart JSON (96 Werte, 2 Linien)
                    // ------------------------------
                    
                    function buildChartJSON96() {
                       // §14a angepasste Preise
                       const adjusted = getAdjustedQuarterPricesCt();
                    
                       // Originalpreise (nur normalisiert)
                       const original = [];
                       for (let q = 0; q < 96; q++) {
                           const s = getState(`${PRICE_BASE}${q}.total`);
                           const baseCt = normalizeToCt(s?.val !== undefined ? Number(s.val) : NaN);
                           original.push(isNaN(baseCt) ? null : Number(baseCt.toFixed(2)));
                       }
                    
                       // X-Achse mit Zeitlabels
                       const xAxis = buildXAxis96();
                    
                       // Wertebereich für Farbskala
                       const numeric = adjusted.filter(v => v !== null && !isNaN(v));
                       const minVal = numeric.length ? Math.min(...numeric) : 0;
                       const maxVal = numeric.length ? Math.max(...numeric) : 1;
                    
                       // Chart-Definition
                       const chart = {
                           backgroundColor: "#666666",
                           tooltip: { trigger: "axis", axisPointer: { type: "cross" } },
                           grid: { left: "10%", right: "4%", top: "8%", bottom: "8%" },
                    
                           // Achsen
                           xAxis: {
                               type: "category", boundaryGap: false, data: xAxis,
                               axisLabel: { color: "rgb(230,230,230)" },
                               axisLine: { lineStyle: { color: "rgb(230,230,230)" } },
                               axisTick: { lineStyle: { color: "rgb(230,230,230)" } }
                           },
                           yAxis: {
                               type: "value",
                               axisLabel: { formatter: "{value} ct", color: "rgb(230,230,230)" },
                               axisLine: { lineStyle: { color: "rgb(230,230,230)" } },
                               axisTick: { lineStyle: { color: "rgb(230,230,230)" } }
                           },
                    
                           // Farbskala (wird nicht angezeigt, nur für Farbverläufe)
                           visualMap: {
                               min: minVal,
                               max: maxVal,
                               inRange: { color: ["green", "yellow", "red"] },
                               show: false
                           },
                    
                           // Datenserien
                           series: [
                               {
                                   name: "Angepasster Preis",
                                   type: "line",
                                   step: "end",
                                   symbol: "none",
                                   data: adjusted,
                                   lineStyle: { width: 2 },
                    
                                   // vertikale Linie "Jetzt"
                                   markLine: {
                                       data: [{ name: "Jetzt", xAxis: xAxis[getCurrentQuarterIndex()] }],
                                       lineStyle: { color: "rgb(230,230,230)", type: "dashed", width: 2 },
                                       label: { formatter: "Jetzt", color: "rgb(230,230,230)" }
                                   },
                    
                                   // Flächen für Tarifzonen + beste 4 Stundenblöcke
                                   markArea: {
                                       data: [
                                           // feste Tarifzonen
                                           [{ xAxis: xAxis[0], itemStyle: { color: "rgba(0,200,0,0.1)" }, name: "Low" }, { xAxis: xAxis[24] }],
                                           [{ xAxis: xAxis[24], itemStyle: { color: "rgba(255,165,0,0.1)" }, name: "Standard" }, { xAxis: xAxis[60] }],
                                           [{ xAxis: xAxis[60], itemStyle: { color: "rgba(255,0,0,0.1)" }, name: "High" }, { xAxis: xAxis[80] }],
                                           [{ xAxis: xAxis[80], itemStyle: { color: "rgba(255,165,0,0.1)" }, name: "Standard" }, { xAxis: xAxis[95] }],
                    
                                           // dynamisch: beste 4 Stundenblöcke (hellblau mit Label)
                                           ...getBest4AdjustedHourBlocks().map(b => [
                                               {
                                                   xAxis: xAxis[b.hour * 4],
                                                   itemStyle: { color: "rgba(0,150,255,0.3)" },
                                                   label: {
                                                       show: true,
                                                       color: "rgb(230,230,230)",
                                                       formatter: `${xAxis[b.hour * 4]} - ${xAxis[(b.hour + 1) * 4]}\n(Ø ${b.avg.toFixed(2)} ct)`
                                                   }
                                               },
                                               { xAxis: xAxis[(b.hour + 1) * 4] }
                                           ])
                                       ]
                                   }
                               },
                    
                               // Vergleichslinie: Originalpreise
                               {
                                   name: "Normalpreis",
                                   type: "line",
                                   step: "end",
                                   symbol: "none",
                                   data: original,
                                   lineStyle: { type: "dashed", width: 1, color: "#999999" },
                                   itemStyle: { color: "#999999" }
                               },
                    
                               // Tariflinien (Low/Standard/High)
                               ...getTarifSeriesCt(xAxis)
                           ]
                       };
                    
                       return JSON.stringify(chart);
                    }
                    // ------------------------------
                    // Trigger: alle 96 OIDs überwachen
                    // ------------------------------
                    
                    // Liste aller 96 Viertelstunden-OIDs aus Tibberlink
                    const quarterOids = Array.from({ length: 96 }, (_, i) => `${PRICE_BASE}${i}.total`);
                    
                    /**
                    * Schreibt das Chart-JSON ins Zielobjekt.
                    */
                    function writeChart() {
                       try {
                           const json = buildChartJSON96();   // Chart-Definition erzeugen
                           setState(CHART_OID, json, true);   // Ergebnis ins VIS-Objekt schreiben
                       } catch (e) {
                           console.error("Fehler beim Erstellen des Chart-JSON:", e);
                       }
                    }
                    
                    // Aktualisierung bei jeder Änderung eines Viertelstundenwertes
                    on({ id: quarterOids, change: "ne" }, () => {
                       writeChart();
                    });
                    
                    // Initiales Schreiben beim Start des Scripts
                    writeChart();
                    
                    

                    1 Antwort Letzte Antwort
                    0
                    • M Michi_Pi

                      Ich sehe den normalen Preis, und bei der Monatsabrechnung wird dann die Netzentgeltreduzierung abgezogen.

                      H Offline
                      H Offline
                      HansJochen
                      schrieb am zuletzt editiert von
                      #621

                      @Michi_Pi sagte in TibberLink Adapter:

                      Ich sehe den normalen Preis, und bei der Monatsabrechnung wird dann die Netzentgeltreduzierung abgezogen.

                      Schade, ich hätte eigentlich gehofft, dass Tibber das schlauer übermittelt. Das ist ja nicht nur ein Anzeige-Thema, sondern auch relevant für die Berechnung des Zeitfensters. Ich fände es cool, wenn der Tibberlink Adapter eine Korrekturmöglichkeit integriert. Die Netzgebühren sind ja sehr statisch, dann müssten die Betroffenen halt einmal im Jahr die Gebührenstaffel von Hand eintragen.

                      Das nur als Anregung. Mein Netzbetreiber bietet keine für mich attraktiven 14a Zeitfenster, so dass ich Modul 3 gar nicht erst beauftragt habe.

                      1 Antwort Letzte Antwort
                      0
                      • N Offline
                        N Offline
                        nkoebe
                        schrieb am zuletzt editiert von
                        #622

                        Das wäre natürlich elegant, wenn es im Adapter für 14a eine Config gäbe.
                        Man könnte die Tarife mit den Zeitfenstern angeben und das normale Entgelt und das würde dann die Preise entsprechend berechnen...

                        1 Antwort Letzte Antwort
                        0
                        • M Michi_Pi

                          Ich sehe den normalen Preis, und bei der Monatsabrechnung wird dann die Netzentgeltreduzierung abgezogen.

                          A Offline
                          A Offline
                          ArnoD
                          schrieb am zuletzt editiert von
                          #623

                          @Michi_Pi
                          Das bedeutet, dass Tibber falsche Bruttopreise über die API übermittelt?
                          Das erstaunt mich doch sehr, da die regionalen Unterschiede im Netzentgelt ja im Bruttopreis aktuell berücksichtigt werden.
                          Ich könnte mir sogar vorstellen, dass es hier mit den Verbraucherzentralen Ärger geben könnte, die sehen das nicht so locker, wenn falsche Preise angegeben werden.
                          Ich hoffe das Tibber das dann noch ändert.

                          1 Antwort Letzte Antwort
                          0
                          • S Offline
                            S Offline
                            Schimi
                            schrieb am zuletzt editiert von
                            #624

                            nach meinen Infos... wird bei Modul1 der betrag mit der Gesamtrechnung abgezogen (ist auch richtig, ist ja keine kWh Reduzierung)...
                            Bei Modul 3 soll es direkt in der anzeige richtig angezeigt werden (und auch abgerechnet), zumindest hört man es von den wenigen die Modul 3 bereits haben (youtube)

                            1 Antwort Letzte Antwort
                            0
                            • H Offline
                              H Offline
                              HansJochen
                              schrieb am zuletzt editiert von
                              #625

                              @Michi_Pi habe ich Dich falsch verstanden oder ist das bei Dir anders? Ich dachte, Du hast Modul 3 und bekommst die für Deine Region "normalen" Netzentgelte im Brutto Preis übermittelt und erst am Monatsende wird das dann über die Abrechnung korrigiert?

                              M 1 Antwort Letzte Antwort
                              0
                              • M Offline
                                M Offline
                                Michi_Pi
                                schrieb am zuletzt editiert von
                                #626

                                Hi, nein ich hab nur Modul 1. Modul 3 ist in meiner Region leider auch nicht attraktiv. Da der dieses Zeitfenster nur für die Sommermonate anwendet.

                                1 Antwort Letzte Antwort
                                0
                                • H HansJochen

                                  @Michi_Pi habe ich Dich falsch verstanden oder ist das bei Dir anders? Ich dachte, Du hast Modul 3 und bekommst die für Deine Region "normalen" Netzentgelte im Brutto Preis übermittelt und erst am Monatsende wird das dann über die Abrechnung korrigiert?

                                  M Offline
                                  M Offline
                                  Michi_Pi
                                  schrieb am zuletzt editiert von
                                  #627

                                  @HansJochen sagte in TibberLink Adapter:

                                  @Michi_Pi habe ich Dich falsch verstanden oder ist das bei Dir anders? Ich dachte, Du hast Modul 3 und bekommst die für Deine Region "normalen" Netzentgelte im Brutto Preis übermittelt und erst am Monatsende wird das dann über die Abrechnung korrigiert?

                                  Ja genau, so ist es.

                                  1 Antwort Letzte Antwort
                                  0
                                  • H Offline
                                    H Offline
                                    HansJochen
                                    schrieb am zuletzt editiert von
                                    #628

                                    @Michi_Pi

                                    Okay, aber Du hast ja Modul 1, nicht Modul 3. Dann sind die Netzentgelte für die Aussteuerung ja auch einigermaßen egal, weil sie zu jeder Zeit gleich sind und Du trotzdem zum günstigsten Zeitfenster gelenkt wirst. Bisschen überraschend, dass Tibber anscheinend bei Modul 3 die echten Brutto Preise übermittelt und bei Modul 1 nicht. Vielleicht ist das aber auch nur für Einzelne und nur für eine Übergangszeit anders, abhängig vom Netzbetreiber o.ä. Falls Tibber das bei Dir mal ändert, schreib es doch gerne hier.

                                    Mit Modul 3 ist hier keiner, oder? Das ist ja noch einigermaßen neu.

                                    1 Antwort Letzte Antwort
                                    0
                                    • R Offline
                                      R Offline
                                      ReblausGT
                                      Developer
                                      schrieb am zuletzt editiert von
                                      #629

                                      Ich warte auf meine Modul 3 Schaltung.... dann kann ich das auch testen. Nur leider zeiht sich die Bearbeitung beim Netzbetreiber extrem.

                                      1 Antwort Letzte Antwort
                                      0
                                      • M Offline
                                        M Offline
                                        Michi_Pi
                                        schrieb am zuletzt editiert von
                                        #630

                                        glaub Tibber bastelt da eh noch ständig rum. Am Anfang des Jahres bin ich noch auf Tibber zugegangen und hab ihnen meine Vergünstigungen mitgeteilt damit ich das überhaupt monatlich abgezogen bekommen hatte. Zudem ist es ja auch nicht ganz einfach, da ja auch jeder Netzbetreiber andere Tarife hat. Dieses Jahr hätte bei mir Modul 3 noch Sinn gemacht, nächstes Jahr nicht mehr. Zu dem Rollout hat mein Netzbetreiben auch nicht wirklich Ambitionen. Mit dem Gateway standen die schon bei mir, aber wegen schlechtem Empfang gingen Sie wieder und seither auch keine Rückmeldung. Auch nicht das mir eine externe Antenne oder dergleichen Angeboten wurde damit das funktionieren würde.

                                        1 Antwort Letzte Antwort
                                        0
                                        • L Offline
                                          L Offline
                                          lesiflo
                                          Most Active
                                          schrieb am zuletzt editiert von lesiflo
                                          #631

                                          Hi, falls jemand Interesse hat hier mal zwei Diagramme zum Nachbauen für flexcharts

                                          Jahr:

                                          // ============================================================================
                                          // Tibber Jahresübersicht + eCharts VIS-Widget
                                          // ----------------------------------------------------------------------------
                                          // - Erstellt 12 Datenpunkte für Kosten, Verbrauch, Preis
                                          // - Liest tibber Monthly JSON aus
                                          // - Ergänzt/überschreibt aktuellen Monat aus 0_userdata-Datenpunkten
                                          // - Erstellt eCharts-Konfiguration für VIS
                                          // - Tooltip mit 2 Nachkommastellen
                                          // ============================================================================
                                          
                                          // =================== KONFIG ===================
                                          const jsonMonthlyDP = 'tibberlink.0.Homes.xxxxxxxxxxxxx.Consumption.jsonMonthly';
                                          const rootDP        = '0_userdata.0.Tibber.Jahreswerte';
                                          const visDP         = `${rootDP}.eCharts_Monatsbalken`;
                                          
                                          // Userdata aktuelle Monatswerte
                                          const dpPriceThisMonth = '0_userdata.0.Tibber.AvgUnitPriceThisMonth';
                                          const dpConsThisMonth  = '0_userdata.0.Tibber.SumConsumptionThisMonth';
                                          const dpCostThisMonth  = '0_userdata.0.Tibber.SumUnitCostThisMonth';
                                          
                                          // =================== 12 Monats-Datenpunkte erzeugen ===================
                                          function createMonthDPs() {
                                              for (let m = 1; m <= 12; m++) {
                                                  createState(`${rootDP}.Cost.M${m}`, 0,  { name: `Kosten Monat ${m}`,       type: 'number', unit: '€',     role: 'value' });
                                                  createState(`${rootDP}.Cons.M${m}`, 0,  { name: `Verbrauch Monat ${m}`,    type: 'number', unit: 'kWh',   role: 'value' });
                                                  createState(`${rootDP}.Price.M${m}`,0,  { name: `Durchschnittspreis M${m}`, type: 'number', unit: '€/kWh', role: 'value' });
                                              }
                                              createState(visDP, '', { name: 'eCharts Config Monatsbalken', type: 'string', role: 'text' });
                                          }
                                          createMonthDPs();
                                          
                                          
                                          // =================== Hauptfunktion ===================
                                          function updateYearValues() {
                                              try {
                                                  const raw = getState(jsonMonthlyDP).val;
                                                  if (!raw) return log("Keine Monatsdaten vorhanden", "warn");
                                          
                                                  const data = JSON.parse(raw);
                                                  const currentYear  = new Date().getFullYear();
                                                  const currentMonth = new Date().getMonth() + 1;
                                          
                                                  let arrCost  = Array(12).fill(0);
                                                  let arrCons  = Array(12).fill(0);
                                                  let arrPrice = Array(12).fill(0);
                                          
                                                  // ========== JSON durchlaufen ==========
                                                  data.forEach(entry => {
                                                      if (!entry.from) return;
                                          
                                                      const d = new Date(entry.from);
                                                      const year  = d.getFullYear();
                                                      const month = d.getMonth() + 1;
                                          
                                                      if (year !== currentYear) return;
                                          
                                                      const cost  = parseFloat(entry.totalCost)   || 0;
                                                      const cons  = parseFloat(entry.consumption) || 0;
                                                      const price = parseFloat(entry.unitPrice)   || 0;
                                          
                                                      arrCost[month - 1]  = parseFloat(cost.toFixed(2));
                                                      arrCons[month - 1]  = parseFloat(cons.toFixed(2));
                                                      arrPrice[month - 1] = parseFloat(price.toFixed(2));
                                          
                                                      setState(`${rootDP}.Cost.M${month}`,  cost,  true);
                                                      setState(`${rootDP}.Cons.M${month}`,  cons,  true);
                                                      setState(`${rootDP}.Price.M${month}`, price, true);
                                                  });
                                          
                                                  // =============================================================
                                                  //  **AKTUELLEN MONAT MIT USERDATA ÜBERSCHREIBEN**
                                                  // =============================================================
                                                  const uPrice = parseFloat(getState(dpPriceThisMonth).val) || 0;
                                                  const uCons  = parseFloat(getState(dpConsThisMonth).val)  || 0;
                                                  const uCost  = parseFloat(getState(dpCostThisMonth).val)  || 0;
                                          
                                                  arrCost[currentMonth - 1]  = parseFloat(uCost.toFixed(2));
                                                  arrCons[currentMonth - 1]  = parseFloat(uCons.toFixed(2));
                                                  arrPrice[currentMonth - 1] = parseFloat(uPrice.toFixed(2));
                                          
                                                  setState(`${rootDP}.Cost.M${currentMonth}`,  uCost,  true);
                                                  setState(`${rootDP}.Cons.M${currentMonth}`,  uCons,  true);
                                                  setState(`${rootDP}.Price.M${currentMonth}`, uPrice, true);
                                          
                                                  // =====================================================================
                                                  // eCharts VIS-Konfiguration
                                                  // =====================================================================
                                                  const option = {
                                                      textStyle: { color: '#FFFFFF' },
                                                      tooltip: {
                                                          trigger: 'axis',
                                                          textStyle: { color: '#525252' },
                                                          formatter: function(params) {
                                                              return params.map(p => {
                                                                  let unit = '€/kWh';
                                                                  if (p.seriesName.includes('€')) unit = '€';
                                                                  else if (p.seriesName.includes('kWh')) unit = 'kWh';
                                                                  return `${p.seriesName}: ${p.value.toFixed(2)} ${unit}`;
                                                              }).join('<br/>');
                                                          }
                                                      },
                                                      legend: {
                                                          textStyle: { color: '#FFFFFF' }
                                                      },
                                                      xAxis: {
                                                          type: 'category',
                                                          data: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
                                                          axisLabel: { color: '#FFFFFF' }
                                                      },
                                                      yAxis: [
                                                          {
                                                              type: 'value',
                                                              name: 'Kosten / Verbrauch',
                                                              axisLabel: { color: '#FFFFFF' },
                                                              nameTextStyle: { color: '#FFFFFF' },
                                                              splitLine: { show: true, lineStyle: { color: '#525252' } },
                                                              axisLine: { lineStyle: { color: '#ccc' } }
                                                          },
                                                          {
                                                              type: 'value',
                                                              name: 'Preis',
                                                              position: 'right',
                                                              axisLabel: { color: '#FFFFFF' },
                                                              nameTextStyle: { color: '#FFFFFF' },
                                                              splitLine: { show: true, lineStyle: { color: '#525252' } },
                                                              axisLine: { lineStyle: { color: '#ccc' } }
                                                          }
                                                      ],
                                                      series: [
                                                          { name: 'Kosten (€)', type: 'bar', data: arrCost },
                                                          { name: 'Verbrauch (kWh)', type: 'bar', data: arrCons },
                                                          { name: 'Preis (€/kWh)', type: 'line', yAxisIndex: 1, data: arrPrice }
                                                      ]
                                                  };
                                          
                                                  setState(visDP, JSON.stringify(option), true);
                                                  log("Jahreswerte + aktueller Monat + eCharts VIS aktualisiert", "info");
                                          
                                              } catch (e) {
                                                  log("Fehler JSON: " + e, "error");
                                              }
                                          }
                                          
                                          // =================== TRIGGER ===================
                                          updateYearValues();
                                          on({ id: jsonMonthlyDP, change: 'any' }, () => updateYearValues());
                                          on({ id: [dpPriceThisMonth, dpConsThisMonth, dpCostThisMonth], change: 'ne' }, () => updateYearValues());
                                          

                                          Monat:

                                          // ============================================================================
                                          // Tibber Daily Übersicht für VIS eCharts
                                          // ----------------------------------------------------------------------------
                                          // - ALLE Daten aus Tibbers jsonDaily
                                          // - Linke Achse: Kosten (€) + Verbrauch (kWh)
                                          // - Rechte Achse: Preis (€/kWh)
                                          // - Schriftfarbe X/Y weiß, Y-Hilfslinien #525252
                                          // - Rechte Y-Achse Maximalwert auf 3 Nachkommastellen
                                          // - Preislinie nicht geglättet
                                          // ============================================================================
                                          
                                          const jsonDailyDP = 'tibberlink.0.Homes.xxxxxxxxxxx.Consumption.jsonDaily';
                                          const dpBase = '0_userdata.0.Tibber.Daily.';
                                          const dpDates     = dpBase + 'Dates';
                                          const dpCost      = dpBase + 'Cost';
                                          const dpUsage     = dpBase + 'Usage';
                                          const dpUnitPrice = dpBase + 'UnitPrice';
                                          const dpEchart    = dpBase + 'EchartConfig';
                                          
                                          // =================== Hilfsfunktion ===================
                                          function ensureDP(id) {
                                              if (!existsState(id)) createState(id, '', { type: 'string', read: true, write: true });
                                          }
                                          [dpDates, dpCost, dpUsage, dpUnitPrice, dpEchart].forEach(ensureDP);
                                          
                                          // =================== Datum formatieren TT.MM. ===================
                                          function formatDateTTMM(fromStr) {
                                              const d = new Date(fromStr);
                                              if (isNaN(d)) return '';
                                              const day = ('0' + d.getDate()).slice(-2);
                                              const month = ('0' + (d.getMonth() + 1)).slice(-2);
                                              return `${day}.${month}`;
                                          }
                                          
                                          // =================== Hauptfunktion ===================
                                          async function buildTibberDailyChart() {
                                              const raw = await getStateAsync(jsonDailyDP);
                                              if (!raw || !raw.val) {
                                                  log('⚠ jsonDaily leer oder nicht verfügbar', 'warn');
                                                  return;
                                              }
                                          
                                              let daily;
                                              try {
                                                  daily = JSON.parse(raw.val);
                                                  if (!Array.isArray(daily)) {
                                                      log('❌ JSON ist kein Array', 'error');
                                                      return;
                                                  }
                                              } catch (e) {
                                                  log('❌ Fehler beim Parsen von jsonDaily: ' + e, 'error');
                                                  return;
                                              }
                                          
                                              const dates = [];
                                              const cost = [];
                                              const usage = [];
                                              const price = [];
                                          
                                              daily.forEach(entry => {
                                                  dates.push(formatDateTTMM(entry.from));
                                                  cost.push(Number(entry.totalCost || 0).toFixed(2));
                                                  usage.push(Number(entry.consumption || 0).toFixed(2));
                                                  price.push(Number(entry.unitPrice || 0).toFixed(3));
                                              });
                                          
                                              // Datenpunkte aktualisieren
                                              setState(dpDates, JSON.stringify(dates), true);
                                              setState(dpCost, JSON.stringify(cost), true);
                                              setState(dpUsage, JSON.stringify(usage), true);
                                              setState(dpUnitPrice, JSON.stringify(price), true);
                                          
                                              // Rechte Y-Achse Maximalwert für Preis berechnen (3 Nachkommastellen)
                                              let maxPrice = Math.max(...price.map(p => Number(p))) * 1.1; // 10% Puffer
                                              maxPrice = Number(maxPrice.toFixed(3));
                                          
                                              // Linke Achse: Maximalwert für Kosten und Verbrauch
                                              const maxLeft = Math.max(
                                                  ...cost.map(c => Number(c)),
                                                  ...usage.map(u => Number(u))
                                              ) * 1.1;
                                          
                                              const echartConfig = {
                                                  textStyle: { color: '#FFFFFF' },
                                                  tooltip: {
                                                      trigger: 'axis',
                                                      textStyle: { color: '#525252' },
                                                      formatter: function(params) {
                                                          const day = params[0].axisValue;
                                                          const kosten = params.find(p => p.seriesName === 'Kosten (€)')?.value || 0;
                                                          const verbrauch = params.find(p => p.seriesName === 'Verbrauch (kWh)')?.value || 0;
                                                          const preis = params.find(p => p.seriesName === 'Preis (€/kWh)')?.value || 0;
                                                          return `${day} → Kosten: ${Number(kosten).toFixed(2)} € | Verbrauch: ${Number(verbrauch).toFixed(2)} kWh | Preis: ${Number(preis).toFixed(3)} €/kWh`;
                                                      }
                                                  },
                                                  legend: { textStyle: { color: '#FFFFFF' }, data: ['Kosten (€)', 'Verbrauch (kWh)', 'Preis (€/kWh)'] },
                                                  xAxis: { type: 'category', data: dates, axisLabel: { color: '#FFFFFF' } },
                                                  yAxis: [
                                                      {
                                                          type: 'value',
                                                          name: 'Kosten / Verbrauch',
                                                          min: 0,
                                                          max: maxLeft,
                                                          axisLabel: { color: '#FFFFFF' },
                                                          nameTextStyle: { color: '#FFFFFF', align: 'center' }, // linksbündig
                                                          splitLine: { show: true, lineStyle: { color: '#525252' } }
                                                      },
                                                      {
                                                          type: 'value',
                                                          name: 'Preis',
                                                          position: 'right',
                                                          min: 0,
                                                          max: maxPrice,
                                                          axisLabel: { 
                                                              color: '#FFFFFF', 
                                                              formatter: function(value) { return Number(value).toFixed(3) + ' €/kWh'; } 
                                                          },
                                                          nameTextStyle: { color: '#FFFFFF' },
                                                          splitLine: { show: true, lineStyle: { color: '#525252' } }
                                                      }
                                                  ],
                                                  series: [
                                                      { name: 'Kosten (€)', type: 'bar', data: cost, yAxisIndex: 0 },
                                                      { name: 'Verbrauch (kWh)', type: 'bar', data: usage, yAxisIndex: 0 },
                                                      { name: 'Preis (€/kWh)', type: 'line', data: price, yAxisIndex: 1 } // nicht geglättet
                                                  ]
                                              };
                                          
                                              setState(dpEchart, JSON.stringify(echartConfig), true);
                                              log('✔ Tibber Daily für VIS aktualisiert – ' + daily.length + ' Einträge');
                                          }
                                          
                                          // =================== Trigger ===================
                                          on({ id: jsonDailyDP, change: 'any' }, () => buildTibberDailyChart());
                                          buildTibberDailyChart();
                                          

                                          image.png

                                          image.png

                                          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
                                          FAQ Cloud / IOT
                                          HowTo: Node.js-Update
                                          HowTo: Backup/Restore
                                          Downloads
                                          BLOG

                                          438

                                          Online

                                          32.5k

                                          Benutzer

                                          81.8k

                                          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