Firmware-Einstellung – technische Auswirkungen¶
Zuletzt geändert am 25.07.2026
Diese Seite beschreibt, wo die Firmware-Version in der Integration gesetzt wird, wie sie ausgewertet wird und welche Folgen die initiale Konfiguration gegenüber einer späteren Änderung der Firmware haben.
Speicherort der Firmware-Version¶
- Initiale Konfiguration (Config Flow, Schritt „user“): Die gewählte Firmware wird nur in den Optionen des Eintrags gespeichert (
entry.options["firmware_version"]). Sie wird bewusst nicht inentry.dataübernommen (config_flow.py Zeilen 333–336:firmware_versionwird aususer_inputfürdata_for_entryentfernt). - Options-Flow (spätere Änderung): Die Firmware ist im Options-Schema (config_flow.py Zeilen 871–877). Beim Speichern werden die Optionen aktualisiert, inkl.
firmware_version. - Reconfigure-Flow: Beim Neukonfigurieren der Integration wird die Firmware in
entry.datageschrieben (config_flow.py Zeilen 689–697). Nach Reconfigure kann die Firmware also indatastehen.
Die Auswertung erfolgt einheitlich über die Hilfsfunktionen in utils.py: zuerst entry.options, Fallback entry.data, sonst DEFAULT_FIRMWARE.
Auswertung im Code¶
Konstanten (const_base.py)¶
Seit V2.7.0 ist FIRMWARE_CONFIG die Primärstruktur und trägt zwei von der Firmware-Zeichenkette abhängige Werte: die numerische Version (Kompatibilitätsprüfung, siehe unten) und den Default für int32_register_order (reg_order). FIRMWARE_VERSION wird automatisch davon abgeleitet und bleibt für alle bestehenden Aufrufer unverändert nutzbar:
FIRMWARE_CONFIG: dict = {
"V1.1.0-3K": {"version": 9, "reg_order": "low_first"},
"V0.0.10-3K": {"version": 8, "reg_order": "low_first"},
"V0.0.9-3K": {"version": 7, "reg_order": "high_first"},
# ...
"V0.0.3-3K": {"version": 1, "reg_order": "high_first"},
}
FIRMWARE_VERSION: dict = {k: v["version"] for k, v in FIRMWARE_CONFIG.items()}
Jede Firmware-Zeichenkette ist einer numerischen Version (aktuell 1–9) zugeordnet. Diese Zahl wird für die Kompatibilitätsprüfung verwendet.
Register-Reihenfolge für 32-Bit-Werte (int32_register_order) — ebenfalls firmware-abhängig¶
Seit V2.7.0 ist nicht nur die Sensor-Verfügbarkeit firmware-abhängig, sondern auch die Interpretation der bereits vorhandenen int32-Sensoren (z. B. Energie-Akkumulation): get_int32_register_order(hass, entry) (modbus_utils.py) liest den reg_order-Wert aus FIRMWARE_CONFIG[fw_version] als Default, sofern kein manueller int32_register_order-Override in lambda_wp_config.yaml gesetzt ist (Priorität: YAML-Override > FW-Default > absoluter Fallback "high_first").
Der Wert wird einmalig beim Setup ausgelesen und in coordinator._int32_register_order gespeichert (init.py) — nicht bei jedem Update-Zyklus neu. Das heißt aber auch: Ein Reload (z. B. durch Ändern der Firmware-Version im Options-Flow, siehe unten) wertet den FW-Default neu aus. Details zur Prioritätskette und den beiden 32-Bit-Reihenfolgen: Register-Reihenfolge int32.
Wichtige Konsequenz beim Firmware-Wechsel: Ändert sich durch den neuen fw_version der reg_order-Default (z. B. bei einem Wechsel zwischen den beiden neuesten und einer älteren Firmware-Version, siehe Tabelle oben), werden bestehende int32-Sensoren ab dem Reload anders interpretiert — ohne dass sich am Gerät etwas geändert hat. Das kann bei Energie-Zählern zu einem scheinbaren Sprung führen. Der in Release 2.8.0 eingeführte calculate_energy_delta()-Schutz (verwirft implausible Deltas über MAX_ENERGY_DELTA_WH statt sie zu kappen und einzubuchen) fängt genau diesen Fall ab.
Abfrage der Firmware¶
get_firmware_version(entry)– liefert die Zeichenkette (z. B."V0.0.8-3K"), u. a. für Anzeige unddevice_info.get_firmware_version_int(entry)– liefert die Zahl (1–8). Wird überall genutzt, wo nach Firmware gefiltert wird.
Reihenfolge: entry.options → entry.data → DEFAULT_FIRMWARE.
Sensor-Filterung¶
get_compatible_sensors(sensor_templates, fw_version) (utils.py), seit V2.8.0 mit zwei Feldern pro Template (Priorität von hoch nach niedrig):
firmware_versions(Range-Notation, neu in V2.8.0): Liste aus"X-Y"(Bereich inklusive),"-X"(Version X ausschließen) oderX(einzelne Version einschließen), ausgewertet über_parse_firmware_versions(). Erlaubt — anders alsfirmware_version— auch eine Obergrenze, z. B.["1-7"]für ein Register, das ab einer neueren Steuerungsgeneration nicht mehr existiert (sieheambient_temperaturein const_sensor.py und Release 2.8.0).firmware_version(Minimum, bestehendes Verhalten): Sensor aktiv, wenntemplate["firmware_version"] <= fw_version.- Kein Feld: Sensor gilt für alle Firmware-Versionen.
firmware_versions hat Vorrang vor firmware_version, falls beide gesetzt sind. Vollständig rückwärtskompatibel — bestehende firmware_version: X-Sensoren sind unverändert.
In den Konstanten (const_sensor.py, const_calculated_sensors.py) haben die allermeisten Sensoren "firmware_version": 1; einzelne können höhere Werte oder (seit V2.8.0) firmware_versions-Bereiche haben.
Wichtig — General Sensors (SENSOR_TYPES): Bis einschließlich V2.7.0 wurde diese Sensorgruppe nirgends durch get_compatible_sensors() gefiltert — weder in sensor.py (Entity-Erzeugung) noch in coordinator.py (_read_general_sensors_batch). Ein firmware_version/firmware_versions-Feld bei einem General Sensor hatte dadurch nie eine Wirkung. Seit V2.8.0 ist das behoben; die Tabelle unten ist entsprechend aktuell.
Sentinel-Filterung als ergänzender Schutz¶
Unabhängig von der FW-Filterung schützt seit V2.8.0 is_sentinel_value() (utils.py) vor Lambda-Protokoll-Sentinel-Rohwerten (0x8000 = Register nicht vorhanden, -3000 als int16 = Fühler nicht angeschlossen), die sonst unskaliert als reale Messwerte gespeichert würden. Ein optionales sentinel_values-Feld im Template aktiviert zusätzlich -1 (0xFFFF) als Sentinel für einen einzelnen Sensor — global ist -1 bewusst kein Sentinel, da er bei manchen Sensoren (z. B. Temperatur-Offsets) ein gültiger Wert ist. Details: Release 2.8.0.
Wo die Firmware-Version verwendet wird¶
| Komponente | Verwendung |
|---|---|
| Coordinator | Beim Aufbau der Register-/Sensor-Mappings (coordinator.py Zeilen 1317–1343) und in _async_update_data (Zeilen 1527–1545): get_firmware_version_int(entry) und get_compatible_sensors(...) für HP, Boil, Buff, Sol, HC. Nur zu den kompatiblen Sensoren gehörende Register werden gelesen. |
| Sensor-Plattform | sensor.py Zeilen 108–113: fw_version = get_firmware_version_int(entry); es werden nur Entities für Sensoren aus get_compatible_sensors(...) erstellt. |
| Climate-Plattform | climate.py Zeilen 191–194: gleiche Logik – nur kompatible Climate-Templates. |
| Template-Sensoren | template_sensor.py Zeilen 79–82: Filterung nach Firmware-Version. |
| Migration/Cleanup | migration.py nutzt get_firmware_version_int für kompatible Sensoren. |
| device_info | utils.py build_device_info: model wird mit get_firmware_version(entry) (Zeichenkette) gesetzt. |
| 32-Bit-Register-Reihenfolge | modbus_utils.py get_int32_register_order(hass, entry): FW-abhängiger reg_order-Default aus FIRMWARE_CONFIG[fw_version] (seit V2.7.0), sofern kein YAML-Override gesetzt ist. Einmalig beim Setup ausgewertet, siehe unten. |
Initiale Konfiguration¶
- Der Nutzer wählt im Config Flow eine Firmware aus der Liste
FIRMWARE_VERSION.keys()(config_flow.py Zeilen 397–398, 266). - Beim Erstellen des Eintrags landet die Firmware nur in options.
- Beim ersten
async_setup_entrylesen alle Plattformen und der Coordinator die Firmware aus den Optionen (überget_firmware_version_int(entry)) und erstellen ausschließlich zu dieser Version passende Entities bzw. Register-Zuordnungen. - Effekt: Von Anfang an existieren nur Sensoren/Climate-Entities, die zur gewählten Firmware passen; es werden nur die zugehörigen Modbus-Register gelesen.
Spätere Änderung der Firmware¶
Über den Options-Flow¶
- Nutzer ändert unter „Optionen“ der Integration die Firmware und speichert.
entry.options["firmware_version"]wird aktualisiert.- Der Update-Listener löst
async_reload_entryaus (init.py Zeile 319). - Ablauf:
async_unload_entry: Alle Plattformen (Sensor, Climate, etc.) und der Coordinator werden entladen, Entities entfernt.async_setup_entry: Setup läuft erneut;get_firmware_version_int(entry)liefert die neue Firmware.- Alle Plattformen und der Coordinator bauen ihre Listen ausschließlich mit
get_compatible_sensors(..., fw_version)für die neue Version auf.
Folgen:
- Firmware-Erhöhung (z. B. 1 → 6): Es werden mehr Sensoren/Register kompatibel. Es entstehen neue Entities; ggf. erscheinen neue Entity-IDs (und bei bereits belegten IDs im Entity-Register z. B. Suffixe wie
_2). - Firmware-Absenkung (z. B. 6 → 1): Sensoren mit
firmware_version> 1 werden aus der Liste gestrichen. Die zugehörigen Entities werden beim Unload entfernt. Die alten Entity-IDs können im Entity-Register als „verwaist“ (restored) zurückbleiben; die zugehörigen Verlaufsdaten bleiben in der Recorder-Datenbank unter der alten Entity-ID, sind aber für die neue Konfiguration nicht mehr sichtbar. - Register-Reihenfolge (
int32_register_order): Ändert der Firmware-Wechsel auch denreg_order-Default (siehe oben), werden bestehende int32-Sensoren ab dem Reload anders interpretiert - ohne YAML-Override. Betroffene Energie-Zähler können dadurch einen scheinbaren Sprung zeigen; dercalculate_energy_delta()-Schutz (Release 2.8.0) verwirft diesen statt ihn einzubuchen.
Es findet keine automatische Migration von Entity-IDs oder Verlaufsdaten beim Firmware-Wechsel statt.
Über den Reconfigure-Flow¶
- Beim Rekonfigurieren wird die Firmware in
entry.datageschrieben und der Eintrag perasync_reloadneu geladen. - Danach greifen
get_firmware_version/get_firmware_version_intwegen der Fallback-Reihenfolge (options vor data) weiterhin zuerst aufentry.optionszu. Wenn options unverändert bleiben, kann die neue Firmware ausdataerst nach einer Options-Anpassung oder wenn options leer sind wirksam werden. In der Praxis wird nach Reconfigure oft die Integration neu gesetzt; dann sind die gleichen inhaltlichen Auswirkungen wie bei der Options-Änderung zu erwarten (Reload, Neuaufbau der Entities nach neuer Firmware).
Kurzüberblick¶
| Aspekt | Initiale Konfiguration | Spätere Änderung (Options) |
|---|---|---|
| Speicherort | Nur entry.options |
entry.options aktualisiert |
| Wann wirksam | Beim ersten Setup | Nach Speichern der Optionen und Reload |
| Entities | Nur zur gewählten Firmware passend | Beim Reload komplett neu aufgebaut; je nach Richtung (Hoch/Runter) neue oder weniger Entities |
| Modbus | Nur Register für kompatible Sensoren | Nach Reload nur noch Register für die neue Firmware |
| Register-Reihenfolge (int32) | FW-abhängiger reg_order-Default aus FIRMWARE_CONFIG (seit V2.7.0) |
Wird beim Reload neu ausgewertet — kann bestehende int32-Sensoren anders interpretieren (siehe Folgen oben) |
| Verlauf/Statistik | Keine Besonderheit | Keine Migration; bei entfernten Entities bleiben alte IDs ggf. als Waisen im Register, Verlauf bleibt unter alter Entity-ID |
Die technische Grundlage für die Anzeige und Konfiguration der Firmware im UI bildet die gleiche Stelle im Config Flow (config_flow.py Zeilen 397–398: firmware_options = list(FIRMWARE_VERSION.keys()) für die Dropdown-Liste; die tatsächlichen Auswirkungen entstehen durch die beschriebene Filterung in Coordinator und allen Plattformen.