Reported by @maic-de in #464. Confirmed on a second installation (SUN2000-8K-MAP0 + LUNA2000). Code below is from release/v1.5.0.
Symptom
The Huawei battery's Discharging cutoff capacity cannot be set below 12 %. Huawei's own minimum is 5 %.
Cause
The entity comes from a class written for Marstek batteries without hardware cutoff registers, and the Huawei driver reuses it:
# number.py
class MarstekSoftSocLimitNumber(CoordinatorEntity, NumberEntity):
"""Software-enforced SOC limit for batteries that don't expose hardware
cutoff registers (v3/vA/vD)."""
...
else:
self._attr_translation_key = "discharging_cutoff_capacity"
self._attr_unique_id = f"{coordinator.device_key}_discharging_cutoff_capacity"
self._attr_icon = "mdi:battery-arrow-down"
self._attr_native_min_value = 12
self._attr_native_max_value = 50
12 % is the Venus D's hardware floor. Nothing about it applies to a LUNA2000.
The mismatch is wider than the reported symptom
The Huawei driver declares its own register ranges, and they barely overlap with what the entity offers:
# drivers/huawei.py
_CHARGE_CUTOFF_RANGE = (90.0, 100.0) # register 47081
_DISCHARGE_CUTOFF_RANGE = (0.0, 20.0) # register 47082
|
entity offers |
driver accepts |
usable |
| discharge cutoff |
12 – 50 % |
0 – 20 % |
12 – 20 % |
| charge cutoff |
50 – 100 % |
90 – 100 % |
90 – 100 % |
Anything outside the driver's range is not clamped but skipped, and only at debug level:
if not low <= float(soc_pct) <= high:
_LOGGER.debug(
"Huawei driver: %s cutoff %.1f%% is outside the register range "
"%.0f-%.0f%%; leaving the hardware backstop untouched", ...
)
return False
So a user who sets the discharge cutoff to 30 %, or the charge cutoff to 80 %, gets an entity that shows the new value while the hardware backstop never moves, with nothing in the log unless debug is on. Skipping rather than clamping is the right call — the comment explains why — but the control that produces the value should not offer a range the write path will reject.
Visible contradiction on the reported symptom
On my installation the entity reads 5.0, taken from the inverter, while its slider minimum is 12 — the displayed value sits below the minimum the control accepts:
number.omnibattery_huawei_luna2000_2_discharging_cutoff_capacity
state: 5.0
min: 12 max: 50 step: 1 unit: %
Any user who touches that control raises their floor from 5 % to 12 % and cannot undo it through the UI. On a 10 kWh LUNA2000 that is roughly 0.7 kWh removed from the usable range.
Suggested direction
Take the entity bounds from the driver instead of from constants in number.py. The correct values already exist on the driver side (_CHARGE_CUTOFF_RANGE / _DISCHARGE_CUTOFF_RANGE), and the capability set is the natural place to surface them, so every brand supplies its own window rather than inheriting Marstek's.
Reported by @maic-de in #464. Confirmed on a second installation (SUN2000-8K-MAP0 + LUNA2000). Code below is from
release/v1.5.0.Symptom
The Huawei battery's Discharging cutoff capacity cannot be set below 12 %. Huawei's own minimum is 5 %.
Cause
The entity comes from a class written for Marstek batteries without hardware cutoff registers, and the Huawei driver reuses it:
12 % is the Venus D's hardware floor. Nothing about it applies to a LUNA2000.
The mismatch is wider than the reported symptom
The Huawei driver declares its own register ranges, and they barely overlap with what the entity offers:
Anything outside the driver's range is not clamped but skipped, and only at debug level:
So a user who sets the discharge cutoff to 30 %, or the charge cutoff to 80 %, gets an entity that shows the new value while the hardware backstop never moves, with nothing in the log unless debug is on. Skipping rather than clamping is the right call — the comment explains why — but the control that produces the value should not offer a range the write path will reject.
Visible contradiction on the reported symptom
On my installation the entity reads 5.0, taken from the inverter, while its slider minimum is 12 — the displayed value sits below the minimum the control accepts:
Any user who touches that control raises their floor from 5 % to 12 % and cannot undo it through the UI. On a 10 kWh LUNA2000 that is roughly 0.7 kWh removed from the usable range.
Suggested direction
Take the entity bounds from the driver instead of from constants in
number.py. The correct values already exist on the driver side (_CHARGE_CUTOFF_RANGE/_DISCHARGE_CUTOFF_RANGE), and the capability set is the natural place to surface them, so every brand supplies its own window rather than inheriting Marstek's.