From 196295a4072932044016f64af5d13288abcac7bd Mon Sep 17 00:00:00 2001 From: darkrain-nl Date: Wed, 30 Sep 2026 13:14:57 +0200 Subject: [PATCH] Use the library's string and pack component maps in Sofar (#183624) --- homeassistant/components/sofar/__init__.py | 9 ++++-- homeassistant/components/sofar/const.py | 4 --- homeassistant/components/sofar/coordinator.py | 8 +++--- homeassistant/components/sofar/sensor.py | 28 ++++++------------- 4 files changed, 19 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/sofar/__init__.py b/homeassistant/components/sofar/__init__.py index 4c83c7fec3aa..9832d9fd28ea 100644 --- a/homeassistant/components/sofar/__init__.py +++ b/homeassistant/components/sofar/__init__.py @@ -5,7 +5,11 @@ import logging from typing import TYPE_CHECKING from modbus_connection import ModbusError, ModbusTcpParams -from sofar_modbus.modern.device import SofarInverter, identify +from sofar_modbus.modern.device import ( + BATTERY_STRING_COMPONENTS, + SofarInverter, + identify, +) from sofar_modbus.tuning import LinkTuner, TimedUnit from homeassistant.components.modbus import async_get_unit @@ -26,7 +30,6 @@ from homeassistant.helpers import ( from homeassistant.helpers.typing import ConfigType from .const import ( - BATTERY_COMPONENTS, CONF_UNIT_ID, DOMAIN, METER_ENERGY, @@ -196,7 +199,7 @@ def _battery_pack_number(serial: str, identifier: str) -> int | None: return None suffix = identifier.removeprefix(prefix) number = int(suffix) if suffix.isdecimal() else None - return number if number in BATTERY_COMPONENTS else None + return number if number in BATTERY_STRING_COMPONENTS else None async def async_remove_config_entry_device( diff --git a/homeassistant/components/sofar/const.py b/homeassistant/components/sofar/const.py index 6e93f65e8a0d..f9a8b6e2501d 100644 --- a/homeassistant/components/sofar/const.py +++ b/homeassistant/components/sofar/const.py @@ -12,7 +12,3 @@ SETTINGS_SCAN_INTERVAL = 60 CONF_UNIT_ID = "unit_id" METER_ENERGY = "meter_energy" - -BATTERY_COMPONENTS = { - n: "battery_1_2" if n <= 2 else "battery_3_8" for n in range(1, 9) -} diff --git a/homeassistant/components/sofar/coordinator.py b/homeassistant/components/sofar/coordinator.py index c8e4aa6c2ebc..15503e6aa0d7 100644 --- a/homeassistant/components/sofar/coordinator.py +++ b/homeassistant/components/sofar/coordinator.py @@ -17,7 +17,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import ATTR_MANUFACTURER, BATTERY_COMPONENTS, DOMAIN +from .const import ATTR_MANUFACTURER, DOMAIN _LOGGER = logging.getLogger(__name__) @@ -176,10 +176,10 @@ class SofarRuntimeData: def pack_is_wired(self, number: int) -> bool: """Whether a pack has answered, so it physically exists.""" - component_name = BATTERY_COMPONENTS[number] - if component_name not in self.served_components: + string = self.readings.device.battery_string(number) + if string.component_name not in self.served_components: return False - return bool(self.readings.device.battery_string(number).voltage) + return bool(string.voltage) def coordinator_for(self, component: str) -> SofarDataUpdateCoordinator: """Which coordinator owns a given component's data.""" diff --git a/homeassistant/components/sofar/sensor.py b/homeassistant/components/sofar/sensor.py index b74e083d96ce..0960e64ef216 100644 --- a/homeassistant/components/sofar/sensor.py +++ b/homeassistant/components/sofar/sensor.py @@ -7,7 +7,11 @@ from enum import IntEnum from typing import cast, override from sofar_modbus.model import CorrectedTotal -from sofar_modbus.modern.device import SofarInverter +from sofar_modbus.modern.device import ( + BATTERY_STRING_COMPONENTS, + PV_STRING_COMPONENTS, + SofarInverter, +) from sofar_modbus.modern.enums import FeedinLimitationMode, PassiveModeTimeoutAction from homeassistant.components.sensor import ( @@ -34,7 +38,7 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.typing import StateType -from .const import BATTERY_COMPONENTS, METER_ENERGY +from .const import METER_ENERGY from .coordinator import SofarConfigEntry from .entity import SofarEntity, SofarEntityDescription @@ -62,7 +66,7 @@ async def async_setup_entry( wired = runtime_data.wired_packs new = { number - for number in BATTERY_COMPONENTS + for number in BATTERY_STRING_COMPONENTS if number not in wired and runtime_data.pack_is_wired(number) } if not new: @@ -166,20 +170,6 @@ class _PartMeasurement: value_fn: Callable[[SofarInverter, int], StateType] -# Which register block each string or pack is read from. -_PV_STRING_COMPONENTS = { - 1: "pv_1_2", - 2: "pv_1_2", - 3: "pv_3", - 4: "pv_4", - 5: "pv_5_6", - 6: "pv_5_6", - 7: "pv_7_8", - 8: "pv_7_8", - 9: "pv_9_10", - 10: "pv_9_10", -} - _PV_STRING_MEASUREMENTS = ( _PartMeasurement( key="pv_voltage", @@ -1717,5 +1707,5 @@ SENSOR_DESCRIPTIONS: tuple[SofarSensorDescription, ...] = ( ) SENSOR_DESCRIPTIONS += _part_sensors( - "pv_string", _PV_STRING_COMPONENTS, _PV_STRING_MEASUREMENTS -) + _part_sensors("battery", BATTERY_COMPONENTS, _BATTERY_MEASUREMENTS) + "pv_string", PV_STRING_COMPONENTS, _PV_STRING_MEASUREMENTS +) + _part_sensors("battery", BATTERY_STRING_COMPONENTS, _BATTERY_MEASUREMENTS)