Home Assistant Unofficial Reference 2024.12.1
lawn_mower.py
Go to the documentation of this file.
1 """Husqvarna Automower lawn mower entity."""
2 
3 from datetime import timedelta
4 import logging
5 from typing import TYPE_CHECKING
6 
7 from aioautomower.model import MowerActivities, MowerStates, WorkArea
8 import voluptuous as vol
9 
11  LawnMowerActivity,
12  LawnMowerEntity,
13  LawnMowerEntityFeature,
14 )
15 from homeassistant.core import HomeAssistant
16 from homeassistant.exceptions import ServiceValidationError
17 from homeassistant.helpers import config_validation as cv, entity_platform
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 
20 from . import AutomowerConfigEntry
21 from .const import DOMAIN
22 from .coordinator import AutomowerDataUpdateCoordinator
23 from .entity import AutomowerAvailableEntity, handle_sending_exception
24 
25 _LOGGER = logging.getLogger(__name__)
26 
27 PARALLEL_UPDATES = 1
28 
29 DOCKED_ACTIVITIES = (MowerActivities.PARKED_IN_CS, MowerActivities.CHARGING)
30 MOWING_ACTIVITIES = (
31  MowerActivities.MOWING,
32  MowerActivities.LEAVING,
33 )
34 PAUSED_STATES = [
35  MowerStates.PAUSED,
36  MowerStates.WAIT_UPDATING,
37  MowerStates.WAIT_POWER_UP,
38 ]
39 SUPPORT_STATE_SERVICES = (
40  LawnMowerEntityFeature.DOCK
41  | LawnMowerEntityFeature.PAUSE
42  | LawnMowerEntityFeature.START_MOWING
43 )
44 MOW = "mow"
45 PARK = "park"
46 OVERRIDE_MODES = [MOW, PARK]
47 
48 
50  hass: HomeAssistant,
51  entry: AutomowerConfigEntry,
52  async_add_entities: AddEntitiesCallback,
53 ) -> None:
54  """Set up lawn mower platform."""
55  coordinator = entry.runtime_data
57  AutomowerLawnMowerEntity(mower_id, coordinator) for mower_id in coordinator.data
58  )
59 
60  platform = entity_platform.async_get_current_platform()
61  platform.async_register_entity_service(
62  "override_schedule",
63  {
64  vol.Required("override_mode"): vol.In(OVERRIDE_MODES),
65  vol.Required("duration"): vol.All(
66  cv.time_period,
67  cv.positive_timedelta,
68  vol.Range(min=timedelta(minutes=1), max=timedelta(days=42)),
69  ),
70  },
71  "async_override_schedule",
72  )
73  platform.async_register_entity_service(
74  "override_schedule_work_area",
75  {
76  vol.Required("work_area_id"): vol.Coerce(int),
77  vol.Required("duration"): vol.All(
78  cv.time_period,
79  cv.positive_timedelta,
80  vol.Range(min=timedelta(minutes=1), max=timedelta(days=42)),
81  ),
82  },
83  "async_override_schedule_work_area",
84  )
85 
86 
88  """Defining each mower Entity."""
89 
90  _attr_name = None
91  _attr_supported_features = SUPPORT_STATE_SERVICES
92 
93  def __init__(
94  self,
95  mower_id: str,
96  coordinator: AutomowerDataUpdateCoordinator,
97  ) -> None:
98  """Set up HusqvarnaAutomowerEntity."""
99  super().__init__(mower_id, coordinator)
100  self._attr_unique_id_attr_unique_id = mower_id
101 
102  @property
103  def activity(self) -> LawnMowerActivity:
104  """Return the state of the mower."""
105  mower_attributes = self.mower_attributesmower_attributes
106  if mower_attributes.mower.state in PAUSED_STATES:
107  return LawnMowerActivity.PAUSED
108  if mower_attributes.mower.activity in MOWING_ACTIVITIES:
109  return LawnMowerActivity.MOWING
110  if mower_attributes.mower.activity == MowerActivities.GOING_HOME:
111  return LawnMowerActivity.RETURNING
112  if (mower_attributes.mower.state == "RESTRICTED") or (
113  mower_attributes.mower.activity in DOCKED_ACTIVITIES
114  ):
115  return LawnMowerActivity.DOCKED
116  return LawnMowerActivity.ERROR
117 
118  @property
119  def work_areas(self) -> dict[int, WorkArea] | None:
120  """Return the work areas of the mower."""
121  return self.mower_attributesmower_attributes.work_areas
122 
123  @handle_sending_exception()
124  async def async_start_mowing(self) -> None:
125  """Resume schedule."""
126  await self.coordinator.api.commands.resume_schedule(self.mower_idmower_id)
127 
128  @handle_sending_exception()
129  async def async_pause(self) -> None:
130  """Pauses the mower."""
131  await self.coordinator.api.commands.pause_mowing(self.mower_idmower_id)
132 
133  @handle_sending_exception()
134  async def async_dock(self) -> None:
135  """Parks the mower until next schedule."""
136  await self.coordinator.api.commands.park_until_next_schedule(self.mower_idmower_id)
137 
138  @handle_sending_exception()
140  self, override_mode: str, duration: timedelta
141  ) -> None:
142  """Override the schedule with mowing or parking."""
143  if override_mode == MOW:
144  await self.coordinator.api.commands.start_for(self.mower_idmower_id, duration)
145  if override_mode == PARK:
146  await self.coordinator.api.commands.park_for(self.mower_idmower_id, duration)
147 
148  @handle_sending_exception()
150  self, work_area_id: int, duration: timedelta
151  ) -> None:
152  """Override the schedule with a certain work area."""
153  if not self.mower_attributesmower_attributes.capabilities.work_areas:
155  translation_domain=DOMAIN, translation_key="work_areas_not_supported"
156  )
157  if TYPE_CHECKING:
158  assert self.work_areaswork_areas is not None
159  if work_area_id not in self.work_areaswork_areas:
161  translation_domain=DOMAIN, translation_key="work_area_not_existing"
162  )
163  await self.coordinator.api.commands.start_in_workarea(
164  self.mower_idmower_id, work_area_id, duration
165  )
None async_override_schedule_work_area(self, int work_area_id, timedelta duration)
Definition: lawn_mower.py:151
None __init__(self, str mower_id, AutomowerDataUpdateCoordinator coordinator)
Definition: lawn_mower.py:97
None async_override_schedule(self, str override_mode, timedelta duration)
Definition: lawn_mower.py:141
None async_setup_entry(HomeAssistant hass, AutomowerConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: lawn_mower.py:53