Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Sensor entity for a Rainforest RAVEn device."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 from typing import Any
7 
9  SensorDeviceClass,
10  SensorEntity,
11  SensorEntityDescription,
12  SensorStateClass,
13 )
14 from homeassistant.const import (
15  CONF_MAC,
16  PERCENTAGE,
17  EntityCategory,
18  UnitOfEnergy,
19  UnitOfPower,
20 )
21 from homeassistant.core import HomeAssistant
22 from homeassistant.helpers.entity_platform import AddEntitiesCallback
23 from homeassistant.helpers.typing import StateType
24 from homeassistant.helpers.update_coordinator import CoordinatorEntity
25 
26 from .coordinator import RAVEnConfigEntry, RAVEnDataCoordinator
27 
28 
29 @dataclass(frozen=True, kw_only=True)
31  """A class that describes RAVEn sensor entities."""
32 
33  message_key: str
34  attribute_keys: list[str] | None = None
35 
36 
37 SENSORS = (
39  message_key="CurrentSummationDelivered",
40  translation_key="total_energy_delivered",
41  key="summation_delivered",
42  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
43  device_class=SensorDeviceClass.ENERGY,
44  state_class=SensorStateClass.TOTAL_INCREASING,
45  ),
47  message_key="CurrentSummationDelivered",
48  translation_key="total_energy_received",
49  key="summation_received",
50  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
51  device_class=SensorDeviceClass.ENERGY,
52  state_class=SensorStateClass.TOTAL_INCREASING,
53  ),
55  message_key="InstantaneousDemand",
56  translation_key="power_demand",
57  key="demand",
58  native_unit_of_measurement=UnitOfPower.KILO_WATT,
59  device_class=SensorDeviceClass.POWER,
60  state_class=SensorStateClass.MEASUREMENT,
61  ),
62 )
63 
64 
65 DIAGNOSTICS = (
67  message_key="NetworkInfo",
68  translation_key="signal_strength",
69  key="link_strength",
70  native_unit_of_measurement=PERCENTAGE,
71  state_class=SensorStateClass.MEASUREMENT,
72  entity_category=EntityCategory.DIAGNOSTIC,
73  attribute_keys=[
74  "channel",
75  ],
76  ),
77 )
78 
79 
81  hass: HomeAssistant,
82  entry: RAVEnConfigEntry,
83  async_add_entities: AddEntitiesCallback,
84 ) -> None:
85  """Set up a config entry."""
86  coordinator = entry.runtime_data
87  entities: list[RAVEnSensor] = [
88  RAVEnSensor(coordinator, description) for description in DIAGNOSTICS
89  ]
90 
91  for meter_mac_addr in entry.data[CONF_MAC]:
92  entities.extend(
93  RAVEnMeterSensor(coordinator, description, meter_mac_addr)
94  for description in SENSORS
95  )
96 
97  meter_data = coordinator.data.get("Meters", {}).get(meter_mac_addr) or {}
98  if meter_data.get("PriceCluster", {}).get("currency"):
99  entities.append(
101  coordinator,
103  message_key="PriceCluster",
104  translation_key="meter_price",
105  key="price",
106  native_unit_of_measurement=f"{meter_data['PriceCluster']['currency'].value}/{UnitOfEnergy.KILO_WATT_HOUR}",
107  state_class=SensorStateClass.MEASUREMENT,
108  attribute_keys=[
109  "tier",
110  "rate_label",
111  ],
112  ),
113  meter_mac_addr,
114  )
115  )
116 
117  async_add_entities(entities)
118 
119 
120 class RAVEnSensor(CoordinatorEntity[RAVEnDataCoordinator], SensorEntity):
121  """Rainforest RAVEn Sensor."""
122 
123  _attr_has_entity_name = True
124  entity_description: RAVEnSensorEntityDescription
125 
126  def __init__(
127  self,
128  coordinator: RAVEnDataCoordinator,
129  entity_description: RAVEnSensorEntityDescription,
130  ) -> None:
131  """Initialize the sensor."""
132  super().__init__(coordinator)
133  self.entity_descriptionentity_description = entity_description
134  self._attr_device_info_attr_device_info = coordinator.device_info
135  self._attr_unique_id_attr_unique_id = (
136  f"{self.coordinator.device_mac_address}"
137  f".{self.entity_description.message_key}.{self.entity_description.key}"
138  )
139 
140  @property
141  def _data(self) -> Any:
142  """Return the raw sensor data from the source."""
143  return self.coordinator.data.get(self.entity_descriptionentity_description.message_key, {})
144 
145  @property
146  def extra_state_attributes(self) -> dict[str, Any] | None:
147  """Return entity specific state attributes."""
148  if self.entity_descriptionentity_description.attribute_keys:
149  return {
150  key: self._data_data.get(key)
151  for key in self.entity_descriptionentity_description.attribute_keys
152  }
153  return None
154 
155  @property
156  def native_value(self) -> StateType:
157  """Return native value of the sensor."""
158  return str(self._data_data.get(self.entity_descriptionentity_description.key))
159 
160 
162  """Rainforest RAVEn Meter Sensor."""
163 
164  def __init__(
165  self,
166  coordinator: RAVEnDataCoordinator,
167  entity_description: RAVEnSensorEntityDescription,
168  meter_mac_addr: str,
169  ) -> None:
170  """Initialize the sensor."""
171  super().__init__(coordinator, entity_description)
172  self._meter_mac_addr_meter_mac_addr = meter_mac_addr
173  self._attr_unique_id_attr_unique_id_attr_unique_id = (
174  f"{self._meter_mac_addr}"
175  f".{self.entity_description.message_key}.{self.entity_description.key}"
176  )
177 
178  @property
179  def _data(self) -> Any:
180  """Return the raw sensor data from the source."""
181  return (
182  self.coordinator.data.get("Meters", {})
183  .get(self._meter_mac_addr_meter_mac_addr, {})
184  .get(self.entity_descriptionentity_description.message_key, {})
185  )
None __init__(self, RAVEnDataCoordinator coordinator, RAVEnSensorEntityDescription entity_description, str meter_mac_addr)
Definition: sensor.py:169
None __init__(self, RAVEnDataCoordinator coordinator, RAVEnSensorEntityDescription entity_description)
Definition: sensor.py:130
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, RAVEnConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:84