diff --git a/homeassistant/components/goodwe/number.py b/homeassistant/components/goodwe/number.py index cde4977e370f93..c91ff01cad6676 100644 --- a/homeassistant/components/goodwe/number.py +++ b/homeassistant/components/goodwe/number.py @@ -1,7 +1,7 @@ """GoodWe PV inverter numeric settings entities.""" from collections.abc import Awaitable, Callable -from dataclasses import dataclass +from dataclasses import dataclass, field import logging from goodwe import Inverter, InverterError @@ -11,13 +11,18 @@ NumberEntity, NumberEntityDescription, ) -from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfPower +from homeassistant.const import ( + PERCENTAGE, + EntityCategory, + UnitOfElectricCurrent, + UnitOfPower, +) from homeassistant.core import HomeAssistant from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from .const import DOMAIN -from .coordinator import GoodweConfigEntry +from .coordinator import GoodweConfigEntry, GoodweUpdateCoordinator _LOGGER = logging.getLogger(__name__) @@ -29,6 +34,9 @@ class GoodweNumberEntityDescription(NumberEntityDescription): getter: Callable[[Inverter], Awaitable[int]] setter: Callable[[Inverter, int], Awaitable[None]] filter: Callable[[Inverter], bool] + # Optional sensor id whose runtime value becomes native_max_value. + # Falls back to native_max_value from the description when not set or unavailable. + max_sensor_id: str | None = field(default=None) def _get_setting_unit(inverter: Inverter, setting: str) -> str: @@ -79,6 +87,38 @@ def _get_setting_unit(inverter: Inverter, setting: str) -> str: setter=lambda inv, val: inv.set_ongrid_battery_dod(val), filter=lambda inv: True, ), + GoodweNumberEntityDescription( + key="battery_charge_current", + translation_key="battery_charge_current", + icon="mdi:battery-arrow-up", + entity_category=EntityCategory.CONFIG, + device_class=NumberDeviceClass.CURRENT, + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + native_step=0.1, + native_min_value=0, + native_max_value=100, + max_sensor_id="battery_charge_limit", + getter=lambda inv: inv.read_setting("battery_charge_current"), + setter=lambda inv, val: inv.write_setting("battery_charge_current", val), + filter=lambda inv: "battery_charge_current" in {s.id_ for s in inv.settings()}, + ), + GoodweNumberEntityDescription( + key="battery_discharge_current", + translation_key="battery_discharge_current", + icon="mdi:battery-arrow-down", + entity_category=EntityCategory.CONFIG, + device_class=NumberDeviceClass.CURRENT, + native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, + native_step=0.1, + native_min_value=0, + native_max_value=100, + max_sensor_id="battery_discharge_limit", + getter=lambda inv: inv.read_setting("battery_discharge_current"), + setter=lambda inv, val: inv.write_setting("battery_discharge_current", val), + filter=lambda inv: ( + "battery_discharge_current" in {s.id_ for s in inv.settings()} + ), + ), ) @@ -89,6 +129,7 @@ async def async_setup_entry( ) -> None: """Set up the inverter select entities from a config entry.""" inverter = config_entry.runtime_data.inverter + coordinator = config_entry.runtime_data.coordinator device_info = config_entry.runtime_data.device_info entities = [] @@ -102,7 +143,9 @@ async def async_setup_entry( continue entities.append( - InverterNumberEntity(device_info, description, inverter, current_value) + InverterNumberEntity( + coordinator, device_info, description, inverter, current_value + ) ) async_add_entities(entities) @@ -117,6 +160,7 @@ class InverterNumberEntity(NumberEntity): def __init__( self, + coordinator: GoodweUpdateCoordinator, device_info: DeviceInfo, description: GoodweNumberEntityDescription, inverter: Inverter, @@ -128,6 +172,17 @@ def __init__( self._attr_device_info = device_info self._attr_native_value = float(current_value) self._inverter: Inverter = inverter + self._coordinator = coordinator + + @property + def native_max_value(self) -> float: + """Return max value, using the BMS-reported limit when available.""" + max_sensor_id = self.entity_description.max_sensor_id + if max_sensor_id is not None: + bms_limit = self._coordinator.sensor_value(max_sensor_id) + if bms_limit is not None and bms_limit > 0: + return float(bms_limit) + return self.entity_description.native_max_value or 100.0 async def async_update(self) -> None: """Get the current value from inverter.""" diff --git a/homeassistant/components/goodwe/strings.json b/homeassistant/components/goodwe/strings.json index fc8c3bccb2341d..eb9bf822a6d2ed 100644 --- a/homeassistant/components/goodwe/strings.json +++ b/homeassistant/components/goodwe/strings.json @@ -24,6 +24,12 @@ } }, "number": { + "battery_charge_current": { + "name": "Battery charge current limit" + }, + "battery_discharge_current": { + "name": "Battery discharge current limit" + }, "battery_discharge_depth": { "name": "Depth of discharge (on-grid)" },