Home Assistant Unofficial Reference 2024.12.1
time.py
Go to the documentation of this file.
1 """Contains time pickers exposed by the Starlink integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Awaitable, Callable
6 from dataclasses import dataclass
7 from datetime import UTC, datetime, time, tzinfo
8 import math
9 
10 from homeassistant.components.time import TimeEntity, TimeEntityDescription
11 from homeassistant.config_entries import ConfigEntry
12 from homeassistant.core import HomeAssistant
13 from homeassistant.exceptions import HomeAssistantError
14 from homeassistant.helpers.entity_platform import AddEntitiesCallback
15 
16 from .const import DOMAIN
17 from .coordinator import StarlinkData, StarlinkUpdateCoordinator
18 from .entity import StarlinkEntity
19 
20 
22  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
23 ) -> None:
24  """Set up all time entities for this entry."""
25  coordinator = hass.data[DOMAIN][entry.entry_id]
26 
28  StarlinkTimeEntity(coordinator, description) for description in TIMES
29  )
30 
31 
32 @dataclass(frozen=True, kw_only=True)
34  """Describes a Starlink time entity."""
35 
36  value_fn: Callable[[StarlinkData, tzinfo], time | None]
37  update_fn: Callable[[StarlinkUpdateCoordinator, time], Awaitable[None]]
38  available_fn: Callable[[StarlinkData], bool]
39 
40 
42  """A TimeEntity for Starlink devices. Handles creating unique IDs."""
43 
44  entity_description: StarlinkTimeEntityDescription
45 
46  @property
47  def native_value(self) -> time | None:
48  """Return the value reported by the time."""
49  return self.entity_descriptionentity_description.value_fn(
50  self.coordinator.data, self.coordinator.timezone
51  )
52 
53  @property
54  def available(self) -> bool:
55  """Return True if entity is available."""
56  return self.entity_descriptionentity_description.available_fn(self.coordinator.data)
57 
58  async def async_set_value(self, value: time) -> None:
59  """Change the time."""
60  return await self.entity_descriptionentity_description.update_fn(self.coordinator, value)
61 
62 
63 def _utc_minutes_to_time(utc_minutes: int, timezone: tzinfo) -> time:
64  hour = math.floor(utc_minutes / 60)
65  if hour > 23:
66  hour -= 24
67  minute = utc_minutes % 60
68  try:
69  utc = datetime.now(UTC).replace(
70  hour=hour, minute=minute, second=0, microsecond=0
71  )
72  except ValueError as exc:
73  raise HomeAssistantError from exc
74  return utc.astimezone(timezone).time()
75 
76 
77 def _time_to_utc_minutes(t: time, timezone: tzinfo) -> int:
78  try:
79  zoned_time = datetime.now(timezone).replace(
80  hour=t.hour, minute=t.minute, second=0, microsecond=0
81  )
82  except ValueError as exc:
83  raise HomeAssistantError from exc
84  utc_time = zoned_time.astimezone(UTC).time()
85  return (utc_time.hour * 60) + utc_time.minute
86 
87 
88 TIMES = [
90  key="sleep_start",
91  translation_key="sleep_start",
92  value_fn=lambda data, timezone: _utc_minutes_to_time(data.sleep[0], timezone),
93  update_fn=lambda coordinator, time: coordinator.async_set_sleep_start(
94  _time_to_utc_minutes(time, coordinator.timezone)
95  ),
96  available_fn=lambda data: data.sleep[2],
97  ),
99  key="sleep_end",
100  translation_key="sleep_end",
101  value_fn=lambda data, timezone: _utc_minutes_to_time(
102  data.sleep[0] + data.sleep[1], timezone
103  ),
104  update_fn=lambda coordinator, time: coordinator.async_set_sleep_duration(
105  _time_to_utc_minutes(time, coordinator.timezone)
106  ),
107  available_fn=lambda data: data.sleep[2],
108  ),
109 ]
bool time(HomeAssistant hass, dt_time|str|None before=None, dt_time|str|None after=None, str|Container[str]|None weekday=None)
Definition: condition.py:802