Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for SLZB-06 sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import datetime, timedelta
8 from itertools import chain
9 
10 from pysmlight import Info, Sensors
11 
13  SensorDeviceClass,
14  SensorEntity,
15  SensorEntityDescription,
16  SensorStateClass,
17 )
18 from homeassistant.const import EntityCategory, UnitOfInformation, UnitOfTemperature
19 from homeassistant.core import HomeAssistant
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 from homeassistant.helpers.typing import StateType
22 from homeassistant.util.dt import utcnow
23 
24 from . import SmConfigEntry
25 from .const import UPTIME_DEVIATION
26 from .coordinator import SmDataUpdateCoordinator
27 from .entity import SmEntity
28 
29 
30 @dataclass(frozen=True, kw_only=True)
32  """Class describing SMLIGHT sensor entities."""
33 
34  value_fn: Callable[[Sensors], float | None]
35 
36 
37 @dataclass(frozen=True, kw_only=True)
39  """Class describing SMLIGHT information entities."""
40 
41  value_fn: Callable[[Info], StateType]
42 
43 
44 INFO: list[SmInfoEntityDescription] = [
46  key="device_mode",
47  translation_key="device_mode",
48  device_class=SensorDeviceClass.ENUM,
49  options=["eth", "wifi", "usb"],
50  value_fn=lambda x: x.coord_mode,
51  ),
53  key="firmware_channel",
54  translation_key="firmware_channel",
55  device_class=SensorDeviceClass.ENUM,
56  options=["dev", "release"],
57  value_fn=lambda x: x.fw_channel,
58  ),
60  key="zigbee_type",
61  translation_key="zigbee_type",
62  device_class=SensorDeviceClass.ENUM,
63  options=["coordinator", "router", "thread"],
64  value_fn=lambda x: x.zb_type,
65  ),
66 ]
67 
68 
69 SENSORS: list[SmSensorEntityDescription] = [
71  key="core_temperature",
72  translation_key="core_temperature",
73  device_class=SensorDeviceClass.TEMPERATURE,
74  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
75  state_class=SensorStateClass.MEASUREMENT,
76  suggested_display_precision=1,
77  value_fn=lambda x: x.esp32_temp,
78  ),
80  key="zigbee_temperature",
81  translation_key="zigbee_temperature",
82  device_class=SensorDeviceClass.TEMPERATURE,
83  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
84  state_class=SensorStateClass.MEASUREMENT,
85  suggested_display_precision=1,
86  value_fn=lambda x: x.zb_temp,
87  ),
89  key="ram_usage",
90  translation_key="ram_usage",
91  device_class=SensorDeviceClass.DATA_SIZE,
92  native_unit_of_measurement=UnitOfInformation.KILOBYTES,
93  entity_registry_enabled_default=False,
94  value_fn=lambda x: x.ram_usage,
95  ),
97  key="fs_usage",
98  translation_key="fs_usage",
99  device_class=SensorDeviceClass.DATA_SIZE,
100  native_unit_of_measurement=UnitOfInformation.KILOBYTES,
101  entity_registry_enabled_default=False,
102  value_fn=lambda x: x.fs_used,
103  ),
104 ]
105 
106 UPTIME: list[SmSensorEntityDescription] = [
108  key="core_uptime",
109  translation_key="core_uptime",
110  device_class=SensorDeviceClass.TIMESTAMP,
111  entity_registry_enabled_default=False,
112  value_fn=lambda x: x.uptime,
113  ),
115  key="socket_uptime",
116  translation_key="socket_uptime",
117  device_class=SensorDeviceClass.TIMESTAMP,
118  entity_registry_enabled_default=False,
119  value_fn=lambda x: x.socket_uptime,
120  ),
121 ]
122 
123 
125  hass: HomeAssistant,
126  entry: SmConfigEntry,
127  async_add_entities: AddEntitiesCallback,
128 ) -> None:
129  """Set up SMLIGHT sensor based on a config entry."""
130  coordinator = entry.runtime_data.data
131 
133  chain(
134  (SmInfoSensorEntity(coordinator, description) for description in INFO),
135  (SmSensorEntity(coordinator, description) for description in SENSORS),
136  (SmUptimeSensorEntity(coordinator, description) for description in UPTIME),
137  )
138  )
139 
140 
142  """Representation of a slzb sensor."""
143 
144  coordinator: SmDataUpdateCoordinator
145  entity_description: SmSensorEntityDescription
146  _attr_entity_category = EntityCategory.DIAGNOSTIC
147 
148  def __init__(
149  self,
150  coordinator: SmDataUpdateCoordinator,
151  description: SmSensorEntityDescription,
152  ) -> None:
153  """Initiate slzb sensor."""
154  super().__init__(coordinator)
155 
156  self.entity_descriptionentity_description = description
157  self._attr_unique_id_attr_unique_id = f"{coordinator.unique_id}_{description.key}"
158 
159  @property
160  def native_value(self) -> datetime | str | float | None:
161  """Return the sensor value."""
162  return self.entity_descriptionentity_description.value_fn(self.coordinator.data.sensors)
163 
164 
166  """Representation of a slzb info sensor."""
167 
168  coordinator: SmDataUpdateCoordinator
169  entity_description: SmInfoEntityDescription
170  _attr_entity_category = EntityCategory.DIAGNOSTIC
171 
172  def __init__(
173  self,
174  coordinator: SmDataUpdateCoordinator,
175  description: SmInfoEntityDescription,
176  ) -> None:
177  """Initiate slzb sensor."""
178  super().__init__(coordinator)
179 
180  self.entity_descriptionentity_description = description
181  self._attr_unique_id_attr_unique_id = f"{coordinator.unique_id}_{description.key}"
182 
183  @property
184  def native_value(self) -> StateType:
185  """Return the sensor value."""
186  value = self.entity_descriptionentity_description.value_fn(self.coordinator.data.info)
187  options = self.entity_descriptionentity_description.options
188 
189  if isinstance(value, int) and options is not None:
190  value = options[value] if 0 <= value < len(options) else None
191 
192  return value
193 
194 
196  """Representation of a slzb uptime sensor."""
197 
198  def __init__(
199  self,
200  coordinator: SmDataUpdateCoordinator,
201  description: SmSensorEntityDescription,
202  ) -> None:
203  "Initialize uptime sensor instance."
204  super().__init__(coordinator, description)
205  self._last_uptime_last_uptime: datetime | None = None
206 
207  def get_uptime(self, uptime: float | None) -> datetime | None:
208  """Return device uptime or zigbee socket uptime.
209 
210  Converts uptime from seconds to a datetime value, allow up to 5
211  seconds deviation. This avoids unnecessary updates to sensor state,
212  that may be caused by clock jitter.
213  """
214  if uptime is None:
215  # reset to unknown state
216  self._last_uptime_last_uptime = None
217  return None
218 
219  new_uptime = utcnow() - timedelta(seconds=uptime)
220 
221  if (
222  not self._last_uptime_last_uptime
223  or abs(new_uptime - self._last_uptime_last_uptime) > UPTIME_DEVIATION
224  ):
225  self._last_uptime_last_uptime = new_uptime
226 
227  return self._last_uptime_last_uptime
228 
229  @property
230  def native_value(self) -> datetime | None:
231  """Return the sensor value."""
232  value = self.entity_descriptionentity_description.value_fn(self.coordinator.data.sensors)
233 
234  return self.get_uptimeget_uptime(value)
None __init__(self, SmDataUpdateCoordinator coordinator, SmInfoEntityDescription description)
Definition: sensor.py:176
None __init__(self, SmDataUpdateCoordinator coordinator, SmSensorEntityDescription description)
Definition: sensor.py:152
datetime|str|float|None native_value(self)
Definition: sensor.py:160
datetime|None get_uptime(self, float|None uptime)
Definition: sensor.py:207
None __init__(self, SmDataUpdateCoordinator coordinator, SmSensorEntityDescription description)
Definition: sensor.py:202
None async_setup_entry(HomeAssistant hass, SmConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:128