You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Entity-mode force-charge / force-discharge / export-limit writes now respect the target entity's unit_of_measurement (D-056). When running in entity mode (typically against foxess_modbus), the integration writes power commands via number.set_value to user-configured target entities. Every power entity published by foxess_modbus declares unit_of_measurement: "kW" with min: 0, max: 15 (values 0–15 kW). Previous releases wrote raw watts (e.g. 10500 for 10.5 kW) into these targets; foxess_modbus clamped every such write to its declared max of 15, so force-charge / force-discharge / export-limit all ran at the clamp ceiling (15 kW) regardless of what the pacing algorithm requested — the user had no effective control. Fix: FoxESSEntityAdapter now routes every power write through a new _convert_and_clamp_power_for_write helper, which reads the target's unit_of_measurement + min + max attributes, converts watts via HA's PowerConverter, and clamps to the declared range. Missing or unrecognised units pass through unchanged with a visible warning (so a 1000× misconfiguration can't be silent); over-max requests are clamped with a warning so the user sees when pacing is capped by the target's declared max. Non-power writes (SoC percent, work-mode select) are untouched. Cloud mode — which writes fdPwr in watts natively via the FoxESS Open API — is unaffected. Nine-test regression suite in tests/test_entity_mode_write_units.py drives the real FoxESSEntityAdapter against a foxess_modbus-shaped number entity (kW/W/missing-unit) covering charge, discharge, export-limit, and a guard that the min_soc percent write is never re-scaled. Restores pacing control for every entity-mode user — the algorithm's decisions now actually take effect on the inverter.
Reverted
Attempted "no-solar dashboard fallback" feature withdrawn. Three pre-release iterations (beta.1 Gen Load swap → beta.2 20-min timeout → beta.3 hide-by-default) tried to replace the stuck-zero solar reading on AC-coupled / unwired-PV installs with something more useful. Each iteration exposed a fresh way the dashboard surface fell short — the Gen Load swap duplicated what the House box already shows, the timeout kept the display honest overnight but didn't fix duplication, and hide-by-default added nothing beyond what boxes: config already offered. Reverted to v1.0.14 behaviour: the four-box overview card renders unconditionally; users who want to hide the solar box on a non-solar install can use the existing boxes: config. The full solar-seen plumbing was removed as dead code; D-052 is marked [RETIRED] in the knowledge tree with the three-pivot story preserved in docs/knowledge/META.md (2026-05-08).
Test infrastructure
Page-fixture predicate hardened against the entity-mode init race (C-031). tests/e2e/conftest.py::_wait_for_lovelace_panel previously gated the final-stage settled signal on main.hass.connected === true (a live JS property) alongside the hui-root DOM check. Under entity-mode CI, the heavier state-change burst from input-helper polling could transiently flap connected=true→false→true across multiple Playwright polls and exhaust the 75 s budget. hui-root's presence is strictly stronger: once mounted, the Lit render that produced it required both panel.hass and main.hass.connected to be true at render time, and the DOM fact survives runtime flaps of either property. Final-stage predicate now settles on hui-root alone. Four new unit tests in tests/test_e2e_page_fixture.py::TestWaitForLovelacePanelEntityModeInitRace extract the predicate string from conftest, evaluate it in real Node.js against an adversarial entity-mode DOM snapshot (panel mounted, hui-root present, connected=false), and assert it returns truthy.