Commit Graph
59 Commits
Author SHA1 Message Date
retr0andClaude Sonnet 5 8f5106e3a0 ShineBridge v1.12.0 — Feature: Prognosebasierter Zwangslade-Timeout (Open-Meteo)
Neuer Standort-Bereich im Einstellungen-Tab (Breitengrad/Längengrad, optional,
site-weit statt pro Gerät). Neues Modul weather_forecast.py fragt Open-Meteos
kostenlose stündliche Solarstrahlungs-Prognose (shortwave_radiation, 48h
voraus, timezone=auto) ab, gecacht alle 3h.

adjusted_timeout_h() passt den Zwangslade-Timeout adaptiv an:
- bald nennenswerte Sonne zu erwarten (naechste 3h) -> Timeout verlaengern
  (x1.75, gedeckelt auf Basiswert+4h)
- auch im 12h-Fenster keine nennenswerte Sonne zu erwarten -> Timeout
  verkuerzen (x0.5, min. 0.5h) statt sinnlos den vollen Timeout abzuwarten
- ohne Standort (lat/lon leer): unveraendertes Verhalten, Feature ist Opt-in

EmsController.update() bekommt einen neuen optionalen timeout_override_h-
Parameter statt selbst Standortdaten zu kennen — Wetter-Logik bleibt im
Poll-Loop, EmsController fokussiert auf die eigentliche Lade-Steuerung.

Auf Sonnenstand-Berechnung bewusst verzichtet — die stuendliche Strahlungs-
prognose bildet Tag/Nacht-Verlauf implizit schon ab, eigene Ephemeriden-
Berechnung waere doppelte Arbeit ohne Mehrwert.

Teil 2 von 2 des 'Prognosebasiertes Laden'-Roadmap-Punkts, damit komplett.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 15:57:04 +02:00
retr0andClaude Sonnet 5 202759cc84 ShineBridge v1.11.2 — Feature: PV-Überschuss batteriebewusst berechnen
_get_pv_surplus() zieht jetzt die aktuelle Batterie-Entladeleistung vom
Netzexport ab, bevor er als PV-Überschuss fürs Auto verwendet wird. Verhindert,
dass PV-Überschussladen bei bewölktem Wetter versehentlich den Hausspeicher
anzapft, wenn der Export eigentlich aus der Batterie statt frischer PV-Produktion
kommt. Betrifft nur PV-Überschussladen — Zwangsladen bleibt bewusst unverändert
netzbasiert. Anlagen ohne Batterie (bat_discharge_power fehlt) verhalten sich
unverändert wie zuvor.

Teil 1 von 2 des 'Prognosebasiertes Laden'-Roadmap-Punkts — Teil 2
(Wetterprognose + Sonnenstand) folgt als eigener Schritt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 15:41:41 +02:00
retr0andClaude Sonnet 5 b7dc008cd7 ShineBridge v1.11.1 — Feature: Backup-Verwaltung im Einstellungen-Tab
Neue Sektion 'Automatische Backups':
- Aufbewahrung (Tage) konfigurierbar statt hartcodierter 14 Tage
  (config_backup_retention_days, Teil der normalen Config-Persistenz)
- Liste aller vorhandenen Backups (Datum, Größe), neueste zuerst
- Download-Button pro Backup
- Wiederherstellen-Button pro Backup (mit Bestätigungsdialog, da überschreibend)

Backend: Validierung+Anwendung aus /api/import-config in _apply_import_data()
extrahiert, von Datei-Upload und neuem Backup-Restore-Endpunkt gemeinsam
genutzt. Neue Endpunkte GET /api/config-backups, GET .../download,
POST .../restore — mit Path-Traversal-Schutz (_safe_backup_filename, nur
Dateinamen aus dem Backup-Ordner selbst).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 12:27:00 +02:00
retr0andClaude Sonnet 5 3318d1344d ShineBridge v1.11.0 — Feature: automatisches tägliches Config-Backup nach /share
Neuer Daemon-Thread (gleiches Muster wie der History-Cleanup-Thread) schreibt
täglich einen Config-Export nach /share/shinebridge-backups/ — bewusst nicht
nach /data, da genau dieser Ordner bei Add-on-Uninstall+Reinstall gelöscht
wird (siehe Vorfall 2026-08-25). Export sofort beim Start plus alle 24h,
14 Tage Aufbewahrung mit automatischem Cleanup alter Dateien.

