From ec6d3ca60bc97766da16b6a61128f7b1251d73ba Mon Sep 17 00:00:00 2001 From: mle Date: Tue, 9 Jan 2024 00:03:30 +0100 Subject: [PATCH] Fix deconding 0x55 as not-set value of EcoMode Recent firmwares seem to unset value/flag as 0x55 instead of 0. --- goodwe/sensor.py | 22 ++++++++++++++-------- tests/test_sensor.py | 3 +++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/goodwe/sensor.py b/goodwe/sensor.py index ba6f281..189302e 100644 --- a/goodwe/sensor.py +++ b/goodwe/sensor.py @@ -385,7 +385,9 @@ def __init__(self, id_: str, offset: int, name: str): self.soc: int = 100 # just to keep same API with V2 def __str__(self): - return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} {self.power}% {'On' if self.on_off != 0 else 'Off'}" + return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} " \ + f"{self.power}% " \ + f"{'On' if self.on_off != 0 else 'Off'}" def read_value(self, data: ProtocolResponse): self.start_h = read_byte(data) @@ -483,7 +485,9 @@ def __init__(self, id_: str, offset: int, name: str): # 2 bytes padding 0000 def __str__(self): - return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} {self.power}% (SoC {self.soc}%) {'On' if self.on_off != 0 else 'Off'}" + return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} " \ + f"{self.power}% (SoC {self.soc}%) " \ + f"{'On' if self.on_off == -1 else 'Off' if self.on_off == 0 else 'Unset'}" def read_value(self, data: ProtocolResponse): self.start_h = read_byte(data) @@ -499,7 +503,7 @@ def read_value(self, data: ProtocolResponse): if self.end_m < 0 or self.end_m > 59: raise ValueError(f"{self.id_}: end_m value {self.end_m} out of range.") self.on_off = read_byte(data) - if self.on_off not in (0, -1): + if self.on_off not in (0, -1, 85): raise ValueError(f"{self.id_}: on_off value {self.on_off} out of range.") self.day_bits = read_byte(data) self.days = decode_day_of_week(self.day_bits) @@ -539,7 +543,7 @@ def is_eco_charge_mode(self) -> bool: and self.start_m == 0 \ and self.end_h == 23 \ and self.end_m == 59 \ - and self.on_off != 0 \ + and self.on_off == -1 \ and self.day_bits == 127 \ and self.power < 0 @@ -549,7 +553,7 @@ def is_eco_discharge_mode(self) -> bool: and self.start_m == 0 \ and self.end_h == 23 \ and self.end_m == 59 \ - and self.on_off != 0 \ + and self.on_off == -1 \ and self.day_bits == 127 \ and self.power > 0 @@ -561,7 +565,7 @@ def as_eco_mode_v1(self) -> EcoModeV1: result.end_h = self.end_h result.end_m = self.end_m result.power = self.power - result.on_off = self.on_off + result.on_off = -1 if self.on_off == -1 else 0 result.day_bits = self.day_bits result.days = self.days return result @@ -584,7 +588,9 @@ def __init__(self, id_: str, offset: int, name: str): # 2 bytes padding 0000 def __str__(self): - return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} {self.import_power}kW (SoC {self.soc}%) {'On' if self.on_off == -4 else 'Off'}" + return f"{self.start_h}:{self.start_m}-{self.end_h}:{self.end_m} {self.days} " \ + f"{self.import_power}kW (SoC {self.soc}%) " \ + f"{'On' if self.on_off == -4 else 'Off' if self.on_off == 3 else 'Unset'}" def read_value(self, data: ProtocolResponse): self.start_h = read_byte(data) @@ -600,7 +606,7 @@ def read_value(self, data: ProtocolResponse): if self.end_m < 0 or self.end_m > 59: raise ValueError(f"{self.id_}: end_m value {self.end_m} out of range.") self.on_off = read_byte(data) - if self.on_off not in (-4, 3): + if self.on_off not in (-4, 3, 85): raise ValueError(f"{self.id_}: on_off value {self.on_off} out of range.") self.day_bits = read_byte(data) self.days = decode_day_of_week(self.day_bits) diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 175fe1e..1744e78 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -175,6 +175,9 @@ def test_eco_mode_v2(self): self.assertFalse(testee.read(data).is_eco_charge_mode()) self.assertFalse(testee.read(data).is_eco_discharge_mode()) + data = MockResponse("0000173b5500001400640000") + self.assertEqual("0:0-23:59 20% (SoC 100%) Unset", testee.read(data).__str__()) + def test_peak_shaving_mode(self): testee = PeakShavingMode("", 0, "")