mirror of
https://github.com/home-assistant/core.git
synced 2025-04-30 12:17:52 +00:00
Store Shelly climate last_target_temp
value in restore extra data (#86482)
fixes undefined
This commit is contained in:
parent
b89a51c63d
commit
9a68f0abe8
@ -2,6 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
from dataclasses import asdict, dataclass
|
||||||
from typing import Any, cast
|
from typing import Any, cast
|
||||||
|
|
||||||
from aioshelly.block_device import Block
|
from aioshelly.block_device import Block
|
||||||
@ -27,7 +28,7 @@ from homeassistant.helpers.entity_registry import (
|
|||||||
async_entries_for_config_entry,
|
async_entries_for_config_entry,
|
||||||
async_get as er_async_get,
|
async_get as er_async_get,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.restore_state import RestoreEntity
|
from homeassistant.helpers.restore_state import ExtraStoredData, RestoreEntity
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
from homeassistant.util.unit_conversion import TemperatureConverter
|
from homeassistant.util.unit_conversion import TemperatureConverter
|
||||||
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
||||||
@ -100,6 +101,17 @@ def async_restore_climate_entities(
|
|||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ShellyClimateExtraStoredData(ExtraStoredData):
|
||||||
|
"""Object to hold extra stored data."""
|
||||||
|
|
||||||
|
last_target_temp: float | None = None
|
||||||
|
|
||||||
|
def as_dict(self) -> dict[str, Any]:
|
||||||
|
"""Return a dict representation of the text data."""
|
||||||
|
return asdict(self)
|
||||||
|
|
||||||
|
|
||||||
class BlockSleepingClimate(
|
class BlockSleepingClimate(
|
||||||
CoordinatorEntity[ShellyBlockCoordinator], RestoreEntity, ClimateEntity
|
CoordinatorEntity[ShellyBlockCoordinator], RestoreEntity, ClimateEntity
|
||||||
):
|
):
|
||||||
@ -131,14 +143,7 @@ class BlockSleepingClimate(
|
|||||||
self.last_state: State | None = None
|
self.last_state: State | None = None
|
||||||
self.last_state_attributes: Mapping[str, Any]
|
self.last_state_attributes: Mapping[str, Any]
|
||||||
self._preset_modes: list[str] = []
|
self._preset_modes: list[str] = []
|
||||||
if coordinator.hass.config.units is US_CUSTOMARY_SYSTEM:
|
self._last_target_temp = SHTRV_01_TEMPERATURE_SETTINGS["default"]
|
||||||
self._last_target_temp = TemperatureConverter.convert(
|
|
||||||
SHTRV_01_TEMPERATURE_SETTINGS["default"],
|
|
||||||
UnitOfTemperature.CELSIUS,
|
|
||||||
UnitOfTemperature.FAHRENHEIT,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self._last_target_temp = SHTRV_01_TEMPERATURE_SETTINGS["default"]
|
|
||||||
|
|
||||||
if self.block is not None and self.device_block is not None:
|
if self.block is not None and self.device_block is not None:
|
||||||
self._unique_id = f"{self.coordinator.mac}-{self.block.description}"
|
self._unique_id = f"{self.coordinator.mac}-{self.block.description}"
|
||||||
@ -154,6 +159,11 @@ class BlockSleepingClimate(
|
|||||||
|
|
||||||
self._channel = cast(int, self._unique_id.split("_")[1])
|
self._channel = cast(int, self._unique_id.split("_")[1])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def extra_restore_state_data(self) -> ShellyClimateExtraStoredData:
|
||||||
|
"""Return text specific state data to be restored."""
|
||||||
|
return ShellyClimateExtraStoredData(self._last_target_temp)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str:
|
def unique_id(self) -> str:
|
||||||
"""Set unique id of entity."""
|
"""Set unique id of entity."""
|
||||||
@ -308,7 +318,6 @@ class BlockSleepingClimate(
|
|||||||
LOGGER.info("Restoring entity %s", self.name)
|
LOGGER.info("Restoring entity %s", self.name)
|
||||||
|
|
||||||
last_state = await self.async_get_last_state()
|
last_state = await self.async_get_last_state()
|
||||||
|
|
||||||
if last_state is not None:
|
if last_state is not None:
|
||||||
self.last_state = last_state
|
self.last_state = last_state
|
||||||
self.last_state_attributes = self.last_state.attributes
|
self.last_state_attributes = self.last_state.attributes
|
||||||
@ -316,6 +325,10 @@ class BlockSleepingClimate(
|
|||||||
list, self.last_state.attributes.get("preset_modes")
|
list, self.last_state.attributes.get("preset_modes")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
last_extra_data = await self.async_get_last_extra_data()
|
||||||
|
if last_extra_data is not None:
|
||||||
|
self._last_target_temp = last_extra_data.as_dict()["last_target_temp"]
|
||||||
|
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@ -25,7 +25,7 @@ from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
|||||||
|
|
||||||
from . import init_integration, register_device, register_entity
|
from . import init_integration, register_device, register_entity
|
||||||
|
|
||||||
from tests.common import mock_restore_cache
|
from tests.common import mock_restore_cache, mock_restore_cache_with_extra_data
|
||||||
|
|
||||||
SENSOR_BLOCK_ID = 3
|
SENSOR_BLOCK_ID = 3
|
||||||
DEVICE_BLOCK_ID = 4
|
DEVICE_BLOCK_ID = 4
|
||||||
@ -191,19 +191,25 @@ async def test_block_restored_climate(hass, mock_block_device, device_reg, monke
|
|||||||
"sensor_0",
|
"sensor_0",
|
||||||
entry,
|
entry,
|
||||||
)
|
)
|
||||||
mock_restore_cache(hass, [State(entity_id, HVACMode.HEAT)])
|
attrs = {"current_temperature": 20.5, "temperature": 4.0}
|
||||||
|
extra_data = {"last_target_temp": 22.0}
|
||||||
|
mock_restore_cache_with_extra_data(
|
||||||
|
hass, ((State(entity_id, HVACMode.OFF, attributes=attrs), extra_data),)
|
||||||
|
)
|
||||||
|
|
||||||
monkeypatch.setattr(mock_block_device, "initialized", False)
|
monkeypatch.setattr(mock_block_device, "initialized", False)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
|
assert hass.states.get(entity_id).attributes.get("temperature") == 4.0
|
||||||
|
|
||||||
# Partial update, should not change state
|
# Partial update, should not change state
|
||||||
mock_block_device.mock_update()
|
mock_block_device.mock_update()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
|
assert hass.states.get(entity_id).attributes.get("temperature") == 4.0
|
||||||
|
|
||||||
# Make device online
|
# Make device online
|
||||||
monkeypatch.setattr(mock_block_device, "initialized", True)
|
monkeypatch.setattr(mock_block_device, "initialized", True)
|
||||||
@ -211,6 +217,24 @@ async def test_block_restored_climate(hass, mock_block_device, device_reg, monke
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.OFF
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
|
assert hass.states.get(entity_id).attributes.get("temperature") == 4.0
|
||||||
|
|
||||||
|
# Test set hvac mode heat, target temp should be set to last target temp (22)
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_HVAC_MODE,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.HEAT},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
mock_block_device.http_request.assert_called_once_with(
|
||||||
|
"get", "thermostat/0", {"target_t_enabled": 1, "target_t": 22.0}
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "targetTemp", 22.0)
|
||||||
|
mock_block_device.mock_update()
|
||||||
|
state = hass.states.get(ENTITY_ID)
|
||||||
|
assert state.state == HVACMode.HEAT
|
||||||
|
assert hass.states.get(entity_id).attributes.get("temperature") == 22.0
|
||||||
|
|
||||||
|
|
||||||
async def test_block_restored_climate_us_customery(
|
async def test_block_restored_climate_us_customery(
|
||||||
@ -229,36 +253,56 @@ async def test_block_restored_climate_us_customery(
|
|||||||
"sensor_0",
|
"sensor_0",
|
||||||
entry,
|
entry,
|
||||||
)
|
)
|
||||||
attrs = {"current_temperature": 67, "temperature": 68}
|
attrs = {"current_temperature": 67, "temperature": 39}
|
||||||
mock_restore_cache(hass, [State(entity_id, HVACMode.HEAT, attributes=attrs)])
|
extra_data = {"last_target_temp": 10.0}
|
||||||
|
mock_restore_cache_with_extra_data(
|
||||||
|
hass, ((State(entity_id, HVACMode.OFF, attributes=attrs), extra_data),)
|
||||||
|
)
|
||||||
|
|
||||||
monkeypatch.setattr(mock_block_device, "initialized", False)
|
monkeypatch.setattr(mock_block_device, "initialized", False)
|
||||||
await hass.config_entries.async_setup(entry.entry_id)
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
assert hass.states.get(entity_id).attributes.get("temperature") == 68
|
assert hass.states.get(entity_id).attributes.get("temperature") == 39
|
||||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
||||||
|
|
||||||
# Partial update, should not change state
|
# Partial update, should not change state
|
||||||
mock_block_device.mock_update()
|
mock_block_device.mock_update()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
assert hass.states.get(entity_id).attributes.get("temperature") == 68
|
assert hass.states.get(entity_id).attributes.get("temperature") == 39
|
||||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
assert hass.states.get(entity_id).attributes.get("current_temperature") == 67
|
||||||
|
|
||||||
# Make device online
|
# Make device online
|
||||||
monkeypatch.setattr(mock_block_device, "initialized", True)
|
monkeypatch.setattr(mock_block_device, "initialized", True)
|
||||||
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "targetTemp", 19.7)
|
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "targetTemp", 4.0)
|
||||||
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "temp", 18.2)
|
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "temp", 18.2)
|
||||||
mock_block_device.mock_update()
|
mock_block_device.mock_update()
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert hass.states.get(entity_id).state == HVACMode.HEAT
|
assert hass.states.get(entity_id).state == HVACMode.OFF
|
||||||
assert hass.states.get(entity_id).attributes.get("temperature") == 67
|
assert hass.states.get(entity_id).attributes.get("temperature") == 39
|
||||||
assert hass.states.get(entity_id).attributes.get("current_temperature") == 65
|
assert hass.states.get(entity_id).attributes.get("current_temperature") == 65
|
||||||
|
|
||||||
|
# Test set hvac mode heat, target temp should be set to last target temp (10.0/50)
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN,
|
||||||
|
SERVICE_SET_HVAC_MODE,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_HVAC_MODE: HVACMode.HEAT},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
mock_block_device.http_request.assert_called_once_with(
|
||||||
|
"get", "thermostat/0", {"target_t_enabled": 1, "target_t": 10.0}
|
||||||
|
)
|
||||||
|
|
||||||
|
monkeypatch.setattr(mock_block_device.blocks[SENSOR_BLOCK_ID], "targetTemp", 10.0)
|
||||||
|
mock_block_device.mock_update()
|
||||||
|
state = hass.states.get(ENTITY_ID)
|
||||||
|
assert state.state == HVACMode.HEAT
|
||||||
|
assert hass.states.get(entity_id).attributes.get("temperature") == 50
|
||||||
|
|
||||||
|
|
||||||
async def test_block_restored_climate_unavailable(
|
async def test_block_restored_climate_unavailable(
|
||||||
hass, mock_block_device, device_reg, monkeypatch
|
hass, mock_block_device, device_reg, monkeypatch
|
||||||
|
Loading…
x
Reference in New Issue
Block a user