Home Assistant Unofficial Reference 2024.12.1
reproduce_state.py
Go to the documentation of this file.
1 """Module that groups code required to handle state restore for component."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from collections.abc import Iterable
7 import logging
8 from typing import Any
9 
10 from homeassistant.const import (
11  ATTR_MODE,
12  SERVICE_TURN_OFF,
13  SERVICE_TURN_ON,
14  STATE_OFF,
15  STATE_ON,
16 )
17 from homeassistant.core import Context, HomeAssistant, State
18 
19 from .const import ATTR_HUMIDITY, DOMAIN, SERVICE_SET_HUMIDITY, SERVICE_SET_MODE
20 
21 _LOGGER = logging.getLogger(__name__)
22 
23 
25  hass: HomeAssistant,
26  state: State,
27  *,
28  context: Context | None = None,
29  reproduce_options: dict[str, Any] | None = None,
30 ) -> None:
31  """Reproduce component states."""
32  if (cur_state := hass.states.get(state.entity_id)) is None:
33  _LOGGER.warning("Unable to find entity %s", state.entity_id)
34  return
35 
36  async def call_service(service: str, keys: Iterable[str]) -> None:
37  """Call service with set of attributes given."""
38  data = {"entity_id": state.entity_id}
39  for key in keys:
40  if key in state.attributes:
41  data[key] = state.attributes[key]
42 
43  await hass.services.async_call(
44  DOMAIN, service, data, blocking=True, context=context
45  )
46 
47  if state.state == STATE_OFF:
48  # Ensure the device is off if it needs to be and exit
49  if cur_state.state != STATE_OFF:
50  await call_service(SERVICE_TURN_OFF, [])
51  return
52 
53  if state.state != STATE_ON:
54  # we can't know how to handle this
55  _LOGGER.warning(
56  "Invalid state specified for %s: %s", state.entity_id, state.state
57  )
58  return
59 
60  # First of all, turn on if needed, because the device might not
61  # be able to set mode and humidity while being off
62  if cur_state.state != STATE_ON:
63  await call_service(SERVICE_TURN_ON, [])
64  # refetch the state as turning on might allow us to see some more values
65  if (cur_state := hass.states.get(state.entity_id)) is None:
66  _LOGGER.warning("Unable to find entity %s", state.entity_id)
67  return
68 
69  # Then set the mode before target humidity, because switching modes
70  # may invalidate target humidity
71  if ATTR_MODE in state.attributes and state.attributes[
72  ATTR_MODE
73  ] != cur_state.attributes.get(ATTR_MODE):
74  await call_service(SERVICE_SET_MODE, [ATTR_MODE])
75 
76  # Next, restore target humidity for the current mode
77  if ATTR_HUMIDITY in state.attributes and state.attributes[
78  ATTR_HUMIDITY
79  ] != cur_state.attributes.get(ATTR_HUMIDITY):
80  await call_service(SERVICE_SET_HUMIDITY, [ATTR_HUMIDITY])
81 
82 
84  hass: HomeAssistant,
85  states: Iterable[State],
86  *,
87  context: Context | None = None,
88  reproduce_options: dict[str, Any] | None = None,
89 ) -> None:
90  """Reproduce component states."""
91  await asyncio.gather(
92  *(
94  hass, state, context=context, reproduce_options=reproduce_options
95  )
96  for state in states
97  )
98  )
None async_reproduce_states(HomeAssistant hass, Iterable[State] states, *Context|None context=None, dict[str, Any]|None reproduce_options=None)
None _async_reproduce_states(HomeAssistant hass, State state, *Context|None context=None, dict[str, Any]|None reproduce_options=None)