Add Sensor descriptions for Bosch SHC (#116775)

* Add Sensor descriptions for Bosch SHC

* fix

* fix

* fix
This commit is contained in:
Joost Lekkerkerker 2024-05-05 15:44:11 +02:00 committed by GitHub
parent cb9914becd
commit da5d975e22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2,12 +2,17 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from boschshcpy import SHCSession from boschshcpy import SHCSession
from boschshcpy.device import SHCDevice from boschshcpy.device import SHCDevice
from homeassistant.components.sensor import ( from homeassistant.components.sensor import (
SensorDeviceClass, SensorDeviceClass,
SensorEntity, SensorEntity,
SensorEntityDescription,
SensorStateClass, SensorStateClass,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
@ -20,341 +25,207 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import DATA_SESSION, DOMAIN from .const import DATA_SESSION, DOMAIN
from .entity import SHCEntity from .entity import SHCEntity
@dataclass(frozen=True, kw_only=True)
class SHCSensorEntityDescription(SensorEntityDescription):
"""Describes a SHC sensor."""
value_fn: Callable[[SHCDevice], StateType]
attributes_fn: Callable[[SHCDevice], dict[str, Any]] | None = None
TEMPERATURE_SENSOR = "temperature"
HUMIDITY_SENSOR = "humidity"
VALVE_TAPPET_SENSOR = "valvetappet"
PURITY_SENSOR = "purity"
AIR_QUALITY_SENSOR = "airquality"
TEMPERATURE_RATING_SENSOR = "temperature_rating"
HUMIDITY_RATING_SENSOR = "humidity_rating"
PURITY_RATING_SENSOR = "purity_rating"
POWER_SENSOR = "power"
ENERGY_SENSOR = "energy"
COMMUNICATION_QUALITY_SENSOR = "communication_quality"
SENSOR_DESCRIPTIONS: dict[str, SHCSensorEntityDescription] = {
TEMPERATURE_SENSOR: SHCSensorEntityDescription(
key=TEMPERATURE_SENSOR,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda device: device.temperature,
),
HUMIDITY_SENSOR: SHCSensorEntityDescription(
key=HUMIDITY_SENSOR,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda device: device.humidity,
),
PURITY_SENSOR: SHCSensorEntityDescription(
key=PURITY_SENSOR,
translation_key=PURITY_SENSOR,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
value_fn=lambda device: device.purity,
),
AIR_QUALITY_SENSOR: SHCSensorEntityDescription(
key=AIR_QUALITY_SENSOR,
translation_key="air_quality",
value_fn=lambda device: device.combined_rating.name,
attributes_fn=lambda device: {
"rating_description": device.description,
},
),
TEMPERATURE_RATING_SENSOR: SHCSensorEntityDescription(
key=TEMPERATURE_RATING_SENSOR,
translation_key=TEMPERATURE_RATING_SENSOR,
value_fn=lambda device: device.temperature_rating.name,
),
COMMUNICATION_QUALITY_SENSOR: SHCSensorEntityDescription(
key=COMMUNICATION_QUALITY_SENSOR,
translation_key=COMMUNICATION_QUALITY_SENSOR,
value_fn=lambda device: device.communicationquality.name,
),
HUMIDITY_RATING_SENSOR: SHCSensorEntityDescription(
key=HUMIDITY_RATING_SENSOR,
translation_key=HUMIDITY_RATING_SENSOR,
value_fn=lambda device: device.humidity_rating.name,
),
PURITY_RATING_SENSOR: SHCSensorEntityDescription(
key=PURITY_RATING_SENSOR,
translation_key=PURITY_RATING_SENSOR,
value_fn=lambda device: device.purity_rating.name,
),
POWER_SENSOR: SHCSensorEntityDescription(
key=POWER_SENSOR,
device_class=SensorDeviceClass.POWER,
native_unit_of_measurement=UnitOfPower.WATT,
value_fn=lambda device: device.powerconsumption,
),
ENERGY_SENSOR: SHCSensorEntityDescription(
key=ENERGY_SENSOR,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
value_fn=lambda device: device.energyconsumption / 1000.0,
),
VALVE_TAPPET_SENSOR: SHCSensorEntityDescription(
key=VALVE_TAPPET_SENSOR,
translation_key=VALVE_TAPPET_SENSOR,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda device: device.position,
attributes_fn=lambda device: {
"valve_tappet_state": device.valvestate.name,
},
),
}
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the SHC sensor platform.""" """Set up the SHC sensor platform."""
entities: list[SensorEntity] = []
session: SHCSession = hass.data[DOMAIN][config_entry.entry_id][DATA_SESSION] session: SHCSession = hass.data[DOMAIN][config_entry.entry_id][DATA_SESSION]
for sensor in session.device_helper.thermostats: entities: list[SensorEntity] = [
entities.append( SHCSensor(
TemperatureSensor( device,
device=sensor, SENSOR_DESCRIPTIONS[sensor_type],
parent_id=session.information.unique_id, session.information.unique_id,
entry_id=config_entry.entry_id, config_entry.entry_id,
)
)
entities.append(
ValveTappetSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
for device in session.device_helper.thermostats
for sensor_type in (TEMPERATURE_SENSOR, VALVE_TAPPET_SENSOR)
]
for sensor in session.device_helper.wallthermostats: entities.extend(
entities.append( SHCSensor(
TemperatureSensor( device,
device=sensor, SENSOR_DESCRIPTIONS[sensor_type],
parent_id=session.information.unique_id, session.information.unique_id,
entry_id=config_entry.entry_id, config_entry.entry_id,
)
)
entities.append(
HumiditySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
for device in session.device_helper.wallthermostats
for sensor_type in (TEMPERATURE_SENSOR, HUMIDITY_SENSOR)
)
for sensor in session.device_helper.twinguards: entities.extend(
entities.append( SHCSensor(
TemperatureSensor( device,
device=sensor, SENSOR_DESCRIPTIONS[sensor_type],
parent_id=session.information.unique_id, session.information.unique_id,
entry_id=config_entry.entry_id, config_entry.entry_id,
)
) )
entities.append( for device in session.device_helper.twinguards
HumiditySensor( for sensor_type in (
device=sensor, TEMPERATURE_SENSOR,
parent_id=session.information.unique_id, HUMIDITY_SENSOR,
entry_id=config_entry.entry_id, PURITY_SENSOR,
) AIR_QUALITY_SENSOR,
) TEMPERATURE_RATING_SENSOR,
entities.append( HUMIDITY_RATING_SENSOR,
PuritySensor( PURITY_RATING_SENSOR,
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
AirQualitySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
TemperatureRatingSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
HumidityRatingSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
PurityRatingSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
)
for sensor in ( entities.extend(
session.device_helper.smart_plugs + session.device_helper.light_switches_bsm SHCSensor(
): device,
entities.append( SENSOR_DESCRIPTIONS[sensor_type],
PowerSensor( session.information.unique_id,
device=sensor, config_entry.entry_id,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
entities.append( for device in (
EnergySensor( session.device_helper.smart_plugs + session.device_helper.light_switches_bsm
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
for sensor_type in (POWER_SENSOR, ENERGY_SENSOR)
)
for sensor in session.device_helper.smart_plugs_compact: entities.extend(
entities.append( SHCSensor(
PowerSensor( device,
device=sensor, SENSOR_DESCRIPTIONS[sensor_type],
parent_id=session.information.unique_id, session.information.unique_id,
entry_id=config_entry.entry_id, config_entry.entry_id,
)
)
entities.append(
EnergySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
CommunicationQualitySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
) )
for device in session.device_helper.smart_plugs_compact
for sensor_type in (POWER_SENSOR, ENERGY_SENSOR, COMMUNICATION_QUALITY_SENSOR)
)
async_add_entities(entities) async_add_entities(entities)
class TemperatureSensor(SHCEntity, SensorEntity): class SHCSensor(SHCEntity, SensorEntity):
"""Representation of an SHC temperature reporting sensor.""" """Representation of a SHC sensor."""
_attr_device_class = SensorDeviceClass.TEMPERATURE entity_description: SHCSensorEntityDescription
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: def __init__(
"""Initialize an SHC temperature reporting sensor.""" self,
device: SHCDevice,
entity_description: SHCSensorEntityDescription,
parent_id: str,
entry_id: str,
) -> None:
"""Initialize sensor."""
super().__init__(device, parent_id, entry_id) super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_temperature" self.entity_description = entity_description
self._attr_unique_id = f"{device.serial}_{entity_description.key}"
@property @property
def native_value(self): def native_value(self) -> StateType:
"""Return the state of the sensor.""" """Return the state of the sensor."""
return self._device.temperature return self.entity_description.value_fn(self._device)
class HumiditySensor(SHCEntity, SensorEntity):
"""Representation of an SHC humidity reporting sensor."""
_attr_device_class = SensorDeviceClass.HUMIDITY
_attr_native_unit_of_measurement = PERCENTAGE
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC humidity reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_humidity"
@property @property
def native_value(self): def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return the state of the sensor."""
return self._device.humidity
class PuritySensor(SHCEntity, SensorEntity):
"""Representation of an SHC purity reporting sensor."""
_attr_translation_key = "purity"
_attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC purity reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_purity"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.purity
class AirQualitySensor(SHCEntity, SensorEntity):
"""Representation of an SHC airquality reporting sensor."""
_attr_translation_key = "air_quality"
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC airquality reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_airquality"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.combined_rating.name
@property
def extra_state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""
return { if self.entity_description.attributes_fn is not None:
"rating_description": self._device.description, return self.entity_description.attributes_fn(self._device)
} return None
class TemperatureRatingSensor(SHCEntity, SensorEntity):
"""Representation of an SHC temperature rating sensor."""
_attr_translation_key = "temperature_rating"
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC temperature rating sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_temperature_rating"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.temperature_rating.name
class CommunicationQualitySensor(SHCEntity, SensorEntity):
"""Representation of an SHC communication quality reporting sensor."""
_attr_translation_key = "communication_quality"
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC communication quality reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_communication_quality"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.communicationquality.name
class HumidityRatingSensor(SHCEntity, SensorEntity):
"""Representation of an SHC humidity rating sensor."""
_attr_translation_key = "humidity_rating"
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC humidity rating sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_humidity_rating"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.humidity_rating.name
class PurityRatingSensor(SHCEntity, SensorEntity):
"""Representation of an SHC purity rating sensor."""
_attr_translation_key = "purity_rating"
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC purity rating sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_purity_rating"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.purity_rating.name
class PowerSensor(SHCEntity, SensorEntity):
"""Representation of an SHC power reporting sensor."""
_attr_device_class = SensorDeviceClass.POWER
_attr_native_unit_of_measurement = UnitOfPower.WATT
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC power reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_power"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.powerconsumption
class EnergySensor(SHCEntity, SensorEntity):
"""Representation of an SHC energy reporting sensor."""
_attr_device_class = SensorDeviceClass.ENERGY
_attr_state_class = SensorStateClass.TOTAL_INCREASING
_attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC energy reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{self._device.serial}_energy"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.energyconsumption / 1000.0
class ValveTappetSensor(SHCEntity, SensorEntity):
"""Representation of an SHC valve tappet reporting sensor."""
_attr_translation_key = "valvetappet"
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = PERCENTAGE
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC valve tappet reporting sensor."""
super().__init__(device, parent_id, entry_id)
self._attr_unique_id = f"{device.serial}_valvetappet"
@property
def native_value(self):
"""Return the state of the sensor."""
return self._device.position
@property
def extra_state_attributes(self):
"""Return the state attributes."""
return {
"valve_tappet_state": self._device.valvestate.name,
}