1 """Sensor platform for Sensibo integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Mapping
6 from dataclasses
import dataclass
7 from datetime
import datetime
8 from typing
import TYPE_CHECKING, Any
10 from pysensibo.model
import MotionSensor, PureAQI, SensiboDevice
15 SensorEntityDescription,
19 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
20 CONCENTRATION_PARTS_PER_BILLION,
21 CONCENTRATION_PARTS_PER_MILLION,
23 SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
25 UnitOfElectricPotential,
32 from .
import SensiboConfigEntry
33 from .coordinator
import SensiboDataUpdateCoordinator
34 from .entity
import SensiboDeviceBaseEntity, SensiboMotionBaseEntity
39 @dataclass(frozen=True, kw_only=True)
41 """Describes Sensibo Motion sensor entity."""
43 value_fn: Callable[[MotionSensor], StateType]
46 @dataclass(frozen=True, kw_only=True)
48 """Describes Sensibo Device sensor entity."""
50 value_fn: Callable[[SensiboDevice], StateType | datetime]
51 extra_fn: Callable[[SensiboDevice], dict[str, str | bool |
None] |
None] |
None
55 key=
"filter_last_reset",
56 translation_key=
"filter_last_reset",
57 device_class=SensorDeviceClass.TIMESTAMP,
58 value_fn=
lambda data: data.filter_last_reset,
62 MOTION_SENSOR_TYPES: tuple[SensiboMotionSensorEntityDescription, ...] = (
65 translation_key=
"rssi",
66 device_class=SensorDeviceClass.SIGNAL_STRENGTH,
67 entity_category=EntityCategory.DIAGNOSTIC,
68 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
69 state_class=SensorStateClass.MEASUREMENT,
70 value_fn=
lambda data: data.rssi,
71 entity_registry_enabled_default=
False,
74 key=
"battery_voltage",
75 translation_key=
"battery_voltage",
76 device_class=SensorDeviceClass.VOLTAGE,
77 entity_category=EntityCategory.DIAGNOSTIC,
78 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
79 state_class=SensorStateClass.MEASUREMENT,
80 value_fn=
lambda data: data.battery_voltage,
84 device_class=SensorDeviceClass.HUMIDITY,
85 native_unit_of_measurement=PERCENTAGE,
86 state_class=SensorStateClass.MEASUREMENT,
87 value_fn=
lambda data: data.humidity,
91 device_class=SensorDeviceClass.TEMPERATURE,
92 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
93 state_class=SensorStateClass.MEASUREMENT,
94 value_fn=
lambda data: data.temperature,
97 PURE_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
100 translation_key=
"pm25_pure",
101 device_class=SensorDeviceClass.ENUM,
102 value_fn=
lambda data: data.pm25_pure.name.lower()
if data.pm25_pure
else None,
104 options=[aqi.name.lower()
for aqi
in PureAQI],
107 key=
"pure_sensitivity",
108 translation_key=
"sensitivity",
109 value_fn=
lambda data: data.pure_sensitivity,
112 FILTER_LAST_RESET_DESCRIPTION,
115 DEVICE_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
118 translation_key=
"timer_time",
119 device_class=SensorDeviceClass.TIMESTAMP,
120 value_fn=
lambda data: data.timer_time,
121 extra_fn=
lambda data: {
"id": data.timer_id,
"turn_on": data.timer_state_on},
125 translation_key=
"feels_like",
126 device_class=SensorDeviceClass.TEMPERATURE,
127 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
128 state_class=SensorStateClass.MEASUREMENT,
129 value_fn=
lambda data: data.feelslike,
131 entity_registry_enabled_default=
False,
134 key=
"climate_react_low",
135 translation_key=
"climate_react_low",
136 device_class=SensorDeviceClass.TEMPERATURE,
137 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
138 state_class=SensorStateClass.MEASUREMENT,
139 value_fn=
lambda data: data.smart_low_temp_threshold,
140 extra_fn=
lambda data: data.smart_low_state,
141 entity_registry_enabled_default=
False,
144 key=
"climate_react_high",
145 translation_key=
"climate_react_high",
146 device_class=SensorDeviceClass.TEMPERATURE,
147 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
148 state_class=SensorStateClass.MEASUREMENT,
149 value_fn=
lambda data: data.smart_high_temp_threshold,
150 extra_fn=
lambda data: data.smart_high_state,
151 entity_registry_enabled_default=
False,
154 key=
"climate_react_type",
155 translation_key=
"smart_type",
156 value_fn=
lambda data: data.smart_type,
158 entity_registry_enabled_default=
False,
160 FILTER_LAST_RESET_DESCRIPTION,
163 AIRQ_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
166 translation_key=
"airq_tvoc",
167 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
168 state_class=SensorStateClass.MEASUREMENT,
169 value_fn=
lambda data: data.tvoc,
174 translation_key=
"airq_co2",
175 device_class=SensorDeviceClass.CO2,
176 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
177 state_class=SensorStateClass.MEASUREMENT,
178 value_fn=
lambda data: data.co2,
181 *DEVICE_SENSOR_TYPES,
184 ELEMENT_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
187 device_class=SensorDeviceClass.PM25,
188 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
189 state_class=SensorStateClass.MEASUREMENT,
190 value_fn=
lambda data: data.pm25,
195 translation_key=
"tvoc",
196 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
197 state_class=SensorStateClass.MEASUREMENT,
198 value_fn=
lambda data: data.tvoc,
203 device_class=SensorDeviceClass.CO2,
204 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
205 state_class=SensorStateClass.MEASUREMENT,
206 value_fn=
lambda data: data.co2,
211 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
212 state_class=SensorStateClass.MEASUREMENT,
213 translation_key=
"ethanol",
214 value_fn=
lambda data: data.etoh,
219 device_class=SensorDeviceClass.AQI,
220 state_class=SensorStateClass.MEASUREMENT,
221 value_fn=
lambda data: data.iaq,
226 DESCRIPTION_BY_MODELS = {
227 "pure": PURE_SENSOR_TYPES,
228 "airq": AIRQ_SENSOR_TYPES,
229 "elements": ELEMENT_SENSOR_TYPES,
235 entry: SensiboConfigEntry,
236 async_add_entities: AddEntitiesCallback,
238 """Set up Sensibo sensor platform."""
240 coordinator = entry.runtime_data
242 entities: list[SensiboMotionSensor | SensiboDeviceSensor] = []
244 for device_id, device_data
in coordinator.data.parsed.items():
245 if device_data.motion_sensors:
248 coordinator, device_id, sensor_id, sensor_data, description
250 for sensor_id, sensor_data
in device_data.motion_sensors.items()
251 for description
in MOTION_SENSOR_TYPES
255 for device_id, device_data
in coordinator.data.parsed.items()
256 for description
in DESCRIPTION_BY_MODELS.get(
257 device_data.model, DEVICE_SENSOR_TYPES
264 """Representation of a Sensibo Motion Sensor."""
266 entity_description: SensiboMotionSensorEntityDescription
270 coordinator: SensiboDataUpdateCoordinator,
273 sensor_data: MotionSensor,
274 entity_description: SensiboMotionSensorEntityDescription,
276 """Initiate Sensibo Motion Sensor."""
288 """Return value of sensor."""
295 """Representation of a Sensibo Device Sensor."""
297 entity_description: SensiboDeviceSensorEntityDescription
301 coordinator: SensiboDataUpdateCoordinator,
303 entity_description: SensiboDeviceSensorEntityDescription,
305 """Initiate Sensibo Device Sensor."""
315 """Return value of sensor."""
320 """Return additional attributes."""
SensiboDevice device_data(self)
MotionSensor|None sensor_data(self)
StateType|datetime native_value(self)
None __init__(self, SensiboDataUpdateCoordinator coordinator, str device_id, SensiboDeviceSensorEntityDescription entity_description)
Mapping[str, Any]|None extra_state_attributes(self)
None __init__(self, SensiboDataUpdateCoordinator coordinator, str device_id, str sensor_id, MotionSensor sensor_data, SensiboMotionSensorEntityDescription entity_description)
StateType native_value(self)
None async_setup_entry(HomeAssistant hass, SensiboConfigEntry entry, AddEntitiesCallback async_add_entities)