Skip to content

Commit 184a002

Browse files
committed
fix: treat STATE_UNKNOWN as absent on the textual read properties
_optional_float() and as_list() already treated STATE_UNKNOWN as absent; low_voltage_mode, fan_mode and current_state did not. A device reporting the literal string "unknown" as its mode was classified as low voltage, and that string would have been echoed straight back into a write payload by async_set_low_voltage_state(). Route the textual properties through a new _optional_str() helper that mirrors _optional_float()'s STATE_UNKNOWN handling; is_low_voltage now derives from low_voltage_mode instead of duplicating the check.
1 parent 91284fb commit 184a002

2 files changed

Lines changed: 24 additions & 8 deletions

File tree

pyhilo/device/climate.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,20 +132,26 @@ def _optional_float(self, attribute: str) -> float | None:
132132
except (TypeError, ValueError):
133133
return None
134134

135+
def _optional_str(self, attribute: str) -> str | None:
136+
"""Return a textual reading, or None when absent or unusable."""
137+
value = self.get_value(attribute, None)
138+
if value is None or value == STATE_UNKNOWN:
139+
return None
140+
return str(value)
141+
135142
@property
136143
def is_low_voltage(self) -> bool:
137144
"""Whether this is a low voltage (24 V) thermostat.
138145
139146
Baseboard thermostats report none of the 24 V attributes and therefore
140147
keep their heat-only behaviour.
141148
"""
142-
return self.get_value(LOW_VOLTAGE_MODE, None) is not None
149+
return self.low_voltage_mode is not None
143150

144151
@property
145152
def low_voltage_mode(self) -> str | None:
146153
"""Operating mode reported by a 24 V thermostat, in Hilo's vocabulary."""
147-
value = self.get_value(LOW_VOLTAGE_MODE, None)
148-
return None if value is None else str(value)
154+
return self._optional_str(LOW_VOLTAGE_MODE)
149155

150156
@property
151157
def allowed_modes(self) -> list[str]:
@@ -155,8 +161,7 @@ def allowed_modes(self) -> list[str]:
155161
@property
156162
def fan_mode(self) -> str | None:
157163
"""Current fan mode, when the device reports one."""
158-
value = self.get_value("fan_mode", None)
159-
return None if value is None else str(value)
164+
return self._optional_str("fan_mode")
160165

161166
@property
162167
def allowed_fan_modes(self) -> list[str]:
@@ -170,8 +175,7 @@ def current_state(self) -> str | None:
170175
Exposed for consumers, but deliberately not mapped to hvac_action yet:
171176
its vocabulary has not been observed in enough operating conditions.
172177
"""
173-
value = self.get_value("current_state", None)
174-
return None if value is None else str(value)
178+
return self._optional_str("current_state")
175179

176180
@property
177181
def cool_setpoint(self) -> float | None:

tests/test_climate.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from unittest.mock import AsyncMock, MagicMock
22

3-
from pyhilo.const import HILO_READING_TYPES
3+
from pyhilo.const import HILO_READING_TYPES, STATE_UNKNOWN
44
from pyhilo.device import DeviceAttribute, DeviceReading, get_device_attributes
55
from pyhilo.device.climate import Climate, as_list
66

@@ -60,6 +60,9 @@ def test_baseboard_is_not_low_voltage(self):
6060
def test_device_reporting_a_mode_is_low_voltage(self):
6161
assert _climate(Thermostat24VMode="COOL").is_low_voltage is True
6262

63+
def test_device_reporting_unknown_mode_is_not_low_voltage(self):
64+
assert _climate(Thermostat24VMode=STATE_UNKNOWN).is_low_voltage is False
65+
6366

6467
class TestLowVoltageProperties:
6568
def test_reads_mode_and_vocabularies(self):
@@ -99,6 +102,15 @@ def test_humidity_rounds_rather_than_truncates(self):
99102
device = _climate(Thermostat24VMode="COOL", Humidity=57.8)
100103
assert device.current_humidity == 58
101104

105+
def test_unknown_state_is_treated_as_absent(self):
106+
device = _climate(
107+
Thermostat24VMode="COOL",
108+
FanMode=STATE_UNKNOWN,
109+
CurrentState=STATE_UNKNOWN,
110+
)
111+
assert device.fan_mode is None
112+
assert device.current_state is None
113+
102114

103115
class TestSetTemperature:
104116
async def test_low_voltage_device_delegates_to_low_voltage_state(self):

0 commit comments

Comments
 (0)