Home Assistant Unofficial Reference 2024.12.1
switch.py
Go to the documentation of this file.
1 """Creates a switch entity for the mower."""
2 
3 import logging
4 from typing import TYPE_CHECKING, Any
5 
6 from aioautomower.model import MowerModes, StayOutZones, Zone
7 
8 from homeassistant.components.switch import SwitchEntity
9 from homeassistant.core import HomeAssistant
10 from homeassistant.helpers import entity_registry as er
11 from homeassistant.helpers.entity_platform import AddEntitiesCallback
12 
13 from . import AutomowerConfigEntry
14 from .coordinator import AutomowerDataUpdateCoordinator
15 from .entity import (
16  AutomowerControlEntity,
17  WorkAreaControlEntity,
18  _work_area_translation_key,
19  handle_sending_exception,
20 )
21 
22 PARALLEL_UPDATES = 1
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 
28  hass: HomeAssistant,
29  entry: AutomowerConfigEntry,
30  async_add_entities: AddEntitiesCallback,
31 ) -> None:
32  """Set up switch platform."""
33  coordinator = entry.runtime_data
34  current_work_areas: dict[str, set[int]] = {}
35  current_stay_out_zones: dict[str, set[str]] = {}
36 
38  AutomowerScheduleSwitchEntity(mower_id, coordinator)
39  for mower_id in coordinator.data
40  )
41 
42  def _async_work_area_listener() -> None:
43  """Listen for new work areas and add switch entities if they did not exist.
44 
45  Listening for deletable work areas is managed in the number platform.
46  """
47  for mower_id in coordinator.data:
48  if (
49  coordinator.data[mower_id].capabilities.work_areas
50  and (_work_areas := coordinator.data[mower_id].work_areas) is not None
51  ):
52  received_work_areas = set(_work_areas.keys())
53  new_work_areas = received_work_areas - current_work_areas.get(
54  mower_id, set()
55  )
56  if new_work_areas:
57  current_work_areas.setdefault(mower_id, set()).update(
58  new_work_areas
59  )
61  WorkAreaSwitchEntity(coordinator, mower_id, work_area_id)
62  for work_area_id in new_work_areas
63  )
64 
65  def _remove_stay_out_zone_entities(
66  removed_stay_out_zones: set, mower_id: str
67  ) -> None:
68  """Remove all unused stay-out zones for all platforms."""
69  entity_reg = er.async_get(hass)
70  for entity_entry in er.async_entries_for_config_entry(
71  entity_reg, entry.entry_id
72  ):
73  for stay_out_zone_uid in removed_stay_out_zones:
74  if entity_entry.unique_id.startswith(f"{mower_id}_{stay_out_zone_uid}"):
75  entity_reg.async_remove(entity_entry.entity_id)
76 
77  def _async_stay_out_zone_listener() -> None:
78  """Listen for new stay-out zones and add/remove switch entities if they did not exist."""
79  for mower_id in coordinator.data:
80  if (
81  coordinator.data[mower_id].capabilities.stay_out_zones
82  and (_stay_out_zones := coordinator.data[mower_id].stay_out_zones)
83  is not None
84  ):
85  received_stay_out_zones = set(_stay_out_zones.zones)
86  current_stay_out_zones_set = current_stay_out_zones.get(mower_id, set())
87  new_stay_out_zones = (
88  received_stay_out_zones - current_stay_out_zones_set
89  )
90  removed_stay_out_zones = (
91  current_stay_out_zones_set - received_stay_out_zones
92  )
93  if new_stay_out_zones:
94  current_stay_out_zones.setdefault(mower_id, set()).update(
95  new_stay_out_zones
96  )
99  coordinator, mower_id, stay_out_zone_uid
100  )
101  for stay_out_zone_uid in new_stay_out_zones
102  )
103  if removed_stay_out_zones:
104  _remove_stay_out_zone_entities(removed_stay_out_zones, mower_id)
105 
106  coordinator.async_add_listener(_async_work_area_listener)
107  coordinator.async_add_listener(_async_stay_out_zone_listener)
108  _async_work_area_listener()
109  _async_stay_out_zone_listener()
110 
111 
113  """Defining the Automower schedule switch."""
114 
115  _attr_translation_key = "enable_schedule"
116 
117  def __init__(
118  self,
119  mower_id: str,
120  coordinator: AutomowerDataUpdateCoordinator,
121  ) -> None:
122  """Set up Automower switch."""
123  super().__init__(mower_id, coordinator)
124  self._attr_unique_id_attr_unique_id = f"{self.mower_id}_{self._attr_translation_key}"
125 
126  @property
127  def is_on(self) -> bool:
128  """Return the state of the switch."""
129  return self.mower_attributesmower_attributes.mower.mode != MowerModes.HOME
130 
131  @handle_sending_exception()
132  async def async_turn_off(self, **kwargs: Any) -> None:
133  """Turn the entity off."""
134  await self.coordinator.api.commands.park_until_further_notice(self.mower_idmower_id)
135 
136  @handle_sending_exception()
137  async def async_turn_on(self, **kwargs: Any) -> None:
138  """Turn the entity on."""
139  await self.coordinator.api.commands.resume_schedule(self.mower_idmower_id)
140 
141 
143  """Defining the Automower stay out zone switch."""
144 
145  _attr_translation_key = "stay_out_zones"
146 
147  def __init__(
148  self,
149  coordinator: AutomowerDataUpdateCoordinator,
150  mower_id: str,
151  stay_out_zone_uid: str,
152  ) -> None:
153  """Set up Automower switch."""
154  super().__init__(mower_id, coordinator)
155  self.coordinatorcoordinator = coordinator
156  self.stay_out_zone_uidstay_out_zone_uid = stay_out_zone_uid
157  self._attr_unique_id_attr_unique_id = (
158  f"{self.mower_id}_{stay_out_zone_uid}_{self._attr_translation_key}"
159  )
160  self._attr_translation_placeholders_attr_translation_placeholders = {"stay_out_zone": self.stay_out_zonestay_out_zone.name}
161 
162  @property
163  def stay_out_zones(self) -> StayOutZones:
164  """Return all stay out zones."""
165  if TYPE_CHECKING:
166  assert self.mower_attributesmower_attributes.stay_out_zones is not None
167  return self.mower_attributesmower_attributes.stay_out_zones
168 
169  @property
170  def stay_out_zone(self) -> Zone:
171  """Return the specific stay out zone."""
172  return self.stay_out_zonesstay_out_zones.zones[self.stay_out_zone_uidstay_out_zone_uid]
173 
174  @property
175  def is_on(self) -> bool:
176  """Return the state of the switch."""
177  return self.stay_out_zonestay_out_zone.enabled
178 
179  @property
180  def available(self) -> bool:
181  """Return True if the device is available and the zones are not `dirty`."""
182  return super().available and not self.stay_out_zonesstay_out_zones.dirty
183 
184  @handle_sending_exception(poll_after_sending=True)
185  async def async_turn_off(self, **kwargs: Any) -> None:
186  """Turn the switch off."""
187  await self.coordinatorcoordinator.api.commands.switch_stay_out_zone(
188  self.mower_idmower_id, self.stay_out_zone_uidstay_out_zone_uid, False
189  )
190 
191  @handle_sending_exception(poll_after_sending=True)
192  async def async_turn_on(self, **kwargs: Any) -> None:
193  """Turn the switch on."""
194  await self.coordinatorcoordinator.api.commands.switch_stay_out_zone(
195  self.mower_idmower_id, self.stay_out_zone_uidstay_out_zone_uid, True
196  )
197 
198 
200  """Defining the Automower work area switch."""
201 
202  def __init__(
203  self,
204  coordinator: AutomowerDataUpdateCoordinator,
205  mower_id: str,
206  work_area_id: int,
207  ) -> None:
208  """Set up Automower switch."""
209  super().__init__(mower_id, coordinator, work_area_id)
210  key = "work_area"
211  self._attr_translation_key_attr_translation_key = _work_area_translation_key(work_area_id, key)
212  self._attr_unique_id_attr_unique_id = f"{mower_id}_{work_area_id}_{key}"
213  if self.work_area_attributeswork_area_attributes.name == "my_lawn":
214  self._attr_translation_placeholders_attr_translation_placeholders = {
215  "work_area": self.work_area_attributeswork_area_attributes.name
216  }
217  else:
218  self._attr_name_attr_name = self.work_area_attributeswork_area_attributes.name
219 
220  @property
221  def is_on(self) -> bool:
222  """Return the state of the switch."""
223  return self.work_area_attributeswork_area_attributes.enabled
224 
225  @handle_sending_exception(poll_after_sending=True)
226  async def async_turn_off(self, **kwargs: Any) -> None:
227  """Turn the switch off."""
228  await self.coordinator.api.commands.workarea_settings(
229  self.mower_idmower_id, self.work_area_idwork_area_id, enabled=False
230  )
231 
232  @handle_sending_exception(poll_after_sending=True)
233  async def async_turn_on(self, **kwargs: Any) -> None:
234  """Turn the switch on."""
235  await self.coordinator.api.commands.workarea_settings(
236  self.mower_idmower_id, self.work_area_idwork_area_id, enabled=True
237  )
None __init__(self, str mower_id, AutomowerDataUpdateCoordinator coordinator)
Definition: switch.py:121
None __init__(self, AutomowerDataUpdateCoordinator coordinator, str mower_id, str stay_out_zone_uid)
Definition: switch.py:152
None __init__(self, AutomowerDataUpdateCoordinator coordinator, str mower_id, int work_area_id)
Definition: switch.py:207
str _work_area_translation_key(int work_area_id, str key)
Definition: entity.py:48
None async_setup_entry(HomeAssistant hass, AutomowerConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: switch.py:31
IssData update(pyiss.ISS iss)
Definition: __init__.py:33