github Zendure/Zendure-HA 1.4.1
Release 1.4.1 🌞

4 hours ago

Release 1.4.1 🌞

Point release on top of 1.4.0 that fixes a regression affecting every existing SolarFlow AC+ user (and any other device whose Zendure-app name contains a +).

🚨 Fix for the 1.4.0 SF2400AC+ / SF1600AC+ / SF4000AC+ regression

Users of SolarFlow AC+ devices upgrading from a pre-1.4.0 install reported that after the upgrade their entities split in two on the same device: the canonical number.solarflow_2400_ac_plus_output_limit became Unavailable while a duplicate ..._output_limit_2 variant carried the live value (#1477). The Zendure Manager consequently reported "No devices online" and manual output-limit changes never reached the device.

Root cause: the + → _plus snakecase change in 1.4.0 made these devices produce entities under new unique_ids. check_entities() renamed the old registry rows to the new canonical entity_id but did not update their unique_id, so when the integration created the live entities with the new unique_id, HA had to append _2 (the canonical slot was squatted by an orphan).

The fix rewrites check_entities() to migrate entity_id AND unique_id in one operation, and to prefer the entry that already carries the correct unique_id when both an orphan and a _2 entity exist. On the first restart after upgrading to 1.4.1:

  • Unavailable orphan entities disappear.
  • _2 duplicates are renamed back to the canonical entity_id.
  • The live entity re-attaches to the same registry row, so recorder history is preserved on the row we kept.

No manual cleanup is needed. If you had already worked around it (renamed entities by hand, deleted orphans), that also continues to work.

🩹 Other fixes in this point release

  • No more "Detected blocking call to read_text" warning (#1474, #1435 by @zoic21) — the integration's one-time translation-map load now runs off the event loop, so Home Assistant no longer logs a blocking-call warning on every startup.
  • Clearer setup error messages (#1480) — a failed setup used to show only "invalid input". The config flow now tells you what actually went wrong: a malformed token, a network problem, an API rejection (with Zendure's own message), a valid token on an account/region with no devices, or a missing MQTT server. This directly helps the "invalid input" reports (#1310, #1263, #1390) where the real cause was a wrong account or region rather than the integration.
  • Device matching ignores spaces — device model names are now matched ignoring spacing, so variants like SolarFlow 800 Pro 2 vs SolarFlow 800 Pro2 resolve to the same device class.

🆕 New device support (from 1.4.0)

  • SolarFlow 4000 AC+ support added.
  • ACE 1500 controllable without a Hub by @ahocevar in #1338 — new hubMode toggle (paired / standalone). Paired mode is the default and byte-identical to previous behaviour. Standalone mode is opt-in for users without a Hub 1200/2000: the integration parks the device in autoModel=0 and drives charging directly via inputLimit writes, with 50 W quantization and a 30 s throttle to protect device flash memory.

⚠️ Notes for users

  • SF2400AC and SF2400AC+ in the same setup: this release resolves the unique_id collision that silently dropped the second device's entities when both kept their Zendure-default names.
  • Multi-device setups with SOCFULL bypass: PR #1422 fixes a regression where one SOCFULL device trickling a few watts to home caused an actively-charging sibling to cycle between 0 W and full power every ~60 s. If you experienced this pattern, please confirm it is resolved.
  • ACE 1500 owners: your ACE 1500 will gain a hubMode select entity, defaulting to paired (existing behaviour). If you run without a Hub, flip it to standalone to enable direct charge control.

🩹 Critical fixes (from 1.4.0)

  • Cap discharge_bypass per device by @zoic21 in #1422 — fixes the charge cycling regression of the #1151 fix.
  • SF2400AC+ no-start fix (kickstart walk introduced in 192bf64, charge-side completed by @zoic21 in #1434) — when the device fails to latch on the first start command, the integration walks the input/output limit by 4 W per tick (capped at 2 × POWER_START) until the device starts drawing power. Replaces the random-jitter approach proposed in #1363.
  • Keep AC relay in input mode when smart_charging has no surplus by @zoic21 in #1427 — eliminates AC relay flap between input and output on every positive P1 fluctuation while charging.
  • Substitute + with _plus in snakecase (c603722) — prevents unique_id collision between SF2400AC and SF2400AC+ devices.
  • Fix p1 matching when SOCFULL and grid reverse disabled by @zaubara in #1296
  • Hub and ACE fixes by @harrymayr in #1287 — removes AC charge capability from HUB family (which doesn't support it), adds UPS pack_state for ACE 1500.
  • Register battery entities immediately on first packData by @devTechi in #1392 — batteries appearing on first HTTP-failed poll are no longer invisible until the next 60-second cycle.
  • Entity registry self-healing (eec95df) — stale entries with the wrong domain or none-typed entries are now cleaned up automatically on integration startup, no manual migration needed.

✨ New sensors (from 1.4.0)

  • Global SOC, battery voltage delta, round-trip efficiency by @zoic21 in #1426
    • global_soc on the Zendure Manager: weighted SOC across all online devices.
    • delta_voltage per battery: max cell voltage minus min cell voltage. A sustained value above ~0.15 V over an extended period may indicate cell imbalance.
    • roundtrip_efficiency per device: lifetime aggrDischarge / aggrCharge × 100.

🛠️ Other fixes and improvements (from 1.4.0)

🌐 Translations (from 1.4.0)

🔧 Build / dependencies

  • Bump ruff from 0.15.12 to 0.15.13 (#1384)
  • Bump ruff from 0.15.13 to 0.15.14 (#1401)
  • Bump ruff from 0.15.14 to 0.15.20 (#1462)
  • Update bleak-retry-connector requirement (#1400)
  • Bump actions/checkout from 6 to 7 (#1448)
  • Update pip requirement to >=26.1.1 (#1367)
  • Update pip requirement to >=26.1.2 (#1409)

👋 New contributors (since 1.3.1)

Full Changelog: 1.4.0...1.4.1

Don't miss a new Zendure-HA release

NewReleases is sending notifications on new releases.