"""Support for HomeMatic sensors.""" from __future__ import annotations from copy import copy import logging from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, SensorEntityDescription, SensorStateClass, ) from homeassistant.const import ( ATTR_NAME, CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, CONCENTRATION_PARTS_PER_MILLION, DEGREE, ELECTRIC_CURRENT_MILLIAMPERE, ELECTRIC_POTENTIAL_VOLT, ENERGY_WATT_HOUR, FREQUENCY_HERTZ, LENGTH_MILLIMETERS, LIGHT_LUX, PERCENTAGE, POWER_WATT, PRESSURE_HPA, SPEED_KILOMETERS_PER_HOUR, TEMP_CELSIUS, VOLUME_CUBIC_METERS, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from .const import ATTR_DISCOVER_DEVICES, ATTR_PARAM from .entity import HMDevice _LOGGER = logging.getLogger(__name__) HM_STATE_HA_CAST = { "IPGarage": {0: "closed", 1: "open", 2: "ventilation", 3: None}, "RotaryHandleSensor": {0: "closed", 1: "tilted", 2: "open"}, "RotaryHandleSensorIP": {0: "closed", 1: "tilted", 2: "open"}, "WaterSensor": {0: "dry", 1: "wet", 2: "water"}, "CO2Sensor": {0: "normal", 1: "added", 2: "strong"}, "IPSmoke": {0: "off", 1: "primary", 2: "intrusion", 3: "secondary"}, "RFSiren": { 0: "disarmed", 1: "extsens_armed", 2: "allsens_armed", 3: "alarm_blocked", }, "IPLockDLD": {0: None, 1: "locked", 2: "unlocked"}, } SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = { "HUMIDITY": SensorEntityDescription( key="HUMIDITY", native_unit_of_measurement=PERCENTAGE, device_class=SensorDeviceClass.HUMIDITY, state_class=SensorStateClass.MEASUREMENT, ), "ACTUAL_TEMPERATURE": SensorEntityDescription( key="ACTUAL_TEMPERATURE", native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, ), "TEMPERATURE": SensorEntityDescription( key="TEMPERATURE", native_unit_of_measurement=TEMP_CELSIUS, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, ), "LUX": SensorEntityDescription( key="LUX", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "CURRENT_ILLUMINATION": SensorEntityDescription( key="CURRENT_ILLUMINATION", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "ILLUMINATION": SensorEntityDescription( key="ILLUMINATION", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "AVERAGE_ILLUMINATION": SensorEntityDescription( key="AVERAGE_ILLUMINATION", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "LOWEST_ILLUMINATION": SensorEntityDescription( key="LOWEST_ILLUMINATION", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "HIGHEST_ILLUMINATION": SensorEntityDescription( key="HIGHEST_ILLUMINATION", native_unit_of_measurement=LIGHT_LUX, device_class=SensorDeviceClass.ILLUMINANCE, state_class=SensorStateClass.MEASUREMENT, ), "POWER": SensorEntityDescription( key="POWER", native_unit_of_measurement=POWER_WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), "IEC_POWER": SensorEntityDescription( key="IEC_POWER", native_unit_of_measurement=POWER_WATT, device_class=SensorDeviceClass.POWER, state_class=SensorStateClass.MEASUREMENT, ), "CURRENT": SensorEntityDescription( key="CURRENT", native_unit_of_measurement=ELECTRIC_CURRENT_MILLIAMPERE, device_class=SensorDeviceClass.CURRENT, state_class=SensorStateClass.MEASUREMENT, ), "CONCENTRATION": SensorEntityDescription( key="CONCENTRATION", native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, device_class=SensorDeviceClass.CO2, state_class=SensorStateClass.MEASUREMENT, ), "ENERGY_COUNTER": SensorEntityDescription( key="ENERGY_COUNTER", native_unit_of_measurement=ENERGY_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), "IEC_ENERGY_COUNTER": SensorEntityDescription( key="IEC_ENERGY_COUNTER", native_unit_of_measurement=ENERGY_WATT_HOUR, device_class=SensorDeviceClass.ENERGY, state_class=SensorStateClass.TOTAL_INCREASING, ), "VOLTAGE": SensorEntityDescription( key="VOLTAGE", native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT, device_class=SensorDeviceClass.VOLTAGE, state_class=SensorStateClass.MEASUREMENT, ), "GAS_POWER": SensorEntityDescription( key="GAS_POWER", native_unit_of_measurement=VOLUME_CUBIC_METERS, device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.MEASUREMENT, ), "GAS_ENERGY_COUNTER": SensorEntityDescription( key="GAS_ENERGY_COUNTER", native_unit_of_measurement=VOLUME_CUBIC_METERS, device_class=SensorDeviceClass.GAS, state_class=SensorStateClass.TOTAL_INCREASING, ), "RAIN_COUNTER": SensorEntityDescription( key="RAIN_COUNTER", native_unit_of_measurement=LENGTH_MILLIMETERS, ), "WIND_SPEED": SensorEntityDescription( key="WIND_SPEED", native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR, icon="mdi:weather-windy", ), "WIND_DIRECTION": SensorEntityDescription( key="WIND_DIRECTION", native_unit_of_measurement=DEGREE, ), "WIND_DIRECTION_RANGE": SensorEntityDescription( key="WIND_DIRECTION_RANGE", native_unit_of_measurement=DEGREE, ), "SUNSHINEDURATION": SensorEntityDescription( key="SUNSHINEDURATION", native_unit_of_measurement="#", ), "AIR_PRESSURE": SensorEntityDescription( key="AIR_PRESSURE", native_unit_of_measurement=PRESSURE_HPA, device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, ), "FREQUENCY": SensorEntityDescription( key="FREQUENCY", native_unit_of_measurement=FREQUENCY_HERTZ, ), "VALUE": SensorEntityDescription( key="VALUE", native_unit_of_measurement="#", ), "VALVE_STATE": SensorEntityDescription( key="VALVE_STATE", native_unit_of_measurement=PERCENTAGE, ), "CARRIER_SENSE_LEVEL": SensorEntityDescription( key="CARRIER_SENSE_LEVEL", native_unit_of_measurement=PERCENTAGE, ), "DUTY_CYCLE_LEVEL": SensorEntityDescription( key="DUTY_CYCLE_LEVEL", native_unit_of_measurement=PERCENTAGE, ), "BRIGHTNESS": SensorEntityDescription( key="BRIGHTNESS", native_unit_of_measurement="#", icon="mdi:invert-colors", ), "MASS_CONCENTRATION_PM_1": SensorEntityDescription( key="MASS_CONCENTRATION_PM_1", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM1, state_class=SensorStateClass.MEASUREMENT, ), "MASS_CONCENTRATION_PM_2_5": SensorEntityDescription( key="MASS_CONCENTRATION_PM_2_5", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM25, state_class=SensorStateClass.MEASUREMENT, ), "MASS_CONCENTRATION_PM_10": SensorEntityDescription( key="MASS_CONCENTRATION_PM_10", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM10, state_class=SensorStateClass.MEASUREMENT, ), "MASS_CONCENTRATION_PM_1_24H_AVERAGE": SensorEntityDescription( key="MASS_CONCENTRATION_PM_1_24H_AVERAGE", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM1, state_class=SensorStateClass.MEASUREMENT, ), "MASS_CONCENTRATION_PM_2_5_24H_AVERAGE": SensorEntityDescription( key="MASS_CONCENTRATION_PM_2_5_24H_AVERAGE", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM25, state_class=SensorStateClass.MEASUREMENT, ), "MASS_CONCENTRATION_PM_10_24H_AVERAGE": SensorEntityDescription( key="MASS_CONCENTRATION_PM_10_24H_AVERAGE", native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, device_class=SensorDeviceClass.PM10, state_class=SensorStateClass.MEASUREMENT, ), } DEFAULT_SENSOR_DESCRIPTION = SensorEntityDescription( key="", entity_registry_enabled_default=True, ) def setup_platform( hass: HomeAssistant, config: ConfigType, add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the HomeMatic sensor platform.""" if discovery_info is None: return devices = [] for conf in discovery_info[ATTR_DISCOVER_DEVICES]: state = conf.get(ATTR_PARAM) if (entity_desc := SENSOR_DESCRIPTIONS.get(state)) is None: name = conf.get(ATTR_NAME) _LOGGER.warning( "Sensor (%s) entity description is missing. Sensor state (%s) needs to be maintained", name, state, ) entity_desc = copy(DEFAULT_SENSOR_DESCRIPTION) new_device = HMSensor(conf, entity_desc) devices.append(new_device) add_entities(devices, True) class HMSensor(HMDevice, SensorEntity): """Representation of a HomeMatic sensor.""" @property def native_value(self): """Return the state of the sensor.""" # Does a cast exist for this class? name = self._hmdevice.__class__.__name__ if name in HM_STATE_HA_CAST: return HM_STATE_HA_CAST[name].get(self._hm_get_state()) # No cast, return original value return self._hm_get_state() def _init_data_struct(self): """Generate a data dictionary (self._data) from metadata.""" if self._state: self._data.update({self._state: None}) else: _LOGGER.critical("Unable to initialize sensor: %s", self._name)