Reset-Manager - Technische Dokumentation¶
Diese Dokumentation beschreibt die zentrale Reset-Logik für alle Sensor-Typen (Cycling und Energy) in der Lambda Heat Pumps Integration.
Übersicht¶
Der ResetManager ist eine zentrale Klasse, die alle Reset-Automatisierungen für periodische Sensoren verwaltet. Er ersetzt die frühere setup_cycling_automations() Funktion und bietet eine einheitliche Schnittstelle für alle Reset-Operationen.
Vorteile der Zentralisierung¶
- Code-Deduplizierung: Einheitliche Handler-Struktur für Cycling- und Energy-Sensoren
- Wartbarkeit: Änderungen an Reset-Logik nur an einem Ort
- Klarheit: Funktion heißt nicht mehr "cycling_automations" wenn sie für alle verwendet wird
- Konsistenz: Beide Sensor-Typen verwenden die gleiche Handler-Struktur
Architektur¶
┌─────────────────────────────────────────────────────────────┐
│ __init__.py │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ async_setup_entry() │ │
│ │ - ResetManager(hass, entry.entry_id) │ │
│ │ - reset_manager.setup_reset_automations() │ │
│ │ - Speichere in hass.data │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ reset_manager.py │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ ResetManager │ │
│ │ - __init__(hass, entry_id) │ │
│ │ - setup_reset_automations() │ │
│ │ - _send_reset_signal_async() │ │
│ │ - cleanup() │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼ (Dispatcher-Signale)
┌─────────────────────────────────────────────────────────────┐
│ sensor.py │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ LambdaCyclingSensor │ │
│ │ - _handle_reset() (einheitlich für alle Perioden) │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ LambdaEnergyConsumptionSensor │ │
│ │ - _handle_reset() (einheitlich) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Implementierung¶
1. ResetManager Klasse¶
Datei: custom_components/lambda_heat_pumps/reset_manager.py
class ResetManager:
"""Zentrale Reset-Logik für alle Sensor-Typen und Perioden."""
def __init__(self, hass: HomeAssistant, entry_id: str):
"""Initialize ResetManager."""
self.hass = hass
self._entry_id = entry_id
self._unsub_timers = {}
def setup_reset_automations(self):
"""Richte Reset-Automatisierungen ein."""
# Daily Reset
@callback
def reset_daily(now: datetime) -> None:
"""Reset daily sensors at midnight and update yesterday sensors."""
_LOGGER.info("Resetting daily sensors at midnight")
# 1. Erst Yesterday-Sensoren auf aktuelle Daily-Werte setzen
self.hass.async_create_task(
_update_yesterday_sensors_async(self.hass, self._entry_id)
)
# 2. Dann Daily-Sensoren auf 0 zurücksetzen
self.hass.async_create_task(
self._send_reset_signal_async(SIGNAL_RESET_DAILY)
)
self._unsub_timers["daily"] = async_track_time_change(
self.hass, reset_daily, hour=0, minute=0, second=0
)
# 2h, 4h, Monthly, Yearly ähnlich...
def cleanup(self):
"""Cleanup Reset-Automatisierungen."""
for period, listener in self._unsub_timers.items():
if listener:
listener()
self._unsub_timers = {}
2. Initialisierung in init.py¶
Datei: custom_components/lambda_heat_pumps/__init__.py
# In async_setup_entry()
from .reset_manager import ResetManager
# Set up reset automations using ResetManager
reset_manager = ResetManager(hass, entry.entry_id)
reset_manager.setup_reset_automations()
# Store reset_manager for cleanup
if "lambda_heat_pumps" not in hass.data:
hass.data["lambda_heat_pumps"] = {}
if entry.entry_id not in hass.data["lambda_heat_pumps"]:
hass.data["lambda_heat_pumps"][entry.entry_id] = {}
hass.data["lambda_heat_pumps"][entry.entry_id]["reset_manager"] = reset_manager
3. Cleanup in init.py¶
Datei: custom_components/lambda_heat_pumps/__init__.py
# In async_unload_entry()
if (
"lambda_heat_pumps" in hass.data
and entry.entry_id in hass.data["lambda_heat_pumps"]
and "reset_manager" in hass.data["lambda_heat_pumps"][entry.entry_id]
):
reset_manager = hass.data["lambda_heat_pumps"][entry.entry_id]["reset_manager"]
reset_manager.cleanup()
del hass.data["lambda_heat_pumps"][entry.entry_id]["reset_manager"]
Reset-Intervalle¶
Der ResetManager verwaltet folgende Reset-Intervalle:
- Daily: Jeden Tag um Mitternacht (00:00:00)
- 2h: Alle 2 Stunden (0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
- 4h: Alle 4 Stunden (0, 4, 8, 12, 16, 20)
- Monthly: 1. des Monats um Mitternacht (00:00:00)
- Yearly: 1. Januar um Mitternacht (00:00:00)
Jedes Reset-Intervall sendet ein entsprechendes Dispatcher-Signal:
- SIGNAL_RESET_DAILY
- SIGNAL_RESET_2H
- SIGNAL_RESET_4H
- SIGNAL_RESET_MONTHLY
- SIGNAL_RESET_YEARLY
Sensor-Handler¶
Cycling-Sensoren¶
Cycling-Sensoren verwenden eine einheitliche _handle_reset() Methode für alle Perioden:
async def _handle_reset(self, entry_id: str):
"""Handle reset signal for all periods (einheitlich, wie Energy)."""
if entry_id != self._entry.entry_id:
return
# Prüfe Periode basierend auf sensor_id und reset_interval
if self._sensor_id.endswith("_daily") and self._reset_interval == "daily":
self._cycling_value = 0
self.async_write_ha_state()
elif self._sensor_id.endswith("_2h") and self._reset_interval == "2h":
self._cycling_value = 0
self.async_write_ha_state()
# ... weitere Perioden
Vorteil: Statt 5 separater Methoden (_handle_daily_reset, _handle_2h_reset, etc.) gibt es jetzt nur noch 1 einheitliche Methode.
Energy-Sensoren¶
Energy-Sensoren verwenden bereits eine einheitliche _handle_reset() Methode (unverändert):
async def _handle_reset(self, entry_id: str):
"""Handle reset signal."""
if self._reset_interval == "daily" and self._period == "daily":
# Update _yesterday_value from total sensor
# ...
elif self._reset_interval != "total":
self._energy_value = 0.0
# ...
Signal-Registrierung¶
Sensoren registrieren sich weiterhin direkt auf die Dispatcher-Signale:
# In LambdaCyclingSensor.async_added_to_hass()
@callback
def _wrap_reset(entry_id: str):
self.hass.async_create_task(self._handle_reset(entry_id))
# Registriere für alle Perioden (einheitlicher Wrapper)
self._unsub_dispatcher = async_dispatcher_connect(
self.hass, SIGNAL_RESET_DAILY, _wrap_reset
)
self._unsub_2h_dispatcher = async_dispatcher_connect(
self.hass, SIGNAL_RESET_2H, _wrap_reset
)
# ... weitere Perioden
Vorteil: Statt 5 separater Wrapper-Funktionen gibt es jetzt nur noch 1 einheitliche Wrapper-Funktion.
Code-Deduplizierung¶
Vorher (5 separate Methoden)¶
async def _handle_daily_reset(self, entry_id: str):
if entry_id == self._entry.entry_id and self._sensor_id.endswith("_daily"):
self._cycling_value = 0
self.async_write_ha_state()
async def _handle_2h_reset(self, entry_id: str):
if entry_id == self._entry.entry_id and self._sensor_id.endswith("_2h"):
self._cycling_value = 0
self.async_write_ha_state()
# ... 3 weitere ähnliche Methoden
Nachher (1 einheitliche Methode)¶
async def _handle_reset(self, entry_id: str):
if entry_id != self._entry.entry_id:
return
if self._sensor_id.endswith("_daily") and self._reset_interval == "daily":
self._cycling_value = 0
self.async_write_ha_state()
elif self._sensor_id.endswith("_2h") and self._reset_interval == "2h":
self._cycling_value = 0
self.async_write_ha_state()
# ... weitere Perioden
Ergebnis: 5 Methoden → 1 Methode (Code-Deduplizierung)
Migration von setup_cycling_automations()¶
Die alte setup_cycling_automations() Funktion wurde durch ResetManager ersetzt:
Vorher¶
# In __init__.py
from .automations import setup_cycling_automations
setup_cycling_automations(hass, entry.entry_id)
# In async_unload_entry()
from .automations import cleanup_cycling_automations
cleanup_cycling_automations(hass, entry.entry_id)
Nachher¶
# In __init__.py
from .reset_manager import ResetManager
reset_manager = ResetManager(hass, entry.entry_id)
reset_manager.setup_reset_automations()
# In async_unload_entry()
if "reset_manager" in hass.data["lambda_heat_pumps"][entry.entry_id]:
reset_manager = hass.data["lambda_heat_pumps"][entry.entry_id]["reset_manager"]
reset_manager.cleanup()
Vorteile¶
- Code-Deduplizierung: Cycling-Handler von 5 Methoden auf 1 Methode reduziert
- Konsistenz: Beide Sensor-Typen verwenden die gleiche Handler-Struktur
- Zentrale Logik: ResetManager verwaltet alle Reset-Operationen
- Klarheit: Funktion heißt nicht mehr "cycling_automations" wenn sie für alle verwendet wird
- Wartbarkeit: Änderungen an Reset-Logik nur an einem Ort
Verwandte Dokumentation¶
- Reset-Logik und Yesterday-Sensoren - Details zur Energy-Sensor Reset-Logik
- Cycling-Sensoren - Details zur Cycling-Sensor Reset-Logik