From 061d827e7c12c2ca419b70729a564b705e541223 Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Tue, 20 Aug 2024 21:00:29 +0930 Subject: [PATCH 1/6] Enable State of Charge support for Storion-S5 --- custom_components/alphaess/const.py | 2 +- custom_components/alphaess/coordinator.py | 14 ++++++++++++-- custom_components/alphaess/enums.py | 2 ++ custom_components/alphaess/manifest.json | 2 +- custom_components/alphaess/sensorlist.py | 7 +++++++ 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/custom_components/alphaess/const.py b/custom_components/alphaess/const.py index a340f06..7463b5d 100644 --- a/custom_components/alphaess/const.py +++ b/custom_components/alphaess/const.py @@ -7,7 +7,7 @@ DOMAIN = "alphaess" PLATFORMS = [Platform.SENSOR] SCAN_INTERVAL = timedelta(minutes=1) -THROTTLE_MULTIPLIER = 1.25 +THROTTLE_MULTIPLIER = 1.35 INVERTER_COUNT = 0 NAME = "Alpha ESS" diff --git a/custom_components/alphaess/coordinator.py b/custom_components/alphaess/coordinator.py index 3287262..1ff1372 100644 --- a/custom_components/alphaess/coordinator.py +++ b/custom_components/alphaess/coordinator.py @@ -27,7 +27,7 @@ async def safe_get(dictionary, key, default=0): class AlphaESSDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching data from the API.""" - def __init__(self, hass: HomeAssistant, client: alphaess.alphaess) -> None: + def __init__(self, hass: HomeAssistant, client: alphaess) -> None: """Initialize.""" super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL) self.api = client @@ -44,7 +44,7 @@ async def _async_update_data(self): LOCAL_INVERTER_COUNT = inverter_count try: - jsondata = await self.api.getdata(THROTTLE_MULTIPLIER * LOCAL_INVERTER_COUNT) + jsondata = await self.api.getdata(True, THROTTLE_MULTIPLIER * LOCAL_INVERTER_COUNT) if jsondata is not None: for invertor in jsondata: @@ -61,6 +61,7 @@ async def _async_update_data(self): _sumdata = invertor.get("SumData", {}) _onedateenergy = invertor.get("OneDateEnergy", {}) _powerdata = invertor.get("LastPower", {}) + _onedatepower = invertor.get("OneDayPower", {}) inverterdata["Total Load"] = await safe_get(_sumdata, "eload") inverterdata["Total Income"] = await safe_get(_sumdata, "totalIncome") @@ -88,6 +89,13 @@ async def _async_update_data(self): inverterdata["Instantaneous Battery SOC"] = _soc inverterdata["State of Charge"] = _soc + + if _onedatepower and _soc is 0: + first_entry = _onedatepower[0] + _cbat = first_entry.get("cbat", 0) + else: + _cbat = 0 + inverterdata["Instantaneous Battery I/O"] = await safe_get(_powerdata, "pbat") inverterdata["Instantaneous Load"] = await safe_get(_powerdata, "pload") inverterdata["Instantaneous Generation"] = await safe_get(_powerdata, "ppv") @@ -100,6 +108,8 @@ async def _async_update_data(self): inverterdata["Instantaneous Grid I/O L2"] = await safe_get(_gridpowerdetails, "pmeterL2") inverterdata["Instantaneous Grid I/O L3"] = await safe_get(_gridpowerdetails, "pmeterL3") + inverterdata["State of Charge CBAT"] = _cbat + self.data.update({invertor["sysSn"]: inverterdata}) return self.data diff --git a/custom_components/alphaess/enums.py b/custom_components/alphaess/enums.py index 30f12ce..3bb9e2e 100644 --- a/custom_components/alphaess/enums.py +++ b/custom_components/alphaess/enums.py @@ -14,6 +14,7 @@ class AlphaESSNames(str, Enum): GridToLoad = "Grid to Load" GridToBattery = "Grid to Battery" StateOfCharge = "State of Charge" + StateOfCharge_CBAT = "State of Charge" Charge = "Charge" Discharge = "Discharge" EVCharger = "EV Charger" @@ -36,3 +37,4 @@ class AlphaESSNames(str, Enum): usCapacity = "Maximum Battery Capacity" cobat = "Installed Capacity" surplusCobat = "Current Capacity" + diff --git a/custom_components/alphaess/manifest.json b/custom_components/alphaess/manifest.json index d451c67..d47af59 100644 --- a/custom_components/alphaess/manifest.json +++ b/custom_components/alphaess/manifest.json @@ -7,6 +7,6 @@ "documentation": "https://github.com/CharlesGillanders/homeassistant-alphaESS", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/CharlesGillanders/homeassistant-alphaESS/issues", - "requirements": ["alphaessopenapi==0.0.10"], + "requirements": ["alphaessopenapi==0.0.11"], "version": "0.5.2" } diff --git a/custom_components/alphaess/sensorlist.py b/custom_components/alphaess/sensorlist.py index 79b774c..d03bc47 100644 --- a/custom_components/alphaess/sensorlist.py +++ b/custom_components/alphaess/sensorlist.py @@ -223,6 +223,13 @@ ] LIMITED_SENSOR_DESCRIPTIONS: List[AlphaESSSensorDescription] = [ + AlphaESSSensorDescription( + key=AlphaESSNames.StateOfCharge_CBAT, + name="State of Charge", + native_unit_of_measurement=PERCENTAGE, + device_class=SensorDeviceClass.BATTERY, + state_class=SensorStateClass.MEASUREMENT, + ), AlphaESSSensorDescription( key=AlphaESSNames.SolarProduction, name="Solar Production", From 40e7175722ec6a12cf4fc90bc019e96da1cf1c73 Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Tue, 20 Aug 2024 21:04:02 +0930 Subject: [PATCH 2/6] Bug fix --- custom_components/alphaess/coordinator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/alphaess/coordinator.py b/custom_components/alphaess/coordinator.py index 1ff1372..a472279 100644 --- a/custom_components/alphaess/coordinator.py +++ b/custom_components/alphaess/coordinator.py @@ -27,7 +27,7 @@ async def safe_get(dictionary, key, default=0): class AlphaESSDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching data from the API.""" - def __init__(self, hass: HomeAssistant, client: alphaess) -> None: + def __init__(self, hass: HomeAssistant, client: alphaess.alphaess) -> None: """Initialize.""" super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL) self.api = client From 2bb834646f8d5c24b04e35bdff51771a7d5fea41 Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Tue, 20 Aug 2024 23:02:53 +0930 Subject: [PATCH 3/6] Bug fix --- custom_components/alphaess/coordinator.py | 7 +++---- custom_components/alphaess/enums.py | 1 - custom_components/alphaess/sensorlist.py | 9 +-------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/custom_components/alphaess/coordinator.py b/custom_components/alphaess/coordinator.py index a472279..7b3d19e 100644 --- a/custom_components/alphaess/coordinator.py +++ b/custom_components/alphaess/coordinator.py @@ -88,13 +88,14 @@ async def _async_update_data(self): _pvpowerdetails = _powerdata.get("ppvDetail", {}) inverterdata["Instantaneous Battery SOC"] = _soc - inverterdata["State of Charge"] = _soc - if _onedatepower and _soc is 0: + if _onedatepower and _soc is not 0: first_entry = _onedatepower[0] _cbat = first_entry.get("cbat", 0) + inverterdata["State of Charge"] = _cbat else: _cbat = 0 + inverterdata["State of Charge"] = _cbat inverterdata["Instantaneous Battery I/O"] = await safe_get(_powerdata, "pbat") inverterdata["Instantaneous Load"] = await safe_get(_powerdata, "pload") @@ -108,8 +109,6 @@ async def _async_update_data(self): inverterdata["Instantaneous Grid I/O L2"] = await safe_get(_gridpowerdetails, "pmeterL2") inverterdata["Instantaneous Grid I/O L3"] = await safe_get(_gridpowerdetails, "pmeterL3") - inverterdata["State of Charge CBAT"] = _cbat - self.data.update({invertor["sysSn"]: inverterdata}) return self.data diff --git a/custom_components/alphaess/enums.py b/custom_components/alphaess/enums.py index 3bb9e2e..d804997 100644 --- a/custom_components/alphaess/enums.py +++ b/custom_components/alphaess/enums.py @@ -14,7 +14,6 @@ class AlphaESSNames(str, Enum): GridToLoad = "Grid to Load" GridToBattery = "Grid to Battery" StateOfCharge = "State of Charge" - StateOfCharge_CBAT = "State of Charge" Charge = "Charge" Discharge = "Discharge" EVCharger = "EV Charger" diff --git a/custom_components/alphaess/sensorlist.py b/custom_components/alphaess/sensorlist.py index d03bc47..df6e86a 100644 --- a/custom_components/alphaess/sensorlist.py +++ b/custom_components/alphaess/sensorlist.py @@ -59,13 +59,6 @@ device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), - AlphaESSSensorDescription( - key=AlphaESSNames.StateOfCharge, - name="State of Charge", - native_unit_of_measurement=PERCENTAGE, - device_class=SensorDeviceClass.BATTERY, - state_class=SensorStateClass.MEASUREMENT, - ), AlphaESSSensorDescription( key=AlphaESSNames.Charge, name="Charge", @@ -224,7 +217,7 @@ LIMITED_SENSOR_DESCRIPTIONS: List[AlphaESSSensorDescription] = [ AlphaESSSensorDescription( - key=AlphaESSNames.StateOfCharge_CBAT, + key=AlphaESSNames.StateOfCharge, name="State of Charge", native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.BATTERY, From 4caac7d7d7160907bc8f52ce8080eff759abf135 Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Tue, 20 Aug 2024 23:04:35 +0930 Subject: [PATCH 4/6] lint fix --- custom_components/alphaess/manifest.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/custom_components/alphaess/manifest.json b/custom_components/alphaess/manifest.json index 35f8368..b6924fc 100644 --- a/custom_components/alphaess/manifest.json +++ b/custom_components/alphaess/manifest.json @@ -1,12 +1,20 @@ { "domain": "alphaess", "name": "Alpha ESS", - "after_dependencies": ["rest"], - "codeowners": ["@CharlesGillanders"], + "after_dependencies": [ + "rest" + ], + "codeowners": [ + "@CharlesGillanders" + ], "config_flow": true, "documentation": "https://github.com/CharlesGillanders/homeassistant-alphaESS", "iot_class": "cloud_polling", "issue_tracker": "https://github.com/CharlesGillanders/homeassistant-alphaESS/issues", - "requirements": ["alphaessopenapi==0.0.11"], + "requirements": [ + "alphaessopenapi==0.0.11" + ], "version": "0.5.3" +} + From 14d57deaf921fa12ac72cad30a03b127a0deb299 Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Wed, 21 Aug 2024 00:54:29 +0930 Subject: [PATCH 5/6] Add throttle only for "Storion-S5" --- custom_components/alphaess/const.py | 16 ++++++++++++++++ custom_components/alphaess/coordinator.py | 17 +++++++++++------ custom_components/alphaess/manifest.json | 5 +++-- custom_components/alphaess/sensor.py | 3 ++- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/custom_components/alphaess/const.py b/custom_components/alphaess/const.py index 7463b5d..94c2910 100644 --- a/custom_components/alphaess/const.py +++ b/custom_components/alphaess/const.py @@ -9,6 +9,7 @@ SCAN_INTERVAL = timedelta(minutes=1) THROTTLE_MULTIPLIER = 1.35 INVERTER_COUNT = 0 +INVERTER_LIST = [] NAME = "Alpha ESS" ISSUE_URL = "https://github.com/CharlesGillanders/homeassistant-alphaESS/issues" @@ -30,3 +31,18 @@ def increment_inverter_count(): def get_inverter_count(): return INVERTER_COUNT + + +# If no Storion-S5, make the throttle amount smaller +def set_throttle_count_lower(): + global THROTTLE_MULTIPLIER + THROTTLE_MULTIPLIER = 1.25 + + +def add_inverter_to_list(inverter): + global INVERTER_LIST + INVERTER_LIST.append(inverter) + + +def get_inverter_list(): + return INVERTER_LIST diff --git a/custom_components/alphaess/coordinator.py b/custom_components/alphaess/coordinator.py index 7b3d19e..23f86d4 100644 --- a/custom_components/alphaess/coordinator.py +++ b/custom_components/alphaess/coordinator.py @@ -7,7 +7,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import DOMAIN, SCAN_INTERVAL, THROTTLE_MULTIPLIER, get_inverter_count +from .const import DOMAIN, SCAN_INTERVAL, THROTTLE_MULTIPLIER, get_inverter_count, set_throttle_count_lower, \ + get_inverter_list _LOGGER: logging.Logger = logging.getLogger(__package__) @@ -32,11 +33,18 @@ def __init__(self, hass: HomeAssistant, client: alphaess.alphaess) -> None: super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL) self.api = client self.update_method = self._async_update_data + self.has_throttle = True self.data: dict[str, dict[str, float]] = {} + self.LOCAL_INVERTER_COUNT = 0 async def _async_update_data(self): """Update data via library.""" + model_list = get_inverter_list() + if "Storion-S5" not in model_list and len(model_list) > 0: + self.has_throttle = False + set_throttle_count_lower() + inverter_count = get_inverter_count() if inverter_count == 1: LOCAL_INVERTER_COUNT = 0 @@ -44,7 +52,7 @@ async def _async_update_data(self): LOCAL_INVERTER_COUNT = inverter_count try: - jsondata = await self.api.getdata(True, THROTTLE_MULTIPLIER * LOCAL_INVERTER_COUNT) + jsondata = await self.api.getdata(self.has_throttle, THROTTLE_MULTIPLIER * LOCAL_INVERTER_COUNT) if jsondata is not None: for invertor in jsondata: @@ -89,13 +97,10 @@ async def _async_update_data(self): inverterdata["Instantaneous Battery SOC"] = _soc - if _onedatepower and _soc is not 0: + if _onedatepower and _soc is 0: first_entry = _onedatepower[0] _cbat = first_entry.get("cbat", 0) inverterdata["State of Charge"] = _cbat - else: - _cbat = 0 - inverterdata["State of Charge"] = _cbat inverterdata["Instantaneous Battery I/O"] = await safe_get(_powerdata, "pbat") inverterdata["Instantaneous Load"] = await safe_get(_powerdata, "pload") diff --git a/custom_components/alphaess/manifest.json b/custom_components/alphaess/manifest.json index b6924fc..32f1efc 100644 --- a/custom_components/alphaess/manifest.json +++ b/custom_components/alphaess/manifest.json @@ -5,7 +5,8 @@ "rest" ], "codeowners": [ - "@CharlesGillanders" + "@CharlesGillanders", + "@Poshy163" ], "config_flow": true, "documentation": "https://github.com/CharlesGillanders/homeassistant-alphaESS", @@ -14,7 +15,7 @@ "requirements": [ "alphaessopenapi==0.0.11" ], - "version": "0.5.3" + "version": "0.5.4" } diff --git a/custom_components/alphaess/sensor.py b/custom_components/alphaess/sensor.py index 2874b9a..7a0a2f3 100644 --- a/custom_components/alphaess/sensor.py +++ b/custom_components/alphaess/sensor.py @@ -13,7 +13,7 @@ from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN, increment_inverter_count +from .const import DOMAIN, increment_inverter_count, add_inverter_to_list from .coordinator import AlphaESSDataUpdateCoordinator _LOGGER: logging.Logger = logging.getLogger(__package__) @@ -39,6 +39,7 @@ async def async_setup_entry(hass, entry, async_add_entities) -> None: for serial, data in coordinator.data.items(): model = data.get("Model") _LOGGER.info(f"Serial: {serial}, Model: {model}") + add_inverter_to_list(model) increment_inverter_count() if model == "Storion-S5": From bd47d18618733a5fcd63228f88380e576fd8461a Mon Sep 17 00:00:00 2001 From: Joshua Leaper Date: Wed, 21 Aug 2024 01:32:46 +0930 Subject: [PATCH 6/6] Small fixes --- custom_components/alphaess/__init__.py | 10 +++++----- custom_components/alphaess/coordinator.py | 3 +-- custom_components/alphaess/enums.py | 1 - custom_components/alphaess/sensorlist.py | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/custom_components/alphaess/__init__.py b/custom_components/alphaess/__init__.py index f8d04b6..1e1d931 100644 --- a/custom_components/alphaess/__init__.py +++ b/custom_components/alphaess/__init__.py @@ -43,10 +43,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: client = alphaess.alphaess(entry.data["AppID"], entry.data["AppSecret"]) - coordinator = AlphaESSDataUpdateCoordinator(hass, client=client) - await coordinator.async_config_entry_first_refresh() + _coordinator = AlphaESSDataUpdateCoordinator(hass, client=client) + await _coordinator.async_config_entry_first_refresh() - hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = _coordinator await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) @@ -54,13 +54,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_battery_charge_handler(call): await client.updateChargeConfigInfo(call.data.get('serial'), call.data.get('chargestopsoc'), - int(call.data.get('enabled') == True), call.data.get('cp1end'), + int(call.data.get('enabled') is True), call.data.get('cp1end'), call.data.get('cp2end'), call.data.get('cp1start'), call.data.get('cp2start')) async def async_battery_discharge_handler(call): await client.updateDisChargeConfigInfo(call.data.get('serial'), call.data.get('dischargecutoffsoc'), - int(call.data.get('enabled') == True), call.data.get('dp1end'), + int(call.data.get('enabled') is True), call.data.get('dp1end'), call.data.get('dp2end'), call.data.get('dp1start'), call.data.get('dp2start')) diff --git a/custom_components/alphaess/coordinator.py b/custom_components/alphaess/coordinator.py index 23f86d4..d671593 100644 --- a/custom_components/alphaess/coordinator.py +++ b/custom_components/alphaess/coordinator.py @@ -7,8 +7,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import DOMAIN, SCAN_INTERVAL, THROTTLE_MULTIPLIER, get_inverter_count, set_throttle_count_lower, \ - get_inverter_list +from .const import DOMAIN, SCAN_INTERVAL, THROTTLE_MULTIPLIER, get_inverter_count, set_throttle_count_lower, get_inverter_list _LOGGER: logging.Logger = logging.getLogger(__package__) diff --git a/custom_components/alphaess/enums.py b/custom_components/alphaess/enums.py index d804997..30f12ce 100644 --- a/custom_components/alphaess/enums.py +++ b/custom_components/alphaess/enums.py @@ -36,4 +36,3 @@ class AlphaESSNames(str, Enum): usCapacity = "Maximum Battery Capacity" cobat = "Installed Capacity" surplusCobat = "Current Capacity" - diff --git a/custom_components/alphaess/sensorlist.py b/custom_components/alphaess/sensorlist.py index df6e86a..abdfea8 100644 --- a/custom_components/alphaess/sensorlist.py +++ b/custom_components/alphaess/sensorlist.py @@ -338,4 +338,4 @@ device_class=SensorDeviceClass.ENERGY, entity_category=EntityCategory.DIAGNOSTIC ) -] \ No newline at end of file +]