Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions homeassistant/components/goodwe/number.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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__)

Expand All @@ -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:
Expand Down Expand Up @@ -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()}
),
),
)


Expand All @@ -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 = []
Expand All @@ -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)
Expand All @@ -117,6 +160,7 @@ class InverterNumberEntity(NumberEntity):

def __init__(
self,
coordinator: GoodweUpdateCoordinator,
device_info: DeviceInfo,
description: GoodweNumberEntityDescription,
inverter: Inverter,
Expand All @@ -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."""
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/goodwe/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -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)"
},
Expand Down
Loading