Repository navigation
Peak Shaving: Batterie bei Stopp, HA-Neustart und Ausfall zuverlässig zurückgeben (Review D4, D3, B3, E9, B13, B20) - #82
Merged
Conversation
…elesene Entitaeten werden nicht geschrieben (Review D4) Ein haengendes Home Assistant verlaengerte den Zyklus um einen Timeout je Aufruf (Energiesensor, Sollwert, Ladeleistung, Marstek-Entitaeten, EEG-Zaehler: 40 s und mehr). Der Waechter im Transport der gemeinsamen Verbindung (core/site_ha_guard.go) lehnt nach dem ersten Timeout die weiteren Aufrufe des Zyklus ab, am Ende des Zyklus (updateBatteryModePeakAware) fragt der naechste wieder. Der EEG-Zaehler wird nach einem eigenen Timeout eine Minute nicht gelesen. numberSetter und omniSwitchOff schreiben nach einem Lesefehler nicht mehr blind, sondern geben den Fehler zurueck; die Freigabe versucht es im naechsten Zyklus erneut und behaelt solange, was evcc haelt. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s Freigabe (Review D3) omniRead und numberState melden unknown/unavailable wie GetState als api.ErrNotAvailable. Dann wird nicht geschrieben (Home Assistant antwortet mit 200 und tut nichts), peakShavingOwned und peakShavingProtOwned bleiben gesetzt, und die Freigabe wird im naechsten Zyklus wiederholt, auch waehrend Home Assistant startet und die Entitaeten noch nicht kennt. Nur ein Schalter, den Home Assistant gar nicht kennt (404), gilt als aus, sonst blockierte die Freigabe jede Aenderung der Entitaeten. fakeHA kennt jetzt nicht verfuegbare und fehlende Entitaeten. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Beim Stoppen gab evcc nur seinen Batteriemodus zurueck. Was der Fork ueber Home Assistant haelt, blieb bis zum ersten Zyklus nach dem naechsten Start: Marstek mit Ladeleistung und Handsteuerung (Netzladen bis voll ohne Peak-Gate), das Limit von Omnibatterys Peak Shaving auf dem letzten Fensterwert, BYD mit Sollwert und Ladeleistung. Eine Shutdown-Funktion (aus restorePeakSettings, in core/site_peak_shutdown.go, kein neuer Upstream-Hook) setzt ein Flag, gegen das der noch laufende Zyklus nichts mehr schreibt, und gibt in der Reihenfolge Sicherheit zuerst zurueck: Marstek Ladeleistung 0 und Handsteuerung aus, Omnibattery behaelt Peak Shaving mit dem Peak-Limit, BYD Ladeleistung 0 und freier Wert. Best Effort in hoechstens 8 s, blockiert den Stopp nicht; was nicht ankommt, bleibt als gehalten markiert. Abgelehnte Aufrufe waehrend des Stopps (Supervisor meldet 400/503 not ready) stehen als info im Log. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
settings.SetBool merkt sich einen Wert nur im Speicher, in die Datenbank kommt er mit dem Minuten-Takt oder beim Stopp. Ein Absturz in der ersten Minute nach der Uebernahme verlor peakShavingOwned und peakShavingProtOwned, die Batterie wurde nach dem Neustart nicht mehr zurueckgegeben. setPeakOwned und setProtOwned speichern bei einer Aenderung sofort; ein Fehler dabei wird einmal je Ursache geloggt. Die Tests lesen die Zeilen aus der Datenbank (SQLite im Speicher) und werden ohne den Aufruf rot. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Der Aufruf stand am Ende von evccs restoreSettings, hinter neun fruehen Returns. Scheitert ein Restore-Schritt von evcc (oder ein kuenftiges neues return err), lud nichts vom Fork: Peak Shaving still aus, kein Kreis, eine gehaltene Batterie wurde nie zurueckgegeben. Der Hook steht jetzt als defer direkt hinter der Pruefung fuer Tests, die alte Zeile entfaellt. Neuer Vertragstest TestForkDeferHooks prueft per Syntaxbaum, dass restoreCustom ein defer im Funktionsrumpf ist und kein evcc-Return davor steht (vor der Aenderung rot). Tabelle und Kommentar angepasst. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…bten Wert (Review B20) Das Fenster mit dem erlaubten Wert wird nur in einem Zyklus mit Zaehlerwerten erneuert. Faellt der Zaehler am Ende eines Fensters aus, behielt Omnibattery bis zum Zaehlerausfall (2 min) den im alten Fenster eingefrorenen Wert, bis zum Doppelten des Limits. applyOmniProtection nimmt Allowed jetzt nur, wenn das Fenster das laufende ist, sonst das Peak-Limit wie bei Zaehlerausfall. Test mit Allowed 7000, Uhr ueber der Grenze und ohne Zaehlerwerte (ohne die Aenderung rot). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Der Wächter lehnt nach einem Timeout alle Aufrufe ab, bis der Zyklus endet. Die Shutdown-Funktion läuft neben dem Zyklus: lief dessen erster HA-Aufruf in einen Timeout, bekamen Ladeleistung, Schalter und Sollwert der Rückgabe errHAHung, und logWrite schrieb das nur auf TRACE. Die Batterie blieb gehalten, ohne Zeile im Log, und das gerade bei langsamem Home Assistant. releasePeakOnShutdown sagt dem Wächter jetzt zuerst, dass evcc stoppt (haStop, baut die Verbindung bei Bedarf): er lehnt dann nichts mehr ab. logWrite prüft das Stoppen vor errHAHung, eine Verweigerung beim Stoppen steht auf INFO. Test mit einem Timeout im laufenden Zyklus für Marstek und BYD, Test für den Wächter einer erst beim Stoppen gebauten Verbindung. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… Marstek bleibt in manueller Steuerung Seit numberSetter bei jedem Lesefehler einen Fehler zurückgibt (statt blind zu schreiben), scheiterte die Freigabe an einer Ladeleistungs- oder Sollwert-Entität, die Home Assistant nicht kennt (gelöscht, umbenannt): Bei einem Marstek blieb die manuelle Steuerung im Modus Charge an und lud weiter aus dem Netz, in jedem Zyklus, beim Stoppen und bei Typ- oder Entitätswechsel (errHandBack). Bei BYD blockierte der Sollwert den Typwechsel. Das Konzept (D3) sieht vor, dass ein Lese-404 im Freigabepfad als freigegeben gilt, umgesetzt war es nur für Schalter. releaseOutput schreibt wie writeOutput, wertet einen 404 aber als zurückgegeben (WARN im Log). Es gilt für die Ladeleistung in releaseOmni, für releasePeak (Marstek und BYD), den BYD-Zweig von SetPeakShavingBatteryType und die Freigabe des alten Ziels in SetPeakShavingEntity. Jeder andere Fehler hält weiter fest. Die Reihenfolge Ladeleistung 0, dann Schalter aus bleibt: Omnibattery nimmt die Leistung nur in manueller Steuerung an (TestOmniGridChargeEndZeroFails). TestOmniEntityNotLoaded prüft jetzt eine nicht verfügbare statt eine fehlende Entität, der 404-Fall steht in TestOmniReleaseEntityGone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Behebt B3, D3 (hoch), D4, E9, B13, B20 aus dem Architektur-Review (Paket P4, Entscheidungen D6 und D7). Je Fund ein Commit, dazu zwei Commits aus dem Code-Review.
unavailable/unknownEntität zählt nicht mehr als Freigabe;ownedbleibt, die Freigabe wird nach der Rückkehr nachgeholt (live beim HA-Start beobachtet: 200 ohne Wirkung).ownedab.restoreCustomläuft alsdeferdirekt nach dem Test-Guard vonrestoreSettings, also auch wenn ein evcc-Restore-Schritt scheitert; Vertragstest per AST (Hook steht in einemdefer).Tests:
TestPeakReleasedOnShutdown,fakeHAmitunavailable, Test mit hängendem Transport (eine Anfrage je Ausgabe und Zyklus), Persistenz mit SQLite, AST-Vertragstest.wsltest.sh ./core/ ./core/peak/grün vor und nach den Fixes.Code-Review (Opus, mittel): zwei Funde mittel (behoben). Offen (niedrig): ein Timeout außerhalb des Zyklus sperrt den ganzen nächsten Zyklus. Bewusst nicht gebaut: Schalter auch ausschalten, wenn das Schreiben der Ladeleistung scheitert – widerspricht dem dokumentierten Ablauf (erst Leistung 0, dann Schalter aus;
TestOmniGridChargeEndZeroFails).Für das Add-on (CHANGELOG): Batterie wird beim Stoppen von evcc an Home Assistant zurückgegeben; nicht verfügbare Entitäten (z. B. beim HA-Start) werden nicht mehr als freigegeben gewertet; hängt HA, verzögert das die Regelung nur noch um einen Timeout. Add-on:
timeout: 30im Manifest, damit die Rückgabe vor dem Beenden fertig wird (eigener PR im Add-on-Repo, ohne Version-Bump).Hook-Änderung in
core/site.go(B13), Touch-Point-Tabelle undforkHooksangepasst. Überschneidung mit P3/P5 incore/site_peakshaving.go.🤖 Generated with Claude Code