Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for hunterdouglass_powerview sensors."""
2 
3 from collections.abc import Callable
4 from dataclasses import dataclass
5 from typing import Any, Final
6 
7 from aiopvapi.helpers.constants import ATTR_NAME
8 from aiopvapi.resources.shade import BaseShade
9 
11  SensorDeviceClass,
12  SensorEntity,
13  SensorEntityDescription,
14  SensorStateClass,
15 )
16 from homeassistant.const import PERCENTAGE, SIGNAL_STRENGTH_DECIBELS, EntityCategory
17 from homeassistant.core import HomeAssistant, callback
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 
20 from .coordinator import PowerviewShadeUpdateCoordinator
21 from .entity import ShadeEntity
22 from .model import PowerviewConfigEntry, PowerviewDeviceInfo
23 
24 
25 @dataclass(frozen=True)
27  """Mixin to describe a Sensor entity."""
28 
29  update_fn: Callable[[BaseShade], Any]
30  device_class_fn: Callable[[BaseShade], SensorDeviceClass | None]
31  native_value_fn: Callable[[BaseShade], int]
32  native_unit_fn: Callable[[BaseShade], str | None]
33  create_entity_fn: Callable[[BaseShade], bool]
34 
35 
36 @dataclass(frozen=True)
38  SensorEntityDescription, PowerviewSensorDescriptionMixin
39 ):
40  """Class to describe a Sensor entity."""
41 
42  entity_category = EntityCategory.DIAGNOSTIC
43  state_class = SensorStateClass.MEASUREMENT
44 
45 
46 def get_signal_device_class(shade: BaseShade) -> SensorDeviceClass | None:
47  """Get the signal value based on version of API."""
48  return SensorDeviceClass.SIGNAL_STRENGTH if shade.api_version >= 3 else None
49 
50 
51 def get_signal_native_unit(shade: BaseShade) -> str:
52  """Get the unit of measurement for signal based on version of API."""
53  return SIGNAL_STRENGTH_DECIBELS if shade.api_version >= 3 else PERCENTAGE
54 
55 
56 SENSORS: Final = [
58  key="charge",
59  device_class_fn=lambda shade: SensorDeviceClass.BATTERY,
60  native_unit_fn=lambda shade: PERCENTAGE,
61  native_value_fn=lambda shade: shade.get_battery_strength(),
62  create_entity_fn=lambda shade: shade.is_battery_powered(),
63  update_fn=lambda shade: shade.refresh_battery(suppress_timeout=True),
64  ),
66  key="signal",
67  translation_key="signal_strength",
68  icon="mdi:signal",
69  device_class_fn=get_signal_device_class,
70  native_unit_fn=get_signal_native_unit,
71  native_value_fn=lambda shade: shade.get_signal_strength(),
72  create_entity_fn=lambda shade: shade.has_signal_strength(),
73  update_fn=lambda shade: shade.refresh(suppress_timeout=True),
74  entity_registry_enabled_default=False,
75  ),
76 ]
77 
78 
80  hass: HomeAssistant,
81  entry: PowerviewConfigEntry,
82  async_add_entities: AddEntitiesCallback,
83 ) -> None:
84  """Set up the hunter douglas sensor entities."""
85  pv_entry = entry.runtime_data
86  entities: list[PowerViewSensor] = []
87  for shade in pv_entry.shade_data.values():
88  room_name = getattr(pv_entry.room_data.get(shade.room_id), ATTR_NAME, "")
89  entities.extend(
91  pv_entry.coordinator,
92  pv_entry.device_info,
93  room_name,
94  shade,
95  shade.name,
96  description,
97  )
98  for description in SENSORS
99  if description.create_entity_fn(shade)
100  )
101  async_add_entities(entities)
102 
103 
105  """Representation of an shade sensor."""
106 
107  entity_description: PowerviewSensorDescription
108 
109  def __init__(
110  self,
111  coordinator: PowerviewShadeUpdateCoordinator,
112  device_info: PowerviewDeviceInfo,
113  room_name: str,
114  shade: BaseShade,
115  name: str,
116  description: PowerviewSensorDescription,
117  ) -> None:
118  """Initialize the sensor entity."""
119  super().__init__(coordinator, device_info, room_name, shade, name)
120  self.entity_descriptionentity_description = description
121  self.entity_descriptionentity_description: PowerviewSensorDescription = description
122  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{self._attr_unique_id}_{description.key}"
123 
124  @property
125  def native_value(self) -> int:
126  """Get the current value of the sensor."""
127  return self.entity_descriptionentity_description.native_value_fn(self._shade_shade)
128 
129  @property
130  def native_unit_of_measurement(self) -> str | None:
131  """Return native unit of measurement of sensor."""
132  return self.entity_descriptionentity_description.native_unit_fn(self._shade_shade)
133 
134  @property
135  def device_class(self) -> SensorDeviceClass | None:
136  """Return the class of this entity."""
137  return self.entity_descriptionentity_description.device_class_fn(self._shade_shade)
138 
139  # pylint: disable-next=hass-missing-super-call
140  async def async_added_to_hass(self) -> None:
141  """When entity is added to hass."""
142  self.async_on_removeasync_on_remove(
143  self.coordinator.async_add_listener(self._async_update_shade_from_group_async_update_shade_from_group)
144  )
145 
146  @callback
148  """Update with new data from the coordinator."""
149  self._shade_shade.raw_data = self.datadatadata.get_raw_data(self._shade_shade.id)
150  self.async_write_ha_stateasync_write_ha_state()
151 
152  async def async_update(self) -> None:
153  """Refresh sensor entity."""
154  async with self.coordinator.radio_operation_lock:
155  await self.entity_descriptionentity_description.update_fn(self._shade_shade)
156  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, PowerviewShadeUpdateCoordinator coordinator, PowerviewDeviceInfo device_info, str room_name, BaseShade shade, str name, PowerviewSensorDescription description)
Definition: sensor.py:117
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
Callable[[], None] async_add_listener(self, CALLBACK_TYPE update_callback, Any context=None)
None async_setup_entry(HomeAssistant hass, PowerviewConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:83
SensorDeviceClass|None get_signal_device_class(BaseShade shade)
Definition: sensor.py:46