From 702b53a7e00f22221b04998a80bfb24c12091a11 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 | 18 ++++++++++++------ tests/sample/et/GW5K-BT_device_info.hex | 1 + tests/test_et.py | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 tests/sample/et/GW5K-BT_device_info.hex diff --git a/goodwe/et.py b/goodwe/et.py index 35843dc..d74b041 100644 --- a/goodwe/et.py +++ b/goodwe/et.py @@ -533,8 +533,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: + 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: @@ -542,8 +545,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: + 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) @@ -556,7 +562,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.info("Battery values not supported, disabling further attempts.") self._has_battery = False else: raise ex @@ -567,7 +573,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.info("Battery 2 values not supported, disabling further attempts.") self._has_battery2 = False else: raise ex @@ -578,7 +584,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.info("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) @@ -596,7 +602,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.info("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 b2eeeb5..13f52ef 100644 --- a/tests/test_et.py +++ b/tests/test_et.py @@ -29,6 +29,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): @@ -1197,3 +1199,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(ModbusRtuReadCommand(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)