"""Langfristige Aufzeichnung der 12V-Batteriespannung (Mein Audi -> Zustand -> Batteriespannung antippen). Eine über die Jahre absinkende Spannung deutet auf eine alternde Batterie hin - dafür braucht es einen Verlauf, nicht nur den aktuellen Wert. Ein Eintrag pro Tag ({datum, min, min_ts, max, max_ts}) reicht dafür und hält die Datei auch über viele Jahre klein, selbst wenn der Sensor mehrfach pro Stunde meldet (aktive Fahrt: Motor an/aus, Ladezustand des Alternators wechselt laufend). Die Prüfung läuft deshalb alle 5 Minuten und trägt jede Messung in den Tageseintrag ein; die Ablage erweitert dabei nur min/max samt dem genauen Zeitstempel der jeweiligen Extremmessung - robust gegen Neustarts und schwankende Erreichbarkeit. Der Tagesminimalwert ist die für die Entladung aussagekräftige Größe: er fällt typischerweise auf den Moment kurz nach dem Start, bevor der Alternator die Ladespannung hochfährt - also am nächsten an die "echte" Ruhespannung heran, ohne 2+ Stunden Standzeit abwarten zu müssen. Deshalb verwendet auch die Ladezustands-/Gesundheitsauswertung im Frontend (AGM_RUHE_MAX_V) den Tagesminimalwert, nicht den Maximalwert. Es wird bewusst NICHT gefiltert, welche Messwerte gespeichert werden - min UND max jedes Tages werden roh aufgezeichnet. Die AGM-Ruhespannungs-Grenze wird erst beim Anzeigen angewendet: Tage, an denen selbst der Minimalwert über der Grenze liegt (Fahrzeug nie im Ruhezustand beobachtet, z. B. bei einer sehr langen Fahrt), tauchen dort nicht in der Statistik auf. Ohne zugeordneten BATTERIE_SENSOR passiert hier bewusst nichts, statt Platzhalter-Nullwerte aufzuzeichnen. Optional wird bei jeder neuen Tagesminimum-Messung auch die aktuelle Außentemperatur (AUSSENTEMP_SENSOR, CAN ambient air temperature) mit aufgezeichnet - für die Messwertliste (Datum, Uhrzeit, Außentemperatur), nicht für die Ladezustandsauswertung selbst. Ohne zugeordneten Temperatursensor bleibt das Feld None, genau wie beim Batteriesensor. """ from __future__ import annotations import datetime import logging from typing import TYPE_CHECKING from .veroeffentlichung import zustand_oder_none if TYPE_CHECKING: from .koordinator import Koordinator _LOGGER = logging.getLogger(__name__) async def pruefen(k: Koordinator) -> None: sensor = k.zuordnung.werte.BATTERIE_SENSOR if not sensor: return wert = zustand_oder_none(k.hass, sensor) if wert is None: return try: spannung = float(wert) except (TypeError, ValueError): return aussentemp = None temp_wert = zustand_oder_none(k.hass, k.zuordnung.werte.AUSSENTEMP_SENSOR) if temp_wert is not None: try: aussentemp = float(temp_wert) except (TypeError, ValueError): pass jetzt = datetime.datetime.now(datetime.UTC) heute = datetime.date.today().isoformat() await k.ablage.batterieverlauf_tageswert_aktualisieren( heute, jetzt.isoformat(), spannung, aussentemp ) await k.batterieverlauf_veroeffentlichen() _LOGGER.debug("Batteriespannung erfasst (%s: %s V)", heute, spannung) async def eintrag_loeschen(k: Koordinator, datum: str | None) -> None: """Löscht einen Tageseintrag aus der Messwertliste (Wischen zum Löschen). Entfernt nur diesen einen Tag - min/max anderer Tage bleiben unberührt, das Diagramm zeichnet beim nächsten Aufruf einfach ohne diesen Punkt.""" if not datum: _LOGGER.warning("batterieverlauf_loeschen ohne datum aufgerufen") return if await k.ablage.batterieverlauf_eintrag_loeschen(datum): await k.batterieverlauf_veroeffentlichen() _LOGGER.info("Batteriespannungs-Tageseintrag %s gelöscht", datum) else: _LOGGER.warning("Batteriespannungs-Tageseintrag %s nicht gefunden", datum)