Hallo @prohand, super Arbeit, ich habe den Code des Branches überprüft und das Ergebnis ist konsistent mit dem, was der Core macht. Du kannst pushen, die Mechanik ist gut. Drei Punkte gibt es trotzdem, von denen zwei eine Korrektur vor oder direkt nach dem Produktionsstart erfordern.
1. Der Parent ist ein Zähler, der auf null zurückgesetzt wird, kein Index
Du veröffentlichst „Energie heute“ unter energy-sensor / energy, was Gladys als „kumulierter Energieverbrauch“ dokumentiert und als Index behandelt. Der Job calculateConsumptionFromIndex macht index(t) − index(t−1) und wirft negative Deltas weg („counter reset detected“). Also wird nichts doppelt gezählt — das ist gut, warum dein Tagesgesamtwert genau ist — aber alles, was zwischen der letzten Abfrage vor Mitternacht und der ersten Abfrage nach Mitternacht verbraucht wird, geht verloren, jede Nacht. Bei 900 Sekunden Abfrageintervall ist das das letzte Viertel der Stunde; und wenn Daikin seinen Bucket 22h–24h erst nach Mitternacht füllt, sind es zwei Stunden, die verschwinden.
Der saubere Fix: Die Integration hält ihren eigenen kumulierten Wert (in ihrem Store, total += max(0, today − today_vorgänger)) und veröffentlicht einen echten energy-sensor / index, der monoton ist. Der Core leitet dann genau ab, und das Mitternachtsproblem verschwindet.
2. Die 2-Stunden-Buckets verfälschen die Kosten in HP/HC und Tempo
Daikin bietet nur 12 Intervalle von 2 Stunden. Deine 30-Minuten-Serie wird also so aussehen: 0, 0, 0, 1.8 kWh, 0, 0, 0, …. Der Tagesgesamtwert ist korrekt (deshalb die Übereinstimmung mit der Onecta-App), aber die Verteilung über den Tag ist es nicht. Denn calculateCostFrom berechnet jede 30-Minuten-Fenster mit dem Preis dieses Fensters: Bei einem Basisvertrag ist das ohne Konsequenzen, bei Spitzen-/Nebenspitzen- oder Tempo-Tarifen kann der Preis jedoch deutlich falsch sein, je nachdem, wann die Abfrage stattfand.
Zwei Optionen: Das klar dokumentieren („Kosten zuverlässig im Basisvertrag, indikativ in HP/HC“), oder besser — saveStates akzeptiert ein created_at, du kannst also die Zustände des Index zeitlich auf die Grenzen der Daikin-Buckets veröffentlichen, statt zur Abfragezeit. Der Verbrauch fällt dann in die richtigen Halbstunden.
3. UUIDs selbst ableiten, ist mein Problem, nicht deins
Die ids der Features auszuwählen, um energy_parent_id verweisen zu können, bevor die Zeilen existieren, funktioniert (das device.create fügt die Features ein und löst die Links in einem zweiten Durchgang), und dein Schutzmechanismus — nur Features zu benennen, die Gladys noch nicht kennt — ist der richtige. Aber das Veröffentlichen einer id im Discovery-Payload entspricht nicht der Spezifikation externer Integrationen: Das funktioniert heute, weil nichts es validiert, und ich will nicht, dass es zu einem impliziten Vertrag wird.
Ich werde also addEnergyFeatures() (das von Zigbee2mqtt/Tasmota) auf externe Integrationen in getDiscoveredDevices anwenden: Jede Integration, die einen Index veröffentlicht, erhält automatisch das 30-Minuten-Paar, IDs und Links werden vom Core verwaltet. Halte deinen Code gut isoliert (featureUuid.js + der Block in buildDevice), damit du ihn entfernen kannst, wenn es verfügbar ist.
Der Link:
Und zwei Details:
- Die Stufe
energydeiner Fähigkeits-Skala ist nutzlos:energy_parent_idkam im August 2025 in Gladys, lange vor den externen Integrationen. Jede Instanz, die deinen Container ausführen kann, hat bereits die Energieverfolgung. - „Energie diesen Monat“ und „Energie dieses Jahr“ müssen auf 0 bleiben, das ist normal und sie sollten auf keinen Fall verknüpft werden: Sie sind ebenfalls als
energytypisiert, daher erscheinen sie als mögliche Eltern in Einstellungen → Energieverfolgung, und ein Benutzer, der sie verkabelt, würde die gleichen kWh mehrmals zählen. Eine Zeile in der Dokumentation mit „Verknüpfen Sie nur den Tagesverbrauch“ würde die Frage vermeiden.
Kurz gesagt: Go für die Produktion, und ich kümmere mich um Punkt 3 auf der Core-Seite.