From f3bb4188f0ffa34468b26ee82d1613fc26bfe9c0 Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Thu, 25 Dec 2025 20:49:06 -0800 Subject: [PATCH] Fix TOU status showing inverted values TOU status was always appearing as OFF regardless of actual state. Root cause: tou_status_to_python converter was using incorrect encoding: - Old (incorrect): 0 = OFF, 1 = ON - Correct: 1 = OFF, 2 = ON (standard OnOffFlag encoding) When device sent 2 (ON), converter returned False. When device sent 1 (OFF), it incorrectly returned True. Changes: - Removed duplicate tou_status_to_python() function - Updated TouStatus type to use device_bool_to_python (same as all OnOffFlag) - Removed redundant TOU status converter tests (already covered by device_bool) - Simplified converters module exports This eliminates code duplication since tou_status uses the same encoding as all other OnOffFlag fields in the device protocol. All 363 tests pass. --- src/nwp500/converters.py | 21 -------------- src/nwp500/models.py | 3 +- tests/test_model_converters.py | 53 ++-------------------------------- 3 files changed, 4 insertions(+), 73 deletions(-) diff --git a/src/nwp500/converters.py b/src/nwp500/converters.py index 2957381..48f10c7 100644 --- a/src/nwp500/converters.py +++ b/src/nwp500/converters.py @@ -13,7 +13,6 @@ __all__ = [ "device_bool_to_python", "device_bool_from_python", - "tou_status_to_python", "tou_override_to_python", "div_10", ] @@ -62,26 +61,6 @@ def device_bool_from_python(value: bool) -> int: return 2 if value else 1 -def tou_status_to_python(value: Any) -> bool: - """Convert Time of Use status to Python bool. - - Device representation: 0 = Off/False, 1 = On/True - - Args: - value: Device TOU status value. - - Returns: - Python boolean. - - Example: - >>> tou_status_to_python(1) - True - >>> tou_status_to_python(0) - False - """ - return bool(value == 1) - - def tou_override_to_python(value: Any) -> bool: """Convert TOU override status to Python bool. diff --git a/src/nwp500/models.py b/src/nwp500/models.py index d3c01e8..50796e7 100644 --- a/src/nwp500/models.py +++ b/src/nwp500/models.py @@ -17,7 +17,6 @@ div_10, enum_validator, tou_override_to_python, - tou_status_to_python, ) from .enums import ( CurrentOperationMode, @@ -56,7 +55,7 @@ Div10 = Annotated[float, BeforeValidator(div_10)] HalfCelsiusToF = Annotated[float, BeforeValidator(half_celsius_to_fahrenheit)] DeciCelsiusToF = Annotated[float, BeforeValidator(deci_celsius_to_fahrenheit)] -TouStatus = Annotated[bool, BeforeValidator(tou_status_to_python)] +TouStatus = Annotated[bool, BeforeValidator(device_bool_to_python)] TouOverride = Annotated[bool, BeforeValidator(tou_override_to_python)] VolumeCodeField = Annotated[ VolumeCode, BeforeValidator(enum_validator(VolumeCode)) diff --git a/tests/test_model_converters.py b/tests/test_model_converters.py index 050d1c5..c6396a7 100644 --- a/tests/test_model_converters.py +++ b/tests/test_model_converters.py @@ -2,10 +2,12 @@ Tests cover: - device_bool_to_python (device 1=False, 2=True) -- tou_status_to_python (TOU status encoding) - tou_override_to_python (TOU override status encoding) - div_10 (divide by 10 converter) - enum_validator (enum validation and conversion) + +Note: tou_status field uses device_bool_to_python +(same as all other OnOffFlag fields) """ import pytest @@ -15,7 +17,6 @@ div_10, enum_validator, tou_override_to_python, - tou_status_to_python, ) from nwp500.enums import DhwOperationSetting, OnOffFlag @@ -90,54 +91,6 @@ def test_off_value_variations(self, off_value): assert device_bool_to_python(off_value) is False -class TestTouStatusConverter: - """Test tou_status_to_python converter. - - TOU (Time of Use) status encoding converts device state to boolean. - Device: 1 = Enabled (True), anything else = Disabled (False) - NOTE: String values are NOT converted to int before comparison. - """ - - def test_tou_disabled(self): - """TOU disabled state: 0 = False.""" - result = tou_status_to_python(0) - assert isinstance(result, bool) - assert result is False - - def test_tou_enabled(self): - """TOU enabled state: 1 = True.""" - result = tou_status_to_python(1) - assert isinstance(result, bool) - assert result is True - - def test_string_disabled(self): - """String '0' = TOU disabled.""" - assert tou_status_to_python("0") is False - - def test_string_enabled(self): - """String '1' is not equal to int 1, so returns False.""" - # tou_status_to_python uses: bool(value == 1) - # String "1" != int 1, so result is False - assert tou_status_to_python("1") is False - - def test_invalid_value(self): - """Value other than 1 is treated as False.""" - assert tou_status_to_python(2) is False - assert tou_status_to_python(3) is False - assert tou_status_to_python(-1) is False - - @pytest.mark.parametrize("enabled_value", [1, 1.0]) - def test_enabled_variations(self, enabled_value): - """Test numeric variations of enabled (value == 1).""" - # Only numeric 1 and float 1.0 equal int 1 - assert tou_status_to_python(enabled_value) is True - - @pytest.mark.parametrize("disabled_value", [0, "0", 0.0, 2, 3, -1, "1"]) - def test_disabled_variations(self, disabled_value): - """Test various representations of disabled (value != 1).""" - assert tou_status_to_python(disabled_value) is False - - class TestTouOverrideConverter: """Test tou_override_to_python converter.