Skip to content

Reliability overhaul: HA 2026.7 + firmware >= 5.1.10 compatibility, event-loop-safe I/O - #3

Open
kkangg1 wants to merge 6 commits into
script0803:mainfrom
kkangg1:feat/ha-stability-fw5110
Open

kkangg1 wants to merge 6 commits into
script0803:mainfrom
kkangg1:feat/ha-stability-fw5110

Conversation

@kkangg1

@kkangg1 kkangg1 commented Sep 4, 2026

Copy link
Copy Markdown

Summary

This PR makes the integration reliable as an always-on Home Assistant polling integration, and restores compatibility with two breaking environment changes: Home Assistant 2026.7 (zeroconf import moved) and device firmware ≥ 5.1.10 (aggregate fields removed from the payload).

It is based on the optimized line I have been running in production against five devices (SPM02-class three-phase meters) for several weeks.

Fixes

  • HA 2026.7: fix the zeroconf import path; without it the config flow fails to load entirely.
  • Firmware ≥ 5.1.10: the firmware no longer reports Total*/Average* aggregates, so those entities silently disappeared. normalize_meter_data() now synthesizes them from per-phase X/Y/Z values (TotalActivePower, TotalReactivePower, TotalApparentPower, TotalCurrent, TotalForwardEnergy, TotalReverseEnergy, TotalEnergy{phase}, TotalEnergy, AverageVoltageLN, AverageLineCurrent). Firmware-provided values always win; a partial phase set never fabricates a total.
  • Discovery: newer firmware advertises mDNS hostnames as BITUO TECHNIK-<model>-<sn> instead of EnergySensor-<model>-<sn>; the previous filter only matched energysensor and silently ignored those devices.
  • Event-loop safety: HTTP calls have a 10s timeout, and settings/OTA metadata file I/O is moved off the event loop (async_add_executor_job).
  • Transient failures: a single failed poll keeps the last data; entities only go unavailable after 2 consecutive failures (FAILURE_THRESHOLD), and missing values report unavailable instead of a bogus 0.
  • Switch platform: capability is probed once at setup; meter-only models no longer poll a non-existent switch endpoint every cycle.
  • Unload: async_unload_entry cleans up entry state; set_frequency applies to the target device or all devices.

Structure

  • Blocking HTTP moved into api.py (BituoApiClient), polling into coordinator.py (DataUpdateCoordinator), pure payload logic into helpers.py with unit tests.
  • Added tests/ (helpers normalization, repository privacy guard) and a CI workflow running them.
  • Committed __pycache__ files removed; .gitignore added.

Notes for the maintainer

  • I realize this is a large diff — it has grown while running in production. If you prefer, I can split it into focused PRs (e.g. HA 2026.7 import fix, firmware 5.1.10 synthesis, discovery filter) against the current file layout; just say the word.
  • manifest.json currently points documentation/issue_tracker at my fork; happy to revert those to this repo before merge.
  • python3 -m unittest discover -s tests — 7 tests pass; compileall clean.

kkangg1 added 6 commits July 29, 2026 20:06
- REQUEST_TIMEOUT 5s -> 10s: slow meters (or event-loop stalls on the
  HA host) regularly exceeded 5s and flipped every entity unavailable.
- FAILURE_THRESHOLD = 2: a single failed poll now keeps the last data
  instead of marking all entities unavailable; entities only go
  unavailable after two consecutive failures.
Newer firmware advertises the device as "BITUO TECHNIK-<model>-<sn>"
instead of "EnergySensor-<model>-<sn>"; the previous filter only
matched "energysensor" and silently ignored those devices.
Firmware 5.1.10 stopped reporting the TotalEnergy{phase} and
TotalEnergy fields, so the corresponding entities vanished.
Derive them from forward/reverse energy (native or synthesized);
firmware-provided values always win.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant