mirror of
https://github.com/home-assistant/core.git
synced 2025-12-20 02:48:57 +00:00
379 lines
12 KiB
Python
379 lines
12 KiB
Python
"""Support for Qbus sensor."""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from qbusmqttapi.discovery import QbusMqttOutput
|
|
from qbusmqttapi.state import (
|
|
GaugeStateProperty,
|
|
QbusMqttGaugeState,
|
|
QbusMqttHumidityState,
|
|
QbusMqttThermoState,
|
|
QbusMqttVentilationState,
|
|
QbusMqttWeatherState,
|
|
)
|
|
|
|
from homeassistant.components.sensor import (
|
|
SensorDeviceClass,
|
|
SensorEntity,
|
|
SensorEntityDescription,
|
|
SensorStateClass,
|
|
)
|
|
from homeassistant.const import (
|
|
CONCENTRATION_PARTS_PER_MILLION,
|
|
LIGHT_LUX,
|
|
PERCENTAGE,
|
|
UnitOfElectricCurrent,
|
|
UnitOfElectricPotential,
|
|
UnitOfEnergy,
|
|
UnitOfLength,
|
|
UnitOfPower,
|
|
UnitOfPressure,
|
|
UnitOfSoundPressure,
|
|
UnitOfSpeed,
|
|
UnitOfTemperature,
|
|
UnitOfVolume,
|
|
UnitOfVolumeFlowRate,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
|
|
from .coordinator import QbusConfigEntry
|
|
from .entity import QbusEntity, create_new_entities, determine_new_outputs
|
|
|
|
PARALLEL_UPDATES = 0
|
|
|
|
|
|
@dataclass(frozen=True, kw_only=True)
|
|
class QbusWeatherDescription(SensorEntityDescription):
|
|
"""Description for Qbus weather entities."""
|
|
|
|
property: str
|
|
|
|
|
|
_WEATHER_DESCRIPTIONS = (
|
|
QbusWeatherDescription(
|
|
key="daylight",
|
|
property="dayLight",
|
|
translation_key="daylight",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="light",
|
|
property="light",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="light_east",
|
|
property="lightEast",
|
|
translation_key="light_east",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="light_south",
|
|
property="lightSouth",
|
|
translation_key="light_south",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="light_west",
|
|
property="lightWest",
|
|
translation_key="light_west",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="temperature",
|
|
property="temperature",
|
|
device_class=SensorDeviceClass.TEMPERATURE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
|
),
|
|
QbusWeatherDescription(
|
|
key="wind",
|
|
property="wind",
|
|
device_class=SensorDeviceClass.WIND_SPEED,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
|
|
),
|
|
)
|
|
|
|
_GAUGE_VARIANT_DESCRIPTIONS = {
|
|
"AIRPRESSURE": SensorEntityDescription(
|
|
key="airpressure",
|
|
device_class=SensorDeviceClass.PRESSURE,
|
|
native_unit_of_measurement=UnitOfPressure.MBAR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"AIRQUALITY": SensorEntityDescription(
|
|
key="airquality",
|
|
device_class=SensorDeviceClass.CO2,
|
|
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"CURRENT": SensorEntityDescription(
|
|
key="current",
|
|
device_class=SensorDeviceClass.CURRENT,
|
|
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"ENERGY": SensorEntityDescription(
|
|
key="energy",
|
|
device_class=SensorDeviceClass.ENERGY,
|
|
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
|
state_class=SensorStateClass.TOTAL,
|
|
),
|
|
"GAS": SensorEntityDescription(
|
|
key="gas",
|
|
device_class=SensorDeviceClass.VOLUME_FLOW_RATE,
|
|
native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"GASFLOW": SensorEntityDescription(
|
|
key="gasflow",
|
|
device_class=SensorDeviceClass.VOLUME_FLOW_RATE,
|
|
native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"HUMIDITY": SensorEntityDescription(
|
|
key="humidity",
|
|
device_class=SensorDeviceClass.HUMIDITY,
|
|
native_unit_of_measurement=PERCENTAGE,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"LIGHT": SensorEntityDescription(
|
|
key="light",
|
|
device_class=SensorDeviceClass.ILLUMINANCE,
|
|
native_unit_of_measurement=LIGHT_LUX,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"LOUDNESS": SensorEntityDescription(
|
|
key="loudness",
|
|
device_class=SensorDeviceClass.SOUND_PRESSURE,
|
|
native_unit_of_measurement=UnitOfSoundPressure.DECIBEL,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"POWER": SensorEntityDescription(
|
|
key="power",
|
|
device_class=SensorDeviceClass.POWER,
|
|
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"PRESSURE": SensorEntityDescription(
|
|
key="pressure",
|
|
device_class=SensorDeviceClass.PRESSURE,
|
|
native_unit_of_measurement=UnitOfPressure.KPA,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"TEMPERATURE": SensorEntityDescription(
|
|
key="temperature",
|
|
device_class=SensorDeviceClass.TEMPERATURE,
|
|
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"VOLTAGE": SensorEntityDescription(
|
|
key="voltage",
|
|
device_class=SensorDeviceClass.VOLTAGE,
|
|
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"VOLUME": SensorEntityDescription(
|
|
key="volume",
|
|
device_class=SensorDeviceClass.VOLUME_STORAGE,
|
|
native_unit_of_measurement=UnitOfVolume.LITERS,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"WATER": SensorEntityDescription(
|
|
key="water",
|
|
device_class=SensorDeviceClass.WATER,
|
|
native_unit_of_measurement=UnitOfVolume.LITERS,
|
|
state_class=SensorStateClass.TOTAL,
|
|
),
|
|
"WATERFLOW": SensorEntityDescription(
|
|
key="waterflow",
|
|
device_class=SensorDeviceClass.VOLUME_FLOW_RATE,
|
|
native_unit_of_measurement=UnitOfVolumeFlowRate.LITERS_PER_HOUR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"WATERLEVEL": SensorEntityDescription(
|
|
key="waterlevel",
|
|
device_class=SensorDeviceClass.DISTANCE,
|
|
native_unit_of_measurement=UnitOfLength.METERS,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"WATERPRESSURE": SensorEntityDescription(
|
|
key="waterpressure",
|
|
device_class=SensorDeviceClass.PRESSURE,
|
|
native_unit_of_measurement=UnitOfPressure.MBAR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
"WIND": SensorEntityDescription(
|
|
key="wind",
|
|
device_class=SensorDeviceClass.WIND_SPEED,
|
|
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
|
|
state_class=SensorStateClass.MEASUREMENT,
|
|
),
|
|
}
|
|
|
|
|
|
def _is_gauge_with_variant(output: QbusMqttOutput) -> bool:
|
|
return (
|
|
output.type == "gauge"
|
|
and isinstance(output.variant, str)
|
|
and _GAUGE_VARIANT_DESCRIPTIONS.get(output.variant.upper()) is not None
|
|
)
|
|
|
|
|
|
def _is_ventilation_with_co2(output: QbusMqttOutput) -> bool:
|
|
return output.type == "ventilation" and output.properties.get("co2") is not None
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: QbusConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Set up sensor entities."""
|
|
|
|
coordinator = entry.runtime_data
|
|
added_outputs: list[QbusMqttOutput] = []
|
|
|
|
def _create_weather_entities() -> list[QbusEntity]:
|
|
new_outputs = determine_new_outputs(
|
|
coordinator, added_outputs, lambda output: output.type == "weatherstation"
|
|
)
|
|
|
|
return [
|
|
QbusWeatherSensor(output, description)
|
|
for output in new_outputs
|
|
for description in _WEATHER_DESCRIPTIONS
|
|
]
|
|
|
|
def _check_outputs() -> None:
|
|
entities: list[QbusEntity] = [
|
|
*create_new_entities(
|
|
coordinator,
|
|
added_outputs,
|
|
_is_gauge_with_variant,
|
|
QbusGaugeVariantSensor,
|
|
),
|
|
*create_new_entities(
|
|
coordinator,
|
|
added_outputs,
|
|
lambda output: output.type == "humidity",
|
|
QbusHumiditySensor,
|
|
),
|
|
*create_new_entities(
|
|
coordinator,
|
|
added_outputs,
|
|
lambda output: output.type == "thermo",
|
|
QbusThermoSensor,
|
|
),
|
|
*create_new_entities(
|
|
coordinator,
|
|
added_outputs,
|
|
_is_ventilation_with_co2,
|
|
QbusVentilationSensor,
|
|
),
|
|
*_create_weather_entities(),
|
|
]
|
|
|
|
async_add_entities(entities)
|
|
|
|
_check_outputs()
|
|
entry.async_on_unload(coordinator.async_add_listener(_check_outputs))
|
|
|
|
|
|
class QbusGaugeVariantSensor(QbusEntity, SensorEntity):
|
|
"""Representation of a Qbus sensor entity for gauges with variant."""
|
|
|
|
_state_cls = QbusMqttGaugeState
|
|
|
|
_attr_name = None
|
|
_attr_suggested_display_precision = 2
|
|
|
|
def __init__(self, mqtt_output: QbusMqttOutput) -> None:
|
|
"""Initialize sensor entity."""
|
|
|
|
super().__init__(mqtt_output)
|
|
|
|
variant = str(mqtt_output.variant)
|
|
self.entity_description = _GAUGE_VARIANT_DESCRIPTIONS[variant.upper()]
|
|
|
|
async def _handle_state_received(self, state: QbusMqttGaugeState) -> None:
|
|
self._attr_native_value = state.read_value(GaugeStateProperty.CURRENT_VALUE)
|
|
|
|
|
|
class QbusHumiditySensor(QbusEntity, SensorEntity):
|
|
"""Representation of a Qbus sensor entity for humidity modules."""
|
|
|
|
_state_cls = QbusMqttHumidityState
|
|
|
|
_attr_device_class = SensorDeviceClass.HUMIDITY
|
|
_attr_name = None
|
|
_attr_native_unit_of_measurement = PERCENTAGE
|
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
|
|
|
async def _handle_state_received(self, state: QbusMqttHumidityState) -> None:
|
|
self._attr_native_value = state.read_value()
|
|
|
|
|
|
class QbusThermoSensor(QbusEntity, SensorEntity):
|
|
"""Representation of a Qbus sensor entity for thermostats."""
|
|
|
|
_state_cls = QbusMqttThermoState
|
|
|
|
_attr_device_class = SensorDeviceClass.TEMPERATURE
|
|
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
|
|
|
async def _handle_state_received(self, state: QbusMqttThermoState) -> None:
|
|
self._attr_native_value = state.read_current_temperature()
|
|
|
|
|
|
class QbusVentilationSensor(QbusEntity, SensorEntity):
|
|
"""Representation of a Qbus sensor entity for ventilations."""
|
|
|
|
_state_cls = QbusMqttVentilationState
|
|
|
|
_attr_device_class = SensorDeviceClass.CO2
|
|
_attr_name = None
|
|
_attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION
|
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
|
_attr_suggested_display_precision = 0
|
|
|
|
async def _handle_state_received(self, state: QbusMqttVentilationState) -> None:
|
|
self._attr_native_value = state.read_co2()
|
|
|
|
|
|
class QbusWeatherSensor(QbusEntity, SensorEntity):
|
|
"""Representation of a Qbus weather sensor."""
|
|
|
|
_state_cls = QbusMqttWeatherState
|
|
|
|
entity_description: QbusWeatherDescription
|
|
|
|
def __init__(
|
|
self, mqtt_output: QbusMqttOutput, description: QbusWeatherDescription
|
|
) -> None:
|
|
"""Initialize sensor entity."""
|
|
|
|
super().__init__(mqtt_output, id_suffix=description.key)
|
|
|
|
self.entity_description = description
|
|
|
|
if description.key == "temperature":
|
|
self._attr_name = None
|
|
|
|
async def _handle_state_received(self, state: QbusMqttWeatherState) -> None:
|
|
if value := state.read_property(self.entity_description.property, None):
|
|
self.native_value = value
|