Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Component to allow setting date/time as platforms."""
2 
3 from __future__ import annotations
4 
5 from datetime import UTC, datetime, timedelta
6 import logging
7 from typing import final
8 
9 from propcache import cached_property
10 import voluptuous as vol
11 
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.core import HomeAssistant, ServiceCall
14 from homeassistant.helpers import config_validation as cv
15 from homeassistant.helpers.entity import Entity, EntityDescription
16 from homeassistant.helpers.entity_component import EntityComponent
17 from homeassistant.helpers.typing import ConfigType
18 from homeassistant.util import dt as dt_util
19 from homeassistant.util.hass_dict import HassKey
20 
21 from .const import ATTR_DATETIME, DOMAIN, SERVICE_SET_VALUE
22 
23 _LOGGER = logging.getLogger(__name__)
24 
25 DATA_COMPONENT: HassKey[EntityComponent[DateTimeEntity]] = HassKey(DOMAIN)
26 ENTITY_ID_FORMAT = DOMAIN + ".{}"
27 PLATFORM_SCHEMA = cv.PLATFORM_SCHEMA
28 PLATFORM_SCHEMA_BASE = cv.PLATFORM_SCHEMA_BASE
29 SCAN_INTERVAL = timedelta(seconds=30)
30 
31 
32 __all__ = ["ATTR_DATETIME", "DOMAIN", "DateTimeEntity", "DateTimeEntityDescription"]
33 
34 
35 async def _async_set_value(entity: DateTimeEntity, service_call: ServiceCall) -> None:
36  """Service call wrapper to set a new date/time."""
37  value: datetime = service_call.data[ATTR_DATETIME]
38  if value.tzinfo is None:
39  value = value.replace(tzinfo=dt_util.get_default_time_zone())
40  return await entity.async_set_value(value)
41 
42 
43 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
44  """Set up Date/Time entities."""
45  component = hass.data[DATA_COMPONENT] = EntityComponent[DateTimeEntity](
46  _LOGGER, DOMAIN, hass, SCAN_INTERVAL
47  )
48  await component.async_setup(config)
49 
50  component.async_register_entity_service(
51  SERVICE_SET_VALUE,
52  {
53  vol.Required(ATTR_DATETIME): cv.datetime,
54  },
55  _async_set_value,
56  )
57 
58  return True
59 
60 
61 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
62  """Set up a config entry."""
63  return await hass.data[DATA_COMPONENT].async_setup_entry(entry)
64 
65 
66 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
67  """Unload a config entry."""
68  return await hass.data[DATA_COMPONENT].async_unload_entry(entry)
69 
70 
71 class DateTimeEntityDescription(EntityDescription, frozen_or_thawed=True):
72  """A class that describes date/time entities."""
73 
74 
75 CACHED_PROPERTIES_WITH_ATTR_ = {
76  "native_value",
77 }
78 
79 
80 class DateTimeEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
81  """Representation of a Date/time entity."""
82 
83  entity_description: DateTimeEntityDescription
84  _attr_device_class: None = None
85  _attr_state: None = None
86  _attr_native_value: datetime | None
87 
88  @cached_property
89  @final
90  def device_class(self) -> None:
91  """Return entity device class."""
92  return None
93 
94  @cached_property
95  @final
96  def state_attributes(self) -> None:
97  """Return the state attributes."""
98  return None
99 
100  @property
101  @final
102  def state(self) -> str | None:
103  """Return the entity state."""
104  if (value := self.native_valuenative_value) is None:
105  return None
106  if value.tzinfo is None:
107  raise ValueError(
108  f"Invalid datetime: {self.entity_id} provides state '{value}', "
109  "which is missing timezone information"
110  )
111 
112  return value.astimezone(UTC).isoformat(timespec="seconds")
113 
114  @cached_property
115  def native_value(self) -> datetime | None:
116  """Return the value reported by the datetime."""
117  return self._attr_native_value
118 
119  def set_value(self, value: datetime) -> None:
120  """Change the date/time."""
121  raise NotImplementedError
122 
123  async def async_set_value(self, value: datetime) -> None:
124  """Change the date/time."""
125  await self.hasshass.async_add_executor_job(self.set_valueset_value, value)
None async_set_value(self, datetime value)
Definition: __init__.py:123
None _async_set_value(DateTimeEntity entity, ServiceCall service_call)
Definition: __init__.py:35
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:66
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:61
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:43