Export-Datenaufbau aus /api/export-config in _build_export_data() extrahiert,
von Endpoint und Scheduler gemeinsam genutzt. Neue Berechtigung map: share:rw
in config.yaml.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 10:52:52 +02:00
retr0andClaude Sonnet 5 789e25967a ShineBridge v1.10.3 — Fix: HA-Entity-Anbindung auf Long-Lived Token umgestellt (host_network verhindert SUPERVISOR_TOKEN)
homeassistant_api: true funktioniert nicht, solange host_network: true gesetzt
ist — der Container ist dann nicht im internen Supervisor-Netzwerk und bekommt
keinen SUPERVISOR_TOKEN injiziert (bestätigt per Diagnose-Log: keine TOKEN/
SUPERVISOR/HASSIO-Env-Var im Container vorhanden).

Statt host_network anzufassen (Risiko für Modbus/Goodwe-UDP): HAEntityReader
nutzt jetzt ein normales, manuell in HA erstelltes Long-Lived Access Token
gegen http://localhost:8123/api — funktioniert dank host_network direkt ohne
Umweg über den Supervisor-Proxy. homeassistant_api wieder aus config.yaml
entfernt (unnötig).

Neue Felder im Geräte-Dialog: 'Home Assistant URL' (Default localhost:8123)
und 'Long-Lived Access Token'.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 16:26:57 +02:00
retr0andClaude Sonnet 5 1b78857b3d ShineBridge v1.10.1 — Fix: Config-Import scheiterte an Geräten ohne modbus_ip (ha_entity-Typ)
/api/import-config verlangte bisher zwingend modbus_ip fuer jedes Geraet in der
importierten Config — der neue GROWATT_WIFI_X-Typ (ha_entity) hat aber keins,
nutzt stattdessen ha_entity_prefix. Import schlug dadurch mit 400 fehl, sobald
so ein Geraet enthalten war. Validierung jetzt protokollabhaengig.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 16:11:13 +02:00
retr0andClaude Sonnet 5 6f30fe6b1c ShineBridge v1.10.0 — Neuer Geräte-Typ: Growatt ShineWifi-X über bestehende HA-Entity (ESPHome)
Statt selbst per Modbus/UDP zu pollen, kann ShineBridge jetzt einen Wechselrichter
einbinden, der bereits per ESPHome nativ in Home Assistant läuft — nützlich für
die ShineWifi-X-Variante, die keine eigene Modbus-TCP-Schnittstelle hat.

- Neuer ha_entity_client.py: liest Sensor-Werte über die interne Supervisor-API
  (http://supervisor/core/api), braucht dafür 'homeassistant_api: true' in
  config.yaml (neu gesetzt — Add-on muss dafür einmal neu installiert werden)
- Neuer Geräte-Typ 'GROWATT_WIFI_X' in inverters.py, protocol='ha_entity'
- Feste Suffix-Zuordnung (dcpower→pv_power, acpower→ac_power, energytoday→
  energy_today, ...) passend zur esphome-growatt-Komponente aus
  growatt-diagnose-tool/ShineWifi-X — Entity-Id ergibt sich als
  sensor.<prefix>_<suffix>
- Neues Feld 'HA Entity-Prefix' im Geräte-Dialog statt Modbus-IP/Port/Adresse,
  blendet sich abhängig vom gewählten Gerätetyp ein/aus
- Läuft danach durch dieselbe Aggregations-/Dashboard-Logik wie jedes andere
  Gerät (kein Sonderfall in EMS/Finanzen nötig, da Netzbezug bereits über den
  bestehenden Zähler erfasst wird — dieser Wechselrichter liefert nur PV-Werte)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 14:28:45 +02:00
retr0andClaude Sonnet 5 eb797ed8b7 ShineBridge v1.9.0 — Fokus auf Energiemanagement: Flash/OTA + Setup-Wizard ausgelagert
Repositionierung: ShineBridge macht ab jetzt eine Sache gut (Energiemanagement),
statt alles zu versuchen. Flash/OTA-Firmware-Update fürs ShineLAN-X und der
Ersteinrichtungs-Wizard sind kein Energiemanagement-Feature und wandern ins neue,
eigenständige Projekt 'growatt-diagnose-tool'.

- 4 Flash/OTA-Endpunkte aus main.py entfernt (probe/firmware/update/reboot)
- Flash-Tab, Flash-Panel und zugehöriges CSS/JS aus index.html entfernt
- Setup-Wizard-Overlay entfernt — Geräte werden über '+ Gerät hinzufügen' im
  Geräte-Tab angelegt (Button existierte bereits unabhängig vom Wizard)
- firmware/-Ordner (ShineLAN-X .bin-Dateien) entfernt, liegt jetzt im neuen Repo
- Dockerfile: COPY firmware/ entfernt
- Bugfix dabei gefunden: switchTab() referenzierte noch den entfernten
  'flash'-Tab per Index — hätte die Tab-Reihenfolge durcheinandergebracht

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 13:14:12 +02:00
retr0andClaude Sonnet 5 f5ed7c5df6 ShineBridge v1.8.31 — EMS-Fixes: konfigurierbarer Max-Ladestrom, Zwangsladen-Retry, Fault-State-Handling
- ems_max_current_ma konfigurierbar statt hardcoded 32A (Zwangsladen darf jetzt nicht mehr
  mehr fordern als die tatsächliche Wallbox liefern kann, z.B. 16A bei einer 11kW-Wallbox)
- Zwangsladen setzt den Ladestrom bei jedem Poll erneut (statt nur einmal beim Start) —
  ein einzelner fehlgeschlagener Modbus-Write hängt nicht mehr die ganze Nacht
- Unbekannte/Fehler-Ladezustände (z.B. Fahrzeug-Störung) werden nicht mehr wie 'abgesteckt'
  behandelt — Strom wird pausiert, aber der Zwangslade-Timer bleibt erhalten
- Neues Settings-Feld 'Max. Ladestrom (A)' im EMS-Dialog

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 12:46:59 +02:00
retr0andClaude Sonnet 4.6 b36b0194f7 ShineBridge v1.8.30 — Ingress-Fix: Flask wieder auf 0.0.0.0
127.0.0.1 brach HAOS Ingress (Proxy kommt von außerhalb localhost).
Sicherheit bleibt gewahrt: kein ports:-Eintrag in config.yaml,
Port 8099 wird nicht ans Host-Netz gemappt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 16:04:15 +02:00
retr0andClaude Sonnet 4.6 04a8fb3125 ShineBridge v1.8.29 — Port 8099 nur auf localhost binden
Flask bindet auf 127.0.0.1 statt 0.0.0.0. Mit host_network: true war Port
8099 direkt vom LAN erreichbar. HAOS-Ingress verbindet sich über localhost,
daher kein Funktionsverlust.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-26 15:23:01 +02:00
retr0andClaude Sonnet 4.6 c4047fc804 fix(v1.8.27): Fahrzeugerkennung + Wizard überschreibt Inverterliste
Bug 1 (inverters.py): Kathrein-Register 0x0061-0x0064 existieren nicht —
(0x0060, 10) schlug daher immer mit IllegalAddress fehl, charging_state
wurde nie gelesen → EMS meldete dauerhaft "kein Fahrzeug". Fix: aufgeteilt
in (0x0060, 1) + (0x0065, 6), sodass die Lücke übersprungen wird.

Bug 2 (index.html): wizardStep2Next() postete [neues_gerät] statt
[...invertersList, neues_gerät] → überschrieb die gesamte Inverterliste.
Wenn der Wizard bei einem bestehenden Setup erschien, flogen alle anderen
Geräte raus. Fix: bestehende Geräte werden beibehalten.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 10:58:44 +02:00
retr0andClaude Sonnet 4.6 5564a50c3c fix(ems): Zwangsladen-Countdown läuft ohne angestecktes Auto
Kathrein Reg 0x0060 liefert IllegalAddress wenn kein Fahrzeug angeschlossen.
Default war 1 (STATE_CONNECTED) → EMS nahm Auto als verbunden an → Countdown.

IllegalAddress ist kein sporadischer Lesefehler, sondern das definierte Signal
der Wallbox für "kein Fahrzeug". Default auf 0 (STATE_IDLE) → EMS kehrt sofort
zu "kein Fahrzeug" zurück, _no_pv_since-Timer wird nicht gestartet.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 10:12:35 +02:00
retr0andClaude Sonnet 4.6 dc2df891fb fix: TCP-Timeout auf 40% des Poll-Intervalls begrenzt (max. 5s)
Logs zeigen: Bei 10s Poll-Rate + 10s TCP-Timeout läuft ein fehlgeschlagener
Connect exakt so lange wie das Interval. stop.wait() wird 0 → nächster Poll
startet sofort → zweite parallele TCP-Verbindung → Wallbox überfordert → Spirale.

Fix: timeout = min(5.0, interval * 0.4). Bei 15s → 5.0s Timeout; bei 10s → 4.0s.
Ein Fehler belegt max. 40% des Intervalls, der Rest ist Wartezeit vor dem nächsten Versuch.
Gilt für WallboxReader (Kathrein) und ModbusReader (ShineLAN-X / SDM-630).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 10:08:59 +02:00
retr0andClaude Sonnet 4.6 a361c30f1b fix: Offline-Flapping — erst nach 3 aufeinanderfolgenden Lesefehlern offline
Ein einzelner UDP-Paketverlust (Goodwe) oder TCP-Timeout (Modbus) hat sofort
MQTT-Status "offline" getriggert. Bei 10s Poll-Rate reicht ein Ausreißer.

Fix: _fail_count pro Poll-Loop, OFFLINE_THRESHOLD=3. Erst wenn 3 Reads in Folge
scheitern (≥30s bei 10s Interval) wird offline publiziert. Erfolg resettet
den Zähler auf 0 und stellt online sofort wieder her.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 09:58:48 +02:00
retr0andClaude Sonnet 4.6 a9f33c8e9e fix(goodwe): Netzbezug-Periode zeigt 0 kWh — integrierter grid_power-Zähler
e_total_imp vom Goodwe-WR ist ein Lifetime-Zähler seit Inbetriebnahme.
Beim ersten Verbinden speichert save_period_start_if_new() den aktuellen
Wert als Periodenstart → Delta = 0.

Fix: _int_import/_int_export werden je Poll-Zyklus aus grid_power integriert
(W × dt / 3.600.000 → kWh), in der measurements-DB persistiert und
beim Neustart aus der DB wiederhergestellt. AGG_SENSOR_IDS bevorzugt nun
_int_import vor e_total_imp, SDM-630 (import_kwh) bleibt erste Wahl.
Private Keys (Prefix _) werden nicht an MQTT gepublished.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-07 09:55:24 +02:00
retr0andClaude Sonnet 4.6 512b743b16 Fix: Stromtarif-Einstellungen nach Neustart verloren + Finanzen-Layout (v1.8.22)
State.mqtt_cfg wurde beim Start nur mit 4 MQTT-Keys initialisiert — alle
Tarif/Billing-Keys fehlten, wurden nach Neustart auf Defaults zurückgesetzt.
Fix: alle persistenten Keys aus load_config() in State.mqtt_cfg übernehmen.

Finanzen-Tab: mehr Abstände, größere Karten (22px Wert), Abschnittsüberschriften,
Trennlinie vor dem Chart.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 08:26:52 +02:00
retr0andClaude Sonnet 4.6 7904d498b5 v1.8.20: Fix Eigenversorgungskarte + Stromtarif-Einstellungen verloren
Bug 1 — Eigenversorgungskarte verschwindet wenn PV offline:
- savings_kwh wird jetzt gesetzt wenn pv_total vorhanden (grid_exp muss
  nicht mehr explizit vorhanden sein, default 0.0)
- Karte bleibt sichtbar auch wenn Wechselrichter offline geht

Bug 2 — Stromtarif-Einstellungen gehen beim Speichern verloren:
- savePrices(): parseInt mit || 1 Fallback, verhindert NaN → JSON-null
- api_save_config(): None-Checks + try/except für alle numerischen Keys,
  save_config() wird garantiert immer aufgerufen

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:25:01 +02:00
retr0andClaude Sonnet 4.6 15c0ede72e v1.8.18: MQTT rc=5 Fehlerhandling, Port-Absicherung, Flash-Wizard + NuttX OTA
MQTT:
- rc=5 (Not Authorized) stoppt Reconnect-Loop via _auth_failed Flag
- Fehlermeldung im MQTT-Einstellungen-Banner sichtbar

Sicherheit:
- /api/* nur über HAOS-Ingress (X-Ingress-Path) oder Loopback erreichbar

Flash-Wizard (Baustelle B):
- Neuer Tab "Flash" mit IP-Eingabe und OTA-Modus-Erkennung
- OTA: integrierte oder eigene Firmware via POST /api/flash/update auf Stick
- Fortschrittsbalken + Polling bis Stick nach Reset wieder online
- ST-Link-Erstflash-Anleitung (Pinout, st-flash Kommando)
- Firmware-Binaries im Docker-Image unter /firmware/

NuttX OTA (Baustelle A, shinelanx-modbus):
- ota_http.c: Zwei-Phasen OTA für STM32F103 Single-Bank Flash
  Stage 1: Firmware in Staging-Bereich (obere Flashhälfte) schreiben
  Stage 2: .ramfuncs aus SRAM heraus — Staging → App-Bereich kopieren, Reset
- ota_http.h, Makefile und main.c entsprechend erweitert
- ld.script.dfu: .ramfuncs in .data Section → Ausführung aus SRAM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 19:45:40 +02:00
retr0andClaude Sonnet 4.6 bbfb11fb9c v1.8.17: Atomarer Config-Write + Backup-Fallback
Verhindert Datenverlust wenn HAOS den Container während eines Saves
stoppt. Schreibt erst config.json.tmp, dann atomares os.replace().
Hält config.json.bak als Fallback für den nächsten Start.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:40:56 +02:00
retr0andClaude Sonnet 4.6 2456f356b4 v1.8.16: Finanzen-Tab — Festpreis vs. Spot-Vergleich
Täglicher Tarif-Tracking: kWh + EPEX-Ø-Preis werden ab jetzt täglich
gespeichert. Neuer Finanzen-Tab zeigt Balkendiagramm (Festpreis vs.
Spot hypothetisch), Summen-Karten und Empfehlung ob flexibler Tarif
sich lohnen würde.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:29:55 +02:00
retr0andClaude Sonnet 4.6 dfb42e6902 v1.8.15: Abschlags-Tracker zeigt ganze Zahlungen statt Bruchmonate
Berechnung auf geleistete Abschlagszahlungen umgestellt:
Anzahl ganzer Monate seit Abrechnungsstart statt Tage/30.4.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 13:12:43 +02:00
retr0andClaude Sonnet 4.6 fec49ec4fb v1.8.14: Abschlags-Tracker (monatliche Rate + Grundpreis)
Neues optionales Feature: Abschlags-Übersicht im Energie-Dashboard.
Zeigt Bereits bezahlt, Grundpreis anteilig, Energiekosten sowie
voraussichtliche Nachzahlung oder Guthaben für das laufende Abrechnungsjahr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 11:45:56 +02:00
retr0andClaude Sonnet 4.6 0dbf0266a8 fix: _get_pv_surplus() via grid_power-Aggregat (SDM-630 fix, v1.8.11)
SDM-630 liefert grid_power (negativ=Einspeisung), wurde von active_power-
Logik nicht erfasst. Jetzt einheitlich über grid_power-Aggregat.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 11:42:08 +02:00
retr0 58a33f966d debug: surplus_w in API + Live-Tab anzeigen 2026-05-04 11:31:06 +02:00
retr0andClaude Sonnet 4.6 10e21f031a v1.8.9: Z2M Geräte-Dropdown für Überschuss-Steuerung
- MQTT Subscribe auf zigbee2mqtt/bridge/devices beim Connect
- Neuer Endpoint GET /api/z2m-devices liefert Friendly Names + Beschreibung
- Eingabefeld für Z2M Name als Datalist-Combo (tippen oder aus Liste wählen)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 10:57:52 +02:00
retr0andClaude Sonnet 4.6 83035fed0e v1.8.8: Überschuss-Geräte (Zigbee2MQTT) + Bugfix Eigenversorgungskarte
- Neu: SurplusDeviceController — schaltet Z2M-Geräte bei PV-Überschuss
  ein/aus (Schwellwert + Hysterese pro Gerät, Background-Loop 30s)
- Neu: API GET/POST /api/surplus-devices, Konfig persistent in config.json
- Neu: Settings-Tab "Überschuss-Geräte", Live-Tab zeigt ON/OFF-Status
- Bugfix: Eigenversorgungskarte (Monat/Jahr) bleibt abends sichtbar wenn
  Wechselrichter offline — letzte kWh-Zähler werden als Fallback genutzt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-04 10:53:46 +02:00
retr0andClaude Sonnet 4.6 4242ca01f6 Feature: EMS Aktiv-Checkbox pro Kathrein-Wallbox-Gerät (v1.8.4)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:53:39 +02:00
retr0andClaude Sonnet 4.6 3ab74a8c21 Fix: Eigenverbrauch = PV_gesamt − Einspeisung statt nur Batterie-Entladung (v1.8.3)
Vollständige Formel: total_energy_total - grid_export_kwh deckt
Direktverbrauch (PV→Haus) + Batterie-Umweg (PV→Bat→Haus) ab.
Fallback auf bat_discharge_total wenn kein PV-Zähler verfügbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:48:02 +02:00
retr0andClaude Sonnet 4.6 3762abd632 Feature: Eigenversorgungs-Ersparnis in Perioden-Karten (v1.8.2)
- bat_discharge_total + bat_charge_total werden jetzt als Perioden-Starts getrackt
- savings_kwh = Batterie-Entladung der Periode (→ Haus + Auto)
- savings_eur = savings_kwh × effektiver Importpreis (Festpreis oder Börsendurchschnitt)
- Neue Karte "Eigenversorgung" (lila) neben Netzbezug/Einspeisung
- Preis-Refaktor: eff_price für Import, Export, Ersparnis aus einer Berechnung

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:38:56 +02:00
retr0andClaude Sonnet 4.6 ec26782765 Feature: Flexibler Stromtarif (Börsenstrom) in Einstellungen + Periodenabrechnung (v1.8.1)
- Tarifart: Festpreis / Flexibel (Börsenstrom) — Radio-Toggle in Einstellungen
- Flexibel: Aufschlag (ct/kWh) + Land (DE/AT) konfigurierbar
- /api/period-energy: bei tariff_type=spot → historische aWATTar-Preise, 1h Cache
- Kostenrechnung Monat/Jahr: Ø Börsenpreis + Aufschlag statt Festpreis
- Periodenkarte zeigt "Ø X.X + Y.Y ct/kWh" bei Börsentarif
- Spot-Chart-Toggle in Einstellungen (spot_chart true/false)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:27:55 +02:00
retr0andClaude Sonnet 4.6 526e802c74 Feature: Börsenstrompreis-Chart (EPEX SPOT via aWATTar) im Energie-Dashboard (v1.8.0)
- /api/spot-price: Proxy zu api.awattar.de/v1/marketdata, 15-min Cache
- EUR/MWh → ct/kWh Konvertierung
- SVG-Balkenchart 24h-Prognose, gleiche Breite wie Flussdiagramm (viewBox 520)
- Farbe nach Preistertil: grün/gelb/rot; aktuelle Stunde hervorgehoben
- Aktuellen Preis als ct/kWh-Label in der Kopfzeile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:15:52 +02:00
retr0andClaude Sonnet 4.6 f96d798274 Revert: SPH Energiebilanz-Ableitung entfernt — Problem war Goodwe pbattery1 (v1.7.7)
Die Growatt SPH Register 1009/1011 liefern korrekte Werte.
Die Ableitung via ac_power_total war unnötig und fehleranfällig.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 08:02:59 +02:00
retr0andClaude Sonnet 4.6 9ff0b2e971 Fix: SPH Batterie-Leistung aus Energiebilanz statt Register 1009/1011 (v1.7.5)
Register 1009 (bat_discharge) liefert beim SPH im Lademodus falsche Werte.
Neue Ableitung: bat_net = pv1+pv2 + power_to_user - power_to_grid - ac_power_total
Alle vier Quellen sind direkt gemessene, verlässliche Register.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 07:58:51 +02:00
retr0andClaude Sonnet 4.6 3ccf11771d Fix: Growatt SPH bat_charge/discharge Messartefakt — nur dominanter Wert bleibt (v1.7.4)
Growatt SPH rapportiert beide Register gleichzeitig als > 0 (physikalisch unmöglich).
Fix: bat_discharge_power = 0 wenn bat_charge_power >= bat_discharge_power, sonst umgekehrt.
Verhindert falschen Hausverbrauch durch doppelt gezählte Batterieleistung.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 07:50:07 +02:00
retr0andClaude Sonnet 4.6 13de5ff976 Fix: Energie-Dashboard Nodes größer (R=56), Labels aus API, Abrechnungsperiode konfig. (v1.7.1)
- SVG-Nodes: Radius 44 → 56, Icon 22 → 26px, Abstände neu berechnet
- Segment-Pfade an neue Positionen angepasst (40px Abstand Kante→Kante)
- period.monthly.label / yearly.label statt hardcoded "Diesen Monat" / "Dieses Jahr"
- billing_day/billing_month: history.period_key(), /api/period-energy, Settings-UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 07:35:48 +02:00
retr0andClaude Sonnet 4.6 e9ca2fcc7d Feature: Abrechnungsperiode + Strompreise im Energie-Dashboard (v1.7.0)
- history.py: Tabelle period_starts — speichert kWh-Zählerstand zu Monats-/Jahresbeginn
- main.py: price_import/price_export in Config; /api/period-energy Endpoint
- Web UI: Preisfelder in Einstellungen (€/kWh Bezug + Vergütung)
- Energie-Dashboard: Cards zeigen Monat/Jahr kWh + Kosten statt All-Time-Total

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 22:37:09 +02:00
retr0andClaude Sonnet 4.6 ef9f96e5d2 Fix+Redesign: Energie-Dashboard SVG-Icons + SDM-630 Aggregation (v1.6.1)
- SVG-Pfad-Icons statt Emoji (Solar, Netz, Haus, Batterie, Wallbox)
- Bezier-Kurven statt gerader Linien für Flussverbindungen
- Rounded-Rect Knoten mit farbigem Top-Border bei kWh-Karten
- SDM-630 grid_power Proxy: total_power -> grid_power (erkannt via import_kwh)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 21:42:12 +02:00
retr0andClaude Sonnet 4.6 cc4777b22f Fix: grid_power Aggregat korrekt für Multi-Wechselrichter-Anlagen
- AGG_FIRST: grid_power wird nicht summiert sondern erste Messung genommen
  (Goodwe CT-Klemme misst bereits Gesamt-Netzleistung inkl. Growatt)
- Growatt-Proxy: grid_power = -power_to_grid wenn kein Grid-Meter vorhanden
  (Growatt-only: Einspeisung korrekt, Netzbezug nicht messbar)
- Goodwe + Growatt: Goodwe-Wert hat Vorrang durch Gerätereihenfolge

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:28:24 +02:00
retr0andClaude Sonnet 4.6 5765f54ebd Fix: Aggregat grid_power nur aus Goodwe grid_power (nicht Wallbox total_power)
- AGG_SENSOR_IDS: grid_power → ["grid_power"] statt ["total_power","active_power"]
  Kathrein total_power = Ladeleistung, nicht Netzleistung
- _compute_aggregates: break nach erstem Match pro Gerät (kein Doppelzählen)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:24:15 +02:00
retr0andClaude Sonnet 4.6 ff428145f4 Fix: EMS Ladestrom = PV-Überschuss + aktuelle Wallbox-Leistung
Goodwe misst Überschuss NACH Wallbox-Verbrauch. EMS muss deshalb
bestehende Ladeleistung (total_power) addieren um Gesamtbudget zu kennen:
  new_current = (surplus + wallbox_power) / (230V × phases)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:22:57 +02:00
retr0andClaude Sonnet 4.6 ad89e1bc56 Fix: active_power Vorzeichen final korrekt (positiv = Einspeisung)
Goodwe ET Bibliothek: house_consumption = ppv + pbattery1 - active_power
→ active_power > 0 = Einspeisung (Überschuss), < 0 = Netzbezug.
Falsches Vorzeichen erzeugte Rückkopplungsschleife: mehr Bezug → mehr
scheinbarer Überschuss → noch mehr Laden.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:08:12 +02:00
retr0andClaude Sonnet 4.6 511cd30182 Revert: active_power Vorzeichen zurück (positiv = Netzbezug)
Goodwe ET: active_power > 0 = Netzbezug, < 0 = Einspeisung.
Original-Logik war korrekt — EMS-Problem lag am charging_state Default.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 13:03:46 +02:00
retr0andClaude Sonnet 4.6 3519a02370 Fix: Goodwe ET active_power Vorzeichen für PV-Überschuss korrigiert
Goodwe ET liefert active_power > 0 bei Einspeisung (nicht negativ).
Falsche Negierung führte zu PV-Überschuss = 0 → EMS lud nie.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 12:53:12 +02:00
retr0andClaude Sonnet 4.6 d1f47177fc Fix: EMS aktiviert sich auch ohne lesbare charging_state (0x0060)
- charging_state Default 0→1 (EV Connected) wenn Register nicht lesbar
- EMS-Status auf INFO hochgestuft inkl. PV-Überschuss

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 12:26:15 +02:00
retr0andClaude Sonnet 4.6 a09bbdd25d Feature: EMS-Konfiguration im Web-UI (v1.5.1)
- Modal zeigt EMS-Felder nur bei KATHREIN_WALLBOX (toggleEmsSection)
- openModal lädt ems_min_pv/timeout/target_hour/phases aus Gerätekonfig
- saveInverter speichert EMS-Parameter in inverters.json
- main.py übergibt EMS-Konfig aus inv_cfg an EmsController()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 12:11:13 +02:00
retr0andClaude Sonnet 4.6 ac965dcfa6 Feature: Kathrein Wallbox + EMS-Controller (v1.5.0)
- wallbox_client.py: WallboxReader FC03, EMS enable/set_current
- ems_controller.py: PV-Überschussladen + 4h-Timeout Zwangsladen bis 06:00
- inverters.py: KATHREIN_WALLBOX mit 18 Sensoren (Meter + EVSE + EMS)
- main.py: kathrein-Protokollzweig, _get_pv_surplus() aus laufenden Geräten

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 12:02:59 +02:00
retr0andClaude Sonnet 4.6 8b65666e80 Fix: Goodwe SOC-Key battery_soc + battery_soh/temperature ergänzt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 11:42:42 +02:00
retr0andClaude Sonnet 4.6 bc92db6c18 Feature: Goodwe GW10KN-ET Support via goodwe UDP/8899
- goodwe_client.py: GoodweReader wraps goodwe library (asyncio → sync)
- inverters.py: GW10KN_ET mit 37 ET-Sensoren, protocol=goodwe_udp
- main.py: poll-loop verzweigt auf GoodweReader bei goodwe_udp-Geräten;
  AGG_SENSOR_IDS um Goodwe-Keys erweitert (ppv, soc, e_total, e_total_imp/exp, …)
- requirements.txt: goodwe==0.4.10 hinzugefügt

Goodwe-Stick (WIFILAN_2.0 v2.4.41) hat eFuse-gesperrten ROM-Download;
Kommunikation erfolgt über WiFi-Stick-IP + UDP-Port 8899.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 10:36:51 +02:00
retr0andClaude Sonnet 4.6 6ae2cbf2b2 Feature: Konfig-Export/Import im Web UI (Einstellungen-Tab)
- GET /api/export-config → JSON-Download mit allen Geräten + MQTT (ohne Passwort)
- POST /api/import-config → Validierung + Übernahme + automatischer Neustart
- Einstellungen-Tab: Exportieren-Button + Importieren-Dateiauswahl
- btn-secondary CSS-Klasse hinzugefügt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 13:06:54 +02:00