1 """Support for sensors through the SmartThings cloud API."""
3 from __future__
import annotations
5 from collections.abc
import Sequence
6 from typing
import NamedTuple
8 from pysmartthings
import Attribute, Capability
9 from pysmartthings.device
import DeviceEntity
18 CONCENTRATION_PARTS_PER_MILLION,
23 UnitOfElectricPotential,
34 from .const
import DATA_BROKERS, DOMAIN
35 from .entity
import SmartThingsEntity
38 class Map(NamedTuple):
39 """Tuple for mapping Smartthings capabilities to Home Assistant sensors."""
43 default_unit: str |
None
44 device_class: SensorDeviceClass |
None
45 state_class: SensorStateClass |
None
46 entity_category: EntityCategory |
None
49 CAPABILITY_TO_SENSORS: dict[str, list[Map]] = {
50 Capability.activity_lighting_mode: [
52 Attribute.lighting_mode,
53 "Activity Lighting Mode",
57 EntityCategory.DIAGNOSTIC,
60 Capability.air_conditioner_mode: [
62 Attribute.air_conditioner_mode,
63 "Air Conditioner Mode",
67 EntityCategory.DIAGNOSTIC,
70 Capability.air_quality_sensor: [
72 Attribute.air_quality,
76 SensorStateClass.MEASUREMENT,
80 Capability.alarm: [
Map(Attribute.alarm,
"Alarm",
None,
None,
None,
None)],
81 Capability.audio_volume: [
82 Map(Attribute.volume,
"Volume", PERCENTAGE,
None,
None,
None)
89 SensorDeviceClass.BATTERY,
91 EntityCategory.DIAGNOSTIC,
94 Capability.body_mass_index_measurement: [
96 Attribute.bmi_measurement,
98 f
"{UnitOfMass.KILOGRAMS}/{UnitOfArea.SQUARE_METERS}",
100 SensorStateClass.MEASUREMENT,
104 Capability.body_weight_measurement: [
106 Attribute.body_weight_measurement,
108 UnitOfMass.KILOGRAMS,
109 SensorDeviceClass.WEIGHT,
110 SensorStateClass.MEASUREMENT,
114 Capability.carbon_dioxide_measurement: [
116 Attribute.carbon_dioxide,
117 "Carbon Dioxide Measurement",
118 CONCENTRATION_PARTS_PER_MILLION,
119 SensorDeviceClass.CO2,
120 SensorStateClass.MEASUREMENT,
124 Capability.carbon_monoxide_detector: [
126 Attribute.carbon_monoxide,
127 "Carbon Monoxide Detector",
134 Capability.carbon_monoxide_measurement: [
136 Attribute.carbon_monoxide_level,
137 "Carbon Monoxide Measurement",
138 CONCENTRATION_PARTS_PER_MILLION,
139 SensorDeviceClass.CO,
140 SensorStateClass.MEASUREMENT,
144 Capability.dishwasher_operating_state: [
146 Attribute.machine_state,
"Dishwasher Machine State",
None,
None,
None,
None
149 Attribute.dishwasher_job_state,
150 "Dishwasher Job State",
157 Attribute.completion_time,
158 "Dishwasher Completion Time",
160 SensorDeviceClass.TIMESTAMP,
165 Capability.dryer_mode: [
167 Attribute.dryer_mode,
172 EntityCategory.DIAGNOSTIC,
175 Capability.dryer_operating_state: [
176 Map(Attribute.machine_state,
"Dryer Machine State",
None,
None,
None,
None),
177 Map(Attribute.dryer_job_state,
"Dryer Job State",
None,
None,
None,
None),
179 Attribute.completion_time,
180 "Dryer Completion Time",
182 SensorDeviceClass.TIMESTAMP,
187 Capability.dust_sensor: [
189 Attribute.fine_dust_level,
193 SensorStateClass.MEASUREMENT,
197 Attribute.dust_level,
201 SensorStateClass.MEASUREMENT,
205 Capability.energy_meter: [
209 UnitOfEnergy.KILO_WATT_HOUR,
210 SensorDeviceClass.ENERGY,
211 SensorStateClass.TOTAL_INCREASING,
215 Capability.equivalent_carbon_dioxide_measurement: [
217 Attribute.equivalent_carbon_dioxide_measurement,
218 "Equivalent Carbon Dioxide Measurement",
219 CONCENTRATION_PARTS_PER_MILLION,
220 SensorDeviceClass.CO2,
221 SensorStateClass.MEASUREMENT,
225 Capability.formaldehyde_measurement: [
227 Attribute.formaldehyde_level,
228 "Formaldehyde Measurement",
229 CONCENTRATION_PARTS_PER_MILLION,
231 SensorStateClass.MEASUREMENT,
235 Capability.gas_meter: [
239 UnitOfEnergy.KILO_WATT_HOUR,
240 SensorDeviceClass.ENERGY,
241 SensorStateClass.MEASUREMENT,
245 Attribute.gas_meter_calorific,
"Gas Meter Calorific",
None,
None,
None,
None
248 Attribute.gas_meter_time,
251 SensorDeviceClass.TIMESTAMP,
256 Attribute.gas_meter_volume,
258 UnitOfVolume.CUBIC_METERS,
259 SensorDeviceClass.GAS,
260 SensorStateClass.MEASUREMENT,
264 Capability.illuminance_measurement: [
266 Attribute.illuminance,
269 SensorDeviceClass.ILLUMINANCE,
270 SensorStateClass.MEASUREMENT,
274 Capability.infrared_level: [
276 Attribute.infrared_level,
280 SensorStateClass.MEASUREMENT,
284 Capability.media_input_source: [
285 Map(Attribute.input_source,
"Media Input Source",
None,
None,
None,
None)
287 Capability.media_playback_repeat: [
289 Attribute.playback_repeat_mode,
290 "Media Playback Repeat",
297 Capability.media_playback_shuffle: [
299 Attribute.playback_shuffle,
"Media Playback Shuffle",
None,
None,
None,
None
302 Capability.media_playback: [
303 Map(Attribute.playback_status,
"Media Playback Status",
None,
None,
None,
None)
305 Capability.odor_sensor: [
306 Map(Attribute.odor_level,
"Odor Sensor",
None,
None,
None,
None)
308 Capability.oven_mode: [
315 EntityCategory.DIAGNOSTIC,
318 Capability.oven_operating_state: [
319 Map(Attribute.machine_state,
"Oven Machine State",
None,
None,
None,
None),
320 Map(Attribute.oven_job_state,
"Oven Job State",
None,
None,
None,
None),
321 Map(Attribute.completion_time,
"Oven Completion Time",
None,
None,
None,
None),
323 Capability.oven_setpoint: [
324 Map(Attribute.oven_setpoint,
"Oven Set Point",
None,
None,
None,
None)
326 Capability.power_consumption_report: [],
327 Capability.power_meter: [
332 SensorDeviceClass.POWER,
333 SensorStateClass.MEASUREMENT,
337 Capability.power_source: [
339 Attribute.power_source,
344 EntityCategory.DIAGNOSTIC,
347 Capability.refrigeration_setpoint: [
349 Attribute.refrigeration_setpoint,
350 "Refrigeration Setpoint",
352 SensorDeviceClass.TEMPERATURE,
357 Capability.relative_humidity_measurement: [
360 "Relative Humidity Measurement",
362 SensorDeviceClass.HUMIDITY,
363 SensorStateClass.MEASUREMENT,
367 Capability.robot_cleaner_cleaning_mode: [
369 Attribute.robot_cleaner_cleaning_mode,
370 "Robot Cleaner Cleaning Mode",
374 EntityCategory.DIAGNOSTIC,
377 Capability.robot_cleaner_movement: [
379 Attribute.robot_cleaner_movement,
380 "Robot Cleaner Movement",
387 Capability.robot_cleaner_turbo_mode: [
389 Attribute.robot_cleaner_turbo_mode,
390 "Robot Cleaner Turbo Mode",
394 EntityCategory.DIAGNOSTIC,
397 Capability.signal_strength: [
400 "LQI Signal Strength",
403 SensorStateClass.MEASUREMENT,
404 EntityCategory.DIAGNOSTIC,
408 "RSSI Signal Strength",
410 SensorDeviceClass.SIGNAL_STRENGTH,
411 SensorStateClass.MEASUREMENT,
412 EntityCategory.DIAGNOSTIC,
415 Capability.smoke_detector: [
416 Map(Attribute.smoke,
"Smoke Detector",
None,
None,
None,
None)
418 Capability.temperature_measurement: [
420 Attribute.temperature,
421 "Temperature Measurement",
423 SensorDeviceClass.TEMPERATURE,
424 SensorStateClass.MEASUREMENT,
428 Capability.thermostat_cooling_setpoint: [
430 Attribute.cooling_setpoint,
431 "Thermostat Cooling Setpoint",
433 SensorDeviceClass.TEMPERATURE,
438 Capability.thermostat_fan_mode: [
440 Attribute.thermostat_fan_mode,
441 "Thermostat Fan Mode",
445 EntityCategory.DIAGNOSTIC,
448 Capability.thermostat_heating_setpoint: [
450 Attribute.heating_setpoint,
451 "Thermostat Heating Setpoint",
453 SensorDeviceClass.TEMPERATURE,
455 EntityCategory.DIAGNOSTIC,
458 Capability.thermostat_mode: [
460 Attribute.thermostat_mode,
465 EntityCategory.DIAGNOSTIC,
468 Capability.thermostat_operating_state: [
470 Attribute.thermostat_operating_state,
471 "Thermostat Operating State",
478 Capability.thermostat_setpoint: [
480 Attribute.thermostat_setpoint,
481 "Thermostat Setpoint",
483 SensorDeviceClass.TEMPERATURE,
485 EntityCategory.DIAGNOSTIC,
488 Capability.three_axis: [],
489 Capability.tv_channel: [
490 Map(Attribute.tv_channel,
"Tv Channel",
None,
None,
None,
None),
491 Map(Attribute.tv_channel_name,
"Tv Channel Name",
None,
None,
None,
None),
493 Capability.tvoc_measurement: [
495 Attribute.tvoc_level,
497 CONCENTRATION_PARTS_PER_MILLION,
499 SensorStateClass.MEASUREMENT,
503 Capability.ultraviolet_index: [
505 Attribute.ultraviolet_index,
509 SensorStateClass.MEASUREMENT,
513 Capability.voltage_measurement: [
516 "Voltage Measurement",
517 UnitOfElectricPotential.VOLT,
518 SensorDeviceClass.VOLTAGE,
519 SensorStateClass.MEASUREMENT,
523 Capability.washer_mode: [
525 Attribute.washer_mode,
530 EntityCategory.DIAGNOSTIC,
533 Capability.washer_operating_state: [
534 Map(Attribute.machine_state,
"Washer Machine State",
None,
None,
None,
None),
535 Map(Attribute.washer_job_state,
"Washer Job State",
None,
None,
None,
None),
537 Attribute.completion_time,
538 "Washer Completion Time",
540 SensorDeviceClass.TIMESTAMP,
548 "C": UnitOfTemperature.CELSIUS,
549 "F": UnitOfTemperature.FAHRENHEIT,
553 THREE_AXIS_NAMES = [
"X Coordinate",
"Y Coordinate",
"Z Coordinate"]
554 POWER_CONSUMPTION_REPORT_NAMES = [
565 config_entry: ConfigEntry,
566 async_add_entities: AddEntitiesCallback,
568 """Add sensors for a config entry."""
569 broker = hass.data[DOMAIN][DATA_BROKERS][config_entry.entry_id]
570 entities: list[SensorEntity] = []
571 for device
in broker.devices.values():
572 for capability
in broker.get_assigned(device.device_id,
"sensor"):
573 if capability == Capability.three_axis:
577 for index
in range(len(THREE_AXIS_NAMES))
580 elif capability == Capability.power_consumption_report:
584 for report_name
in POWER_CONSUMPTION_REPORT_NAMES
588 maps = CAPABILITY_TO_SENSORS[capability]
604 if broker.any_assigned(device.device_id,
"switch"):
605 for capability
in (Capability.energy_meter, Capability.power_meter):
606 maps = CAPABILITY_TO_SENSORS[capability]
626 """Return all capabilities supported if minimum required are present."""
628 capability
for capability
in CAPABILITY_TO_SENSORS
if capability
in capabilities
633 """Define a SmartThings Sensor."""
637 device: DeviceEntity,
640 default_unit: str |
None,
641 device_class: SensorDeviceClass |
None,
642 state_class: str |
None,
643 entity_category: EntityCategory |
None,
645 """Init the class."""
657 """Return the state of the sensor."""
663 return dt_util.parse_datetime(value)
667 """Return the unit this state is expressed in."""
669 return UNITS.get(unit, unit)
if unit
else self.
_default_unit_default_unit
673 """Define a SmartThings Three Axis Sensor."""
676 """Init the class."""
684 """Return the state of the sensor."""
685 three_axis = self.
_device_device.status.attributes[Attribute.three_axis].value
687 return three_axis[self.
_index_index]
688 except (TypeError, IndexError):
693 """Define a SmartThings Sensor."""
697 device: DeviceEntity,
700 """Init the class."""
716 """Return the state of the sensor."""
717 value = self.
_device_device.status.attributes[Attribute.power_consumption].value
718 if value
is None or value.get(self.
report_namereport_name)
is None:
726 """Return specific state attributes."""
729 "power_consumption_start",
730 "power_consumption_end",
732 state_attributes = {}
733 for attribute
in attributes:
734 value = getattr(self.
_device_device.status, attribute)
735 if value
is not None:
736 state_attributes[attribute] = value
737 return state_attributes
SensorDeviceClass|None device_class(self)
_attr_native_unit_of_measurement
None __init__(self, DeviceEntity device, str report_name)
def extra_state_attributes(self)
def native_unit_of_measurement(self)
None __init__(self, DeviceEntity device, str attribute, str name, str|None default_unit, SensorDeviceClass|None device_class, str|None state_class, EntityCategory|None entity_category)
def __init__(self, device, index)
str|None device_class(self)
Sequence[str]|None get_capabilities(Sequence[str] capabilities)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)