diff --git a/custom_components/foxess_modbus/const.py b/custom_components/foxess_modbus/const.py index 733296d9..13f4ff4e 100755 --- a/custom_components/foxess_modbus/const.py +++ b/custom_components/foxess_modbus/const.py @@ -13,8 +13,7 @@ AUX = "AUX" LAN = "LAN" -# Inverter models. These need to match the string returned from the inverter -# Also matches config[INVERTER_BASE] +# Inverter models. These need to match config[INVERTER_BASE] H1 = "H1" AC1 = "AC1" AIO_H1 = "AIO-H1" @@ -22,6 +21,7 @@ H3 = "H3" AC3 = "AC3" AIO_H3 = "AIO-H3" +KUARA_H3 = "KUARA-H3" # Platforms SENSOR = "sensor" diff --git a/custom_components/foxess_modbus/entities/entity_descriptions.py b/custom_components/foxess_modbus/entities/entity_descriptions.py index bbcd5f7f..5f4385c5 100644 --- a/custom_components/foxess_modbus/entities/entity_descriptions.py +++ b/custom_components/foxess_modbus/entities/entity_descriptions.py @@ -13,6 +13,7 @@ from ..const import H1 from ..const import H3 from ..const import KH +from ..const import KUARA_H3 from .charge_periods import CHARGE_PERIODS from .entity_factory import EntityFactory from .inverter_model_spec import EntitySpec @@ -36,7 +37,7 @@ H1_SET = [H1, AIO_H1, AC1] -H3_SET = [*H3, AIO_H3, AC3] +H3_SET = [H3, AIO_H3, AC3, KUARA_H3] # TODO: There should be equivalent registers for the H3 somewhere BMS_CONNECT_STATE_ADDRESS = [ diff --git a/custom_components/foxess_modbus/inverter_profiles.py b/custom_components/foxess_modbus/inverter_profiles.py index 95fbc341..c488f85e 100644 --- a/custom_components/foxess_modbus/inverter_profiles.py +++ b/custom_components/foxess_modbus/inverter_profiles.py @@ -18,6 +18,7 @@ from .const import INVERTER_BASE from .const import INVERTER_CONN from .const import KH +from .const import KUARA_H3 from .const import LAN from .entities import invalid_ranges from .entities.charge_periods import CHARGE_PERIODS @@ -93,8 +94,9 @@ def create_charge_periods( class InverterModelProfile: """Describes the capabilities of an inverter model""" - def __init__(self, model: str) -> None: + def __init__(self, model: str, model_pattern: str) -> None: self.model = model + self.model_pattern = model_pattern self.connection_types: dict[str, InverterModelConnectionTypeProfile] = {} def add_connection_type( @@ -121,7 +123,7 @@ def add_connection_type( INVERTER_PROFILES = { x.model: x for x in [ - InverterModelProfile(H1) + InverterModelProfile(H1, r"^H1-") .add_connection_type( AUX, RegisterType.INPUT, @@ -131,7 +133,7 @@ def add_connection_type( LAN, RegisterType.HOLDING, ), - InverterModelProfile(AC1) + InverterModelProfile(AC1, r"^AC1-") .add_connection_type( AUX, RegisterType.INPUT, @@ -141,7 +143,7 @@ def add_connection_type( LAN, RegisterType.HOLDING, ), - InverterModelProfile(AIO_H1) + InverterModelProfile(AIO_H1, r"^AIO-H1-") .add_connection_type( AUX, RegisterType.INPUT, @@ -152,9 +154,9 @@ def add_connection_type( RegisterType.HOLDING, ), # The KH doesn't have a LAN port. It supports both input and holding over RS485 - InverterModelProfile(KH).add_connection_type(AUX, RegisterType.INPUT), + InverterModelProfile(KH, r"^KH-").add_connection_type(AUX, RegisterType.INPUT), # The H3 seems to use holding registers for everything - InverterModelProfile(H3) + InverterModelProfile(H3, r"^H3-") .add_connection_type( LAN, RegisterType.HOLDING, @@ -163,7 +165,7 @@ def add_connection_type( AUX, RegisterType.HOLDING, ), - InverterModelProfile(AC3) + InverterModelProfile(AC3, r"^AC3-") .add_connection_type( LAN, RegisterType.HOLDING, @@ -172,7 +174,7 @@ def add_connection_type( AUX, RegisterType.HOLDING, ), - InverterModelProfile(AIO_H3) + InverterModelProfile(AIO_H3, r"^AIO-H3-") .add_connection_type( AUX, RegisterType.HOLDING, @@ -181,6 +183,15 @@ def add_connection_type( LAN, RegisterType.HOLDING, ), + # Kuara 6.0-3-H: H3-6.0-E + # Kuara 8.0-3-H: H3-8.0-E + # Kuara 10.0-3-H: H3-10.0-E + # Kuara 12.0-3-H: H3-12.0-E + # I haven't seen any indication that these support a direct LAN connection + InverterModelProfile(KUARA_H3, r"^Kuara [^-]+-3-H$").add_connection_type( + AUX, + RegisterType.HOLDING, + ), ] } diff --git a/custom_components/foxess_modbus/modbus_controller.py b/custom_components/foxess_modbus/modbus_controller.py index 5deb2e67..3a288184 100644 --- a/custom_components/foxess_modbus/modbus_controller.py +++ b/custom_components/foxess_modbus/modbus_controller.py @@ -1,5 +1,6 @@ """Modbus controller""" import logging +import re import threading from contextlib import contextmanager from datetime import datetime @@ -347,7 +348,7 @@ async def autodetect(client: ModbusClient, slave: int, adapter_config: dict[str, # Take off tailing spaces and H3's leading space full_model = full_model.strip() for model in INVERTER_PROFILES.values(): - if full_model.startswith(model.model): + if re.match(model.model_pattern, full_model): _LOGGER.info("Autodetected inverter as '%s' (%s)", model.model, full_model) return model.model, full_model