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 collections.abc import Callable
from dataclasses import dataclass
from typing import Any
from boschshcpy import SHCSession
from boschshcpy.device import SHCDevice
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
@ -20,341 +25,207 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from .const import DATA_SESSION, DOMAIN
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(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the SHC sensor platform."""
entities: list[SensorEntity] = []
session: SHCSession = hass.data[DOMAIN][config_entry.entry_id][DATA_SESSION]
for sensor in session.device_helper.thermostats:
entities.append(
TemperatureSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
entities: list[SensorEntity] = [
SHCSensor(
device,
SENSOR_DESCRIPTIONS[sensor_type],
session.information.unique_id,
config_entry.entry_id,
)
for device in session.device_helper.thermostats
for sensor_type in (TEMPERATURE_SENSOR, VALVE_TAPPET_SENSOR)
]
entities.extend(
SHCSensor(
device,
SENSOR_DESCRIPTIONS[sensor_type],
session.information.unique_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.wallthermostats
for sensor_type in (TEMPERATURE_SENSOR, HUMIDITY_SENSOR)
)
entities.extend(
SHCSensor(
device,
SENSOR_DESCRIPTIONS[sensor_type],
session.information.unique_id,
config_entry.entry_id,
)
for device in session.device_helper.twinguards
for sensor_type in (
TEMPERATURE_SENSOR,
HUMIDITY_SENSOR,
PURITY_SENSOR,
AIR_QUALITY_SENSOR,
TEMPERATURE_RATING_SENSOR,
HUMIDITY_RATING_SENSOR,
PURITY_RATING_SENSOR,
)
)
for sensor in session.device_helper.wallthermostats:
entities.append(
TemperatureSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
entities.extend(
SHCSensor(
device,
SENSOR_DESCRIPTIONS[sensor_type],
session.information.unique_id,
config_entry.entry_id,
)
)
entities.append(
HumiditySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
for sensor in session.device_helper.twinguards:
entities.append(
TemperatureSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
HumiditySensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
PuritySensor(
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 (
for device in (
session.device_helper.smart_plugs + session.device_helper.light_switches_bsm
):
entities.append(
PowerSensor(
device=sensor,
parent_id=session.information.unique_id,
entry_id=config_entry.entry_id,
)
)
entities.append(
EnergySensor(
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.append(
PowerSensor(
device=sensor,
parent_id=session.information.unique_id,
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,
entities.extend(
SHCSensor(
device,
SENSOR_DESCRIPTIONS[sensor_type],
session.information.unique_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)
class TemperatureSensor(SHCEntity, SensorEntity):
"""Representation of an SHC temperature reporting sensor."""
class SHCSensor(SHCEntity, SensorEntity):
"""Representation of a SHC sensor."""
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
entity_description: SHCSensorEntityDescription
def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None:
"""Initialize an SHC temperature reporting sensor."""
def __init__(
self,
device: SHCDevice,
entity_description: SHCSensorEntityDescription,
parent_id: str,
entry_id: str,
) -> None:
"""Initialize sensor."""
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
def native_value(self):
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self._device.temperature
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"
return self.entity_description.value_fn(self._device)
@property
def native_value(self):
"""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):
def extra_state_attributes(self) -> dict[str, Any] | None:
"""Return the state attributes."""
return {
"rating_description": self._device.description,
}
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,
}
if self.entity_description.attributes_fn is not None:
return self.entity_description.attributes_fn(self._device)
return None