1 """Support for RFXtrx sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import date, datetime
8 from decimal
import Decimal
10 from typing
import Any, cast
12 from RFXtrx
import ControlEvent, RFXtrxDevice, RFXtrxEvent, SensorEvent
17 SensorEntityDescription,
24 SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
27 UnitOfElectricCurrent,
28 UnitOfElectricPotential,
31 UnitOfPrecipitationDepth,
42 from .
import DeviceTuple, async_setup_platform_entry, get_rfx_object
43 from .const
import ATTR_EVENT
44 from .entity
import RfxtrxEntity
46 _LOGGER = logging.getLogger(__name__)
50 """Battery is given as a value between 0 and 9."""
53 return (value + 1) * 10
57 """Rssi is given as dBm value."""
60 return f
"{value*8-120}"
63 @dataclass(frozen=True)
65 """Description of sensor entities."""
67 convert: Callable[[Any], StateType | date | datetime | Decimal] =
lambda x: cast(
75 device_class=SensorDeviceClass.PRESSURE,
76 state_class=SensorStateClass.MEASUREMENT,
77 native_unit_of_measurement=UnitOfPressure.HPA,
80 key=
"Battery numeric",
81 device_class=SensorDeviceClass.BATTERY,
82 state_class=SensorStateClass.MEASUREMENT,
83 native_unit_of_measurement=PERCENTAGE,
84 convert=_battery_convert,
85 entity_category=EntityCategory.DIAGNOSTIC,
89 device_class=SensorDeviceClass.CURRENT,
90 state_class=SensorStateClass.MEASUREMENT,
91 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
95 translation_key=
"current_ch_1",
96 device_class=SensorDeviceClass.CURRENT,
97 state_class=SensorStateClass.MEASUREMENT,
98 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
102 translation_key=
"current_ch_2",
103 device_class=SensorDeviceClass.CURRENT,
104 state_class=SensorStateClass.MEASUREMENT,
105 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
109 translation_key=
"current_ch_3",
110 device_class=SensorDeviceClass.CURRENT,
111 state_class=SensorStateClass.MEASUREMENT,
112 native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
116 translation_key=
"instantaneous_power",
117 device_class=SensorDeviceClass.POWER,
118 state_class=SensorStateClass.MEASUREMENT,
119 native_unit_of_measurement=UnitOfPower.WATT,
123 device_class=SensorDeviceClass.HUMIDITY,
124 state_class=SensorStateClass.MEASUREMENT,
125 native_unit_of_measurement=PERCENTAGE,
129 device_class=SensorDeviceClass.SIGNAL_STRENGTH,
130 state_class=SensorStateClass.MEASUREMENT,
131 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
132 convert=_rssi_convert,
133 entity_category=EntityCategory.DIAGNOSTIC,
137 device_class=SensorDeviceClass.TEMPERATURE,
138 state_class=SensorStateClass.MEASUREMENT,
139 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
143 translation_key=
"temperature_2",
144 device_class=SensorDeviceClass.TEMPERATURE,
145 state_class=SensorStateClass.MEASUREMENT,
146 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
150 translation_key=
"total_energy_usage",
151 device_class=SensorDeviceClass.ENERGY,
152 state_class=SensorStateClass.TOTAL_INCREASING,
153 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
157 device_class=SensorDeviceClass.VOLTAGE,
158 state_class=SensorStateClass.MEASUREMENT,
159 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
162 key=
"Wind direction",
163 translation_key=
"wind_direction",
164 state_class=SensorStateClass.MEASUREMENT,
165 native_unit_of_measurement=DEGREE,
169 state_class=SensorStateClass.MEASUREMENT,
170 native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
171 device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
175 translation_key=
"sound",
179 translation_key=
"sensor_status",
183 translation_key=
"count",
184 state_class=SensorStateClass.TOTAL_INCREASING,
185 native_unit_of_measurement=
"count",
189 translation_key=
"counter_value",
190 state_class=SensorStateClass.TOTAL_INCREASING,
191 native_unit_of_measurement=
"count",
195 translation_key=
"chill",
196 device_class=SensorDeviceClass.TEMPERATURE,
197 state_class=SensorStateClass.MEASUREMENT,
198 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
201 key=
"Wind average speed",
202 translation_key=
"wind_average_speed",
203 state_class=SensorStateClass.MEASUREMENT,
204 native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
205 device_class=SensorDeviceClass.WIND_SPEED,
209 translation_key=
"wind_gust",
210 state_class=SensorStateClass.MEASUREMENT,
211 native_unit_of_measurement=UnitOfSpeed.METERS_PER_SECOND,
212 device_class=SensorDeviceClass.WIND_SPEED,
216 state_class=SensorStateClass.MEASUREMENT,
217 native_unit_of_measurement=UnitOfPrecipitationDepth.MILLIMETERS,
218 device_class=SensorDeviceClass.PRECIPITATION,
222 translation_key=
"forecast_status",
225 key=
"Forecast numeric",
226 translation_key=
"forecast",
229 key=
"Humidity status",
230 translation_key=
"humidity_status",
234 translation_key=
"uv_index",
235 state_class=SensorStateClass.MEASUREMENT,
236 native_unit_of_measurement=UV_INDEX,
240 SENSOR_TYPES_DICT = {desc.key: desc
for desc
in SENSOR_TYPES}
245 config_entry: ConfigEntry,
246 async_add_entities: AddEntitiesCallback,
248 """Set up config entry."""
250 def _supported(event: RFXtrxEvent) -> bool:
251 return isinstance(event, (ControlEvent, SensorEvent))
255 auto: RFXtrxEvent |
None,
256 device_id: DeviceTuple,
257 entity_info: dict[str, Any],
263 SENSOR_TYPES_DICT[data_type],
264 event=event
if auto
else None,
266 for data_type
in set(event.values) & set(SENSOR_TYPES_DICT)
270 hass, config_entry, async_add_entities, _supported, _constructor
276 """Representation of a RFXtrx sensor.
278 Since all repeated events have meaning, these types of sensors
279 need to have force update enabled.
282 _attr_force_update =
True
283 entity_description: RfxtrxSensorEntityDescription
287 device: RFXtrxDevice,
288 device_id: DeviceTuple,
289 entity_description: RfxtrxSensorEntityDescription,
290 event: RFXtrxEvent |
None =
None,
292 """Initialize the sensor."""
293 super().
__init__(device, device_id, event=event)
298 """Restore device state."""
304 and (event := old_state.attributes.get(ATTR_EVENT))
310 """Return the state of the sensor."""
317 def _handle_event(self, event: RFXtrxEvent, device_id: DeviceTuple) ->
None:
318 """Check if event applies to me and update."""
326 "Sensor update (Device ID: %s Class: %s Sub: %s)",
327 event.device.id_string,
328 event.device.__class__.__name__,
329 event.device.subtype,
None _apply_event(self, rfxtrxmod.RFXtrxEvent event)
None _handle_event(self, RFXtrxEvent event, DeviceTuple device_id)
None __init__(self, RFXtrxDevice device, DeviceTuple device_id, RfxtrxSensorEntityDescription entity_description, RFXtrxEvent|None event=None)
StateType|date|datetime|Decimal native_value(self)
None async_added_to_hass(self)
None async_write_ha_state(self)
State|None async_get_last_state(self)
int|None _battery_convert(int|None value)
str|None _rssi_convert(int|None value)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
None async_setup_platform_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities, Callable[[rfxtrxmod.RFXtrxEvent], bool] supported, Callable[[rfxtrxmod.RFXtrxEvent, rfxtrxmod.RFXtrxEvent|None, DeviceTuple, dict[str, Any],], list[Entity],] constructor)
rfxtrxmod.RFXtrxEvent|None get_rfx_object(str packetid)