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 from typing import Any
8 
9 from homeassistant.const import (
10  ATTR_SUPPORTED_FEATURES,
11  SERVICE_MEDIA_PAUSE,
12  SERVICE_MEDIA_PLAY,
13  SERVICE_MEDIA_STOP,
14  SERVICE_TURN_OFF,
15  SERVICE_TURN_ON,
16  SERVICE_VOLUME_MUTE,
17  SERVICE_VOLUME_SET,
18  STATE_BUFFERING,
19  STATE_IDLE,
20  STATE_OFF,
21  STATE_ON,
22  STATE_PAUSED,
23  STATE_PLAYING,
24 )
25 from homeassistant.core import Context, HomeAssistant, State
26 
27 from .const import (
28  ATTR_INPUT_SOURCE,
29  ATTR_MEDIA_CONTENT_ID,
30  ATTR_MEDIA_CONTENT_TYPE,
31  ATTR_MEDIA_VOLUME_LEVEL,
32  ATTR_MEDIA_VOLUME_MUTED,
33  ATTR_SOUND_MODE,
34  DOMAIN,
35  SERVICE_PLAY_MEDIA,
36  SERVICE_SELECT_SOUND_MODE,
37  SERVICE_SELECT_SOURCE,
38  MediaPlayerEntityFeature,
39 )
40 
41 
43  hass: HomeAssistant,
44  state: State,
45  *,
46  context: Context | None = None,
47  reproduce_options: dict[str, Any] | None = None,
48 ) -> None:
49  """Reproduce component states."""
50  cur_state = hass.states.get(state.entity_id)
51  features = cur_state.attributes[ATTR_SUPPORTED_FEATURES] if cur_state else 0
52 
53  async def call_service(service: str, keys: Iterable[str]) -> None:
54  """Call service with set of attributes given."""
55  data = {"entity_id": state.entity_id}
56  for key in keys:
57  if key in state.attributes:
58  data[key] = state.attributes[key]
59 
60  await hass.services.async_call(
61  DOMAIN, service, data, blocking=True, context=context
62  )
63 
64  if state.state == STATE_OFF:
65  if features & MediaPlayerEntityFeature.TURN_OFF:
66  await call_service(SERVICE_TURN_OFF, [])
67  # entities that are off have no other attributes to restore
68  return
69 
70  if (
71  state.state
72  in (
73  STATE_BUFFERING,
74  STATE_IDLE,
75  STATE_ON,
76  STATE_PAUSED,
77  STATE_PLAYING,
78  )
79  and features & MediaPlayerEntityFeature.TURN_ON
80  ):
81  await call_service(SERVICE_TURN_ON, [])
82 
83  cur_state = hass.states.get(state.entity_id)
84  features = cur_state.attributes[ATTR_SUPPORTED_FEATURES] if cur_state else 0
85 
86  # First set source & sound mode to match the saved supported features
87  if (
88  ATTR_INPUT_SOURCE in state.attributes
89  and features & MediaPlayerEntityFeature.SELECT_SOURCE
90  ):
91  await call_service(SERVICE_SELECT_SOURCE, [ATTR_INPUT_SOURCE])
92 
93  if (
94  ATTR_SOUND_MODE in state.attributes
95  and features & MediaPlayerEntityFeature.SELECT_SOUND_MODE
96  ):
97  await call_service(SERVICE_SELECT_SOUND_MODE, [ATTR_SOUND_MODE])
98 
99  if (
100  ATTR_MEDIA_VOLUME_LEVEL in state.attributes
101  and features & MediaPlayerEntityFeature.VOLUME_SET
102  ):
103  await call_service(SERVICE_VOLUME_SET, [ATTR_MEDIA_VOLUME_LEVEL])
104 
105  if (
106  ATTR_MEDIA_VOLUME_MUTED in state.attributes
107  and features & MediaPlayerEntityFeature.VOLUME_MUTE
108  ):
109  await call_service(SERVICE_VOLUME_MUTE, [ATTR_MEDIA_VOLUME_MUTED])
110 
111  already_playing = False
112 
113  if (ATTR_MEDIA_CONTENT_TYPE in state.attributes) and (
114  ATTR_MEDIA_CONTENT_ID in state.attributes
115  ):
116  if features & MediaPlayerEntityFeature.PLAY_MEDIA:
117  await call_service(
118  SERVICE_PLAY_MEDIA,
119  [ATTR_MEDIA_CONTENT_TYPE, ATTR_MEDIA_CONTENT_ID],
120  )
121  already_playing = True
122 
123  if (
124  not already_playing
125  and state.state in (STATE_BUFFERING, STATE_PLAYING)
126  and features & MediaPlayerEntityFeature.PLAY
127  ):
128  await call_service(SERVICE_MEDIA_PLAY, [])
129  elif state.state == STATE_IDLE:
130  if features & MediaPlayerEntityFeature.STOP:
131  await call_service(SERVICE_MEDIA_STOP, [])
132  elif state.state == STATE_PAUSED:
133  if features & MediaPlayerEntityFeature.PAUSE:
134  await call_service(SERVICE_MEDIA_PAUSE, [])
135 
136 
138  hass: HomeAssistant,
139  states: Iterable[State],
140  *,
141  context: Context | None = None,
142  reproduce_options: dict[str, Any] | None = None,
143 ) -> None:
144  """Reproduce component states."""
145  await asyncio.gather(
146  *(
148  hass, state, context=context, reproduce_options=reproduce_options
149  )
150  for state in states
151  )
152  )
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)