From e796f22f9ff28b06507d89d2b3406d4a8959088a Mon Sep 17 00:00:00 2001 From: mle Date: Wed, 8 May 2024 18:38:57 +0200 Subject: [PATCH] Fix setup of BT inverters BT inverters do not respond to 47547 register read command with 'ILLEGAL DATA ADDRESS', but they do not respond at all. Adjust the EcoModeV2 setup to consider this behavior. --- goodwe/et.py | 20 +++++++++++++------- tests/sample/et/GW5K-BT_device_info.hex | 1 + tests/test_et.py | 25 +++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 tests/sample/et/GW5K-BT_device_info.hex diff --git a/goodwe/et.py b/goodwe/et.py index 9f5c6f3..b38e815 100644 --- a/goodwe/et.py +++ b/goodwe/et.py @@ -3,7 +3,7 @@ import logging from typing import Tuple -from .exceptions import RequestRejectedException +from .exceptions import RequestFailedException, RequestRejectedException from .inverter import Inverter from .inverter import OperationMode from .inverter import SensorKind as Kind @@ -482,8 +482,11 @@ async def read_device_info(self): self._settings.update({s.id_: s for s in self.__settings_arm_fw_19}) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.debug("Cannot read EcoModeV2 settings, using to EcoModeV1.") + logger.debug("EcoModeV2 settings not supported, switching to EcoModeV1.") self._has_eco_mode_v2 = False + except RequestFailedException as ex: + logger.debug("Cannot read EcoModeV2 settings, switching to EcoModeV1.") + self._has_eco_mode_v2 = False # Check and add Peak Shaving settings added in (ETU fw 22) try: @@ -491,8 +494,11 @@ async def read_device_info(self): self._settings.update({s.id_: s for s in self.__settings_arm_fw_22}) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.debug("Cannot read PeakShaving setting, disabling it.") + logger.debug("PeakShaving setting not supported, disabling it.") self._has_peak_shaving = False + except RequestFailedException as ex: + logger.debug("Cannot read _has_peak_shaving settings, disabling it.") + self._has_peak_shaving = False async def read_runtime_data(self) -> Dict[str, Any]: response = await self._read_from_socket(self._READ_RUNNING_DATA) @@ -505,7 +511,7 @@ async def read_runtime_data(self) -> Dict[str, Any]: data.update(self._map_response(response, self._sensors_battery)) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.warning("Cannot read battery values, disabling further attempts.") + logger.warning("Battery values not supported, disabling further attempts.") self._has_battery = False else: raise ex @@ -516,7 +522,7 @@ async def read_runtime_data(self) -> Dict[str, Any]: self._map_response(response, self._sensors_battery2)) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.warning("Cannot read battery 2 values, disabling further attempts.") + logger.warning("Battery 2 values not supported, disabling further attempts.") self._has_battery2 = False else: raise ex @@ -527,7 +533,7 @@ async def read_runtime_data(self) -> Dict[str, Any]: data.update(self._map_response(response, self._sensors_meter)) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.warning("Cannot read extended meter values, disabling further attempts.") + logger.warning("Extended meter values not supported, disabling further attempts.") self._has_meter_extended = False self._sensors_meter = tuple(filter(self._not_extended_meter, self._sensors_meter)) response = await self._read_from_socket(self._READ_METER_DATA) @@ -545,7 +551,7 @@ async def read_runtime_data(self) -> Dict[str, Any]: data.update(self._map_response(response, self._sensors_mppt)) except RequestRejectedException as ex: if ex.message == 'ILLEGAL DATA ADDRESS': - logger.warning("Cannot read MPPT values, disabling further attempts.") + logger.warning("MPPT values not supported, disabling further attempts.") self._has_mppt = False else: raise ex diff --git a/tests/sample/et/GW5K-BT_device_info.hex b/tests/sample/et/GW5K-BT_device_info.hex new file mode 100644 index 0000000..3bb36a2 --- /dev/null +++ b/tests/sample/et/GW5K-BT_device_info.hex @@ -0,0 +1 @@ +aa55f703420000138800fe393530303042545532303357303030304757354b2d425420202000030003007c000b009330343032392d30332d53313030323034312d31312d533030828f \ No newline at end of file diff --git a/tests/test_et.py b/tests/test_et.py index 8359564..d8e8d3b 100644 --- a/tests/test_et.py +++ b/tests/test_et.py @@ -28,6 +28,8 @@ async def _read_from_socket(self, command: ProtocolCommand) -> ProtocolResponse: if filename is not None: if 'ILLEGAL DATA ADDRESS' == filename: raise RequestRejectedException('ILLEGAL DATA ADDRESS') + if 'NO RESPONSE' == filename: + raise RequestFailedException() with open(root_dir + '/sample/et/' + filename, 'r') as f: response = bytes.fromhex(f.read()) if not command.validator(response): @@ -1196,3 +1198,26 @@ def test_GW29K9_ET_runtime_data(self): self.assertSensor('apparent_power3', 0, 'VA', data) self.assertFalse(self.sensor_map, f"Some sensors were not tested {self.sensor_map}") + + +class GW5K_BT_Test(EtMock): + + def __init__(self, methodName='runTest'): + EtMock.__init__(self, methodName) + self.mock_response(self._READ_DEVICE_VERSION_INFO, 'GW5K-BT_device_info.hex') + self.mock_response(ModbusReadCommand(self.comm_addr, 47547, 6), 'NO RESPONSE') + + def test_GW5K_BT_device_info(self): + self.loop.run_until_complete(self.read_device_info()) + self.assertEqual('GW5K-BT', self.model_name) + self.assertEqual('95000BTU203W0000', self.serial_number) + self.assertEqual(5000, self.rated_power) + self.assertEqual(0, self.modbus_version) + self.assertEqual(254, self.ac_output_type) + self.assertEqual(3, self.dsp1_version) + self.assertEqual(3, self.dsp2_version) + self.assertEqual(124, self.dsp_svn_version) + self.assertEqual(11, self.arm_version) + self.assertEqual(147, self.arm_svn_version) + self.assertEqual('04029-03-S10', self.firmware) + self.assertEqual('02041-11-S00', self.arm_firmware)