mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-22 19:23:34 +00:00
Use first known thermostat state as main state (#1054)
Instead of trying to use the first state when multiple are reported, iterate over the known states and pick the first matching. This will fix an issue where the device reports extra states (like `low_battery`) while having a known mode active. Related to https://github.com/home-assistant/core/issues/121335
This commit is contained in:
parent
239b5dd267
commit
a044063526
@ -4,15 +4,10 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from ...feature import Feature
|
from ...feature import Feature
|
||||||
from ..smartmodule import SmartModule
|
from ..smartmodule import SmartModule
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from ..smartdevice import SmartDevice
|
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@ -31,11 +26,11 @@ class TemperatureControl(SmartModule):
|
|||||||
|
|
||||||
REQUIRED_COMPONENT = "temp_control"
|
REQUIRED_COMPONENT = "temp_control"
|
||||||
|
|
||||||
def __init__(self, device: SmartDevice, module: str):
|
def _initialize_features(self):
|
||||||
super().__init__(device, module)
|
"""Initialize features after the initial update."""
|
||||||
self._add_feature(
|
self._add_feature(
|
||||||
Feature(
|
Feature(
|
||||||
device,
|
self._device,
|
||||||
id="target_temperature",
|
id="target_temperature",
|
||||||
name="Target temperature",
|
name="Target temperature",
|
||||||
container=self,
|
container=self,
|
||||||
@ -50,7 +45,7 @@ class TemperatureControl(SmartModule):
|
|||||||
# TODO: this might belong into its own module, temperature_correction?
|
# TODO: this might belong into its own module, temperature_correction?
|
||||||
self._add_feature(
|
self._add_feature(
|
||||||
Feature(
|
Feature(
|
||||||
device,
|
self._device,
|
||||||
id="temperature_offset",
|
id="temperature_offset",
|
||||||
name="Temperature offset",
|
name="Temperature offset",
|
||||||
container=self,
|
container=self,
|
||||||
@ -65,7 +60,7 @@ class TemperatureControl(SmartModule):
|
|||||||
|
|
||||||
self._add_feature(
|
self._add_feature(
|
||||||
Feature(
|
Feature(
|
||||||
device,
|
self._device,
|
||||||
id="state",
|
id="state",
|
||||||
name="State",
|
name="State",
|
||||||
container=self,
|
container=self,
|
||||||
@ -78,7 +73,7 @@ class TemperatureControl(SmartModule):
|
|||||||
|
|
||||||
self._add_feature(
|
self._add_feature(
|
||||||
Feature(
|
Feature(
|
||||||
device,
|
self._device,
|
||||||
id="thermostat_mode",
|
id="thermostat_mode",
|
||||||
name="Thermostat mode",
|
name="Thermostat mode",
|
||||||
container=self,
|
container=self,
|
||||||
@ -109,23 +104,24 @@ class TemperatureControl(SmartModule):
|
|||||||
if self._device.sys_info.get("frost_protection_on", False):
|
if self._device.sys_info.get("frost_protection_on", False):
|
||||||
return ThermostatState.Off
|
return ThermostatState.Off
|
||||||
|
|
||||||
states = self._device.sys_info["trv_states"]
|
states = self.states
|
||||||
|
|
||||||
# If the states is empty, the device is idling
|
# If the states is empty, the device is idling
|
||||||
if not states:
|
if not states:
|
||||||
return ThermostatState.Idle
|
return ThermostatState.Idle
|
||||||
|
|
||||||
|
# Discard known extra states, and report on unknown extra states
|
||||||
|
states.discard("low_battery")
|
||||||
if len(states) > 1:
|
if len(states) > 1:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning("Got multiple states: %s", states)
|
||||||
"Got multiple states (%s), using the first one: %s", states, states[0]
|
|
||||||
)
|
|
||||||
|
|
||||||
state = states[0]
|
# Return the first known state
|
||||||
try:
|
for state in ThermostatState:
|
||||||
return ThermostatState(state)
|
if state.value in states:
|
||||||
except: # noqa: E722
|
return state
|
||||||
_LOGGER.warning("Got unknown state: %s", state)
|
|
||||||
return ThermostatState.Unknown
|
_LOGGER.warning("Got unknown state: %s", states)
|
||||||
|
return ThermostatState.Unknown
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def allowed_temperature_range(self) -> tuple[int, int]:
|
def allowed_temperature_range(self) -> tuple[int, int]:
|
||||||
@ -147,6 +143,11 @@ class TemperatureControl(SmartModule):
|
|||||||
"""Return target temperature."""
|
"""Return target temperature."""
|
||||||
return self._device.sys_info["target_temp"]
|
return self._device.sys_info["target_temp"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def states(self) -> set:
|
||||||
|
"""Return thermostat states."""
|
||||||
|
return set(self._device.sys_info["trv_states"])
|
||||||
|
|
||||||
async def set_target_temperature(self, target: float):
|
async def set_target_temperature(self, target: float):
|
||||||
"""Set target temperature."""
|
"""Set target temperature."""
|
||||||
if (
|
if (
|
||||||
|
@ -94,7 +94,7 @@ async def test_temperature_offset(dev):
|
|||||||
),
|
),
|
||||||
pytest.param(
|
pytest.param(
|
||||||
ThermostatState.Heating,
|
ThermostatState.Heating,
|
||||||
[ThermostatState.Heating],
|
["heating"],
|
||||||
False,
|
False,
|
||||||
id="heating is heating",
|
id="heating is heating",
|
||||||
),
|
),
|
||||||
@ -135,3 +135,11 @@ async def test_thermostat_mode_warnings(dev, mode, states, msg, caplog):
|
|||||||
temp_module.data["trv_states"] = states
|
temp_module.data["trv_states"] = states
|
||||||
assert temp_module.mode is mode
|
assert temp_module.mode is mode
|
||||||
assert msg in caplog.text
|
assert msg in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
@thermostats_smart
|
||||||
|
async def test_thermostat_heating_with_low_battery(dev):
|
||||||
|
"""Test that mode is reported correctly with extra states."""
|
||||||
|
temp_module: TemperatureControl = dev.modules["TemperatureControl"]
|
||||||
|
temp_module.data["trv_states"] = ["low_battery", "heating"]
|
||||||
|
assert temp_module.mode is ThermostatState.Heating
|
||||||
|
Loading…
Reference in New Issue
Block a user