From fe72bb24f5629bf8706b9981c9b54dc661e0e283 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sat, 13 Apr 2024 11:11:27 +0100 Subject: [PATCH 1/2] Only disable remote control when the user disables force charge/discharge It turns out that strategy periods also enable remote control, and this is visible over modbus. If we tidy up and disable remote control, we can mess up an active strategy period. Fixes: #588 --- .../foxess_modbus/remote_control_manager.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/custom_components/foxess_modbus/remote_control_manager.py b/custom_components/foxess_modbus/remote_control_manager.py index af557a3..cc59cda 100644 --- a/custom_components/foxess_modbus/remote_control_manager.py +++ b/custom_components/foxess_modbus/remote_control_manager.py @@ -31,7 +31,7 @@ def __init__( self._mode = RemoteControlMode.DISABLE self._prev_mode = RemoteControlMode.DISABLE - self._remote_control_enabled: bool | None = None # None = we don't know + self._remote_control_enabled = False self._current_import_power = 0 # Set the first time that we enable force charge self._discharge_power: int | None = None self._charge_power: int | None = None @@ -297,7 +297,7 @@ async def _update_discharge(self) -> None: await self._write_active_power(export_power) async def _enable_remote_control(self, fallback_work_mode: WorkMode) -> None: - if self._remote_control_enabled in (None, False): + if not self._remote_control_enabled: self._remote_control_enabled = True timeout = self._poll_rate * 2 @@ -312,7 +312,12 @@ async def _enable_remote_control(self, fallback_work_mode: WorkMode) -> None: await self._controller.write_register(self._addresses.remote_enable, 1) async def _disable_remote_control(self, work_mode: WorkMode | None = None) -> None: - if self._remote_control_enabled in (None, True): + # The strategy periods feature of the foxess app use the remote control register internally. If we disable + # remote control when a strategy period is active, we'll end up disabling it. + # We therefore need to be a bit careful, and only disable remote control if we previously enabled it. + # If we did have it enabled, but then restarted, then we just need to let the watchdog catch it. + + if self._remote_control_enabled: self._remote_control_enabled = False await self._controller.write_register(self._addresses.remote_enable, 0) @@ -335,7 +340,7 @@ async def poll_complete_callback(self) -> None: await self._update() async def became_connected_callback(self) -> None: - self._remote_control_enabled = None # Don't know whether it's enabled or not + self._remote_control_enabled = False await self._update() def update_callback(self, changed_addresses: set[int]) -> None: From 1d276f33444c783b2bec99c956a4aa5a5e76b218 Mon Sep 17 00:00:00 2001 From: Antony Male Date: Sat, 13 Apr 2024 11:23:24 +0100 Subject: [PATCH 2/2] Correct work mode even if it changes while remote control is enabled --- .../foxess_modbus/remote_control_manager.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/custom_components/foxess_modbus/remote_control_manager.py b/custom_components/foxess_modbus/remote_control_manager.py index cc59cda..ee8befa 100644 --- a/custom_components/foxess_modbus/remote_control_manager.py +++ b/custom_components/foxess_modbus/remote_control_manager.py @@ -297,16 +297,16 @@ async def _update_discharge(self) -> None: await self._write_active_power(export_power) async def _enable_remote_control(self, fallback_work_mode: WorkMode) -> None: + # We set a fallback work mode so that the inverter still does "roughly" the right thing if we disconnect + # (This might not be available, e.g. on H1 LAN) + current_work_mode = self._read(self._addresses.work_mode, signed=False) + if current_work_mode != fallback_work_mode and self._addresses.work_mode is not None: + await self._controller.write_register(self._addresses.work_mode, int(fallback_work_mode)) + if not self._remote_control_enabled: self._remote_control_enabled = True timeout = self._poll_rate * 2 - # We set a fallback work mode so that the inverter still does "roughly" the right thing if we disconnect - # (This might not be available, e.g. on H1 LAN) - current_work_mode = self._read(self._addresses.work_mode, signed=False) - if current_work_mode != fallback_work_mode and self._addresses.work_mode is not None: - await self._controller.write_register(self._addresses.work_mode, int(fallback_work_mode)) - # We can't do multi-register writes to these registers await self._controller.write_register(self._addresses.timeout_set, timeout) await self._controller.write_register(self._addresses.remote_enable, 1)