core/homeassistant/components/comfoconnect/sensor.py

340 lines
11 KiB
Python

"""Platform to control a Zehnder ComfoAir Q350/450/600 ventilation unit."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from pycomfoconnect import (
SENSOR_BYPASS_STATE,
SENSOR_CURRENT_RMOT,
SENSOR_DAYS_TO_REPLACE_FILTER,
SENSOR_FAN_EXHAUST_DUTY,
SENSOR_FAN_EXHAUST_FLOW,
SENSOR_FAN_EXHAUST_SPEED,
SENSOR_FAN_SUPPLY_DUTY,
SENSOR_FAN_SUPPLY_FLOW,
SENSOR_FAN_SUPPLY_SPEED,
SENSOR_HUMIDITY_EXHAUST,
SENSOR_HUMIDITY_EXTRACT,
SENSOR_HUMIDITY_OUTDOOR,
SENSOR_HUMIDITY_SUPPLY,
SENSOR_POWER_CURRENT,
SENSOR_POWER_TOTAL,
SENSOR_PREHEATER_POWER_CURRENT,
SENSOR_PREHEATER_POWER_TOTAL,
SENSOR_TEMPERATURE_EXHAUST,
SENSOR_TEMPERATURE_EXTRACT,
SENSOR_TEMPERATURE_OUTDOOR,
SENSOR_TEMPERATURE_SUPPLY,
)
import voluptuous as vol
from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONF_RESOURCES,
PERCENTAGE,
REVOLUTIONS_PER_MINUTE,
UnitOfEnergy,
UnitOfPower,
UnitOfTemperature,
UnitOfTime,
UnitOfVolumeFlowRate,
)
from homeassistant.core import HomeAssistant
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN, SIGNAL_COMFOCONNECT_UPDATE_RECEIVED, ComfoConnectBridge
ATTR_AIR_FLOW_EXHAUST = "air_flow_exhaust"
ATTR_AIR_FLOW_SUPPLY = "air_flow_supply"
ATTR_BYPASS_STATE = "bypass_state"
ATTR_CURRENT_HUMIDITY = "current_humidity"
ATTR_CURRENT_RMOT = "current_rmot"
ATTR_CURRENT_TEMPERATURE = "current_temperature"
ATTR_DAYS_TO_REPLACE_FILTER = "days_to_replace_filter"
ATTR_EXHAUST_FAN_DUTY = "exhaust_fan_duty"
ATTR_EXHAUST_FAN_SPEED = "exhaust_fan_speed"
ATTR_EXHAUST_HUMIDITY = "exhaust_humidity"
ATTR_EXHAUST_TEMPERATURE = "exhaust_temperature"
ATTR_OUTSIDE_HUMIDITY = "outside_humidity"
ATTR_OUTSIDE_TEMPERATURE = "outside_temperature"
ATTR_POWER_CURRENT = "power_usage"
ATTR_POWER_TOTAL = "power_total"
ATTR_PREHEATER_POWER_CURRENT = "preheater_power_usage"
ATTR_PREHEATER_POWER_TOTAL = "preheater_power_total"
ATTR_SUPPLY_FAN_DUTY = "supply_fan_duty"
ATTR_SUPPLY_FAN_SPEED = "supply_fan_speed"
ATTR_SUPPLY_HUMIDITY = "supply_humidity"
ATTR_SUPPLY_TEMPERATURE = "supply_temperature"
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class ComfoconnectSensorEntityDescription(SensorEntityDescription):
"""Describes Comfoconnect sensor entity."""
sensor_id: int
multiplier: float = 1
SENSOR_TYPES = (
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Inside temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
sensor_id=SENSOR_TEMPERATURE_EXTRACT,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
name="Inside humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_EXTRACT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_RMOT,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Current RMOT",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
sensor_id=SENSOR_CURRENT_RMOT,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_OUTSIDE_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Outside temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
sensor_id=SENSOR_TEMPERATURE_OUTDOOR,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_OUTSIDE_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
name="Outside humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_OUTDOOR,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Supply temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
sensor_id=SENSOR_TEMPERATURE_SUPPLY,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
name="Supply humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_SUPPLY,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_FAN_SPEED,
state_class=SensorStateClass.MEASUREMENT,
name="Supply fan speed",
native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
icon="mdi:fan-plus",
sensor_id=SENSOR_FAN_SUPPLY_SPEED,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_FAN_DUTY,
state_class=SensorStateClass.MEASUREMENT,
name="Supply fan duty",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:fan-plus",
sensor_id=SENSOR_FAN_SUPPLY_DUTY,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_FAN_SPEED,
state_class=SensorStateClass.MEASUREMENT,
name="Exhaust fan speed",
native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
icon="mdi:fan-minus",
sensor_id=SENSOR_FAN_EXHAUST_SPEED,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_FAN_DUTY,
state_class=SensorStateClass.MEASUREMENT,
name="Exhaust fan duty",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:fan-minus",
sensor_id=SENSOR_FAN_EXHAUST_DUTY,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
name="Exhaust temperature",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
sensor_id=SENSOR_TEMPERATURE_EXHAUST,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
name="Exhaust humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_EXHAUST,
),
ComfoconnectSensorEntityDescription(
key=ATTR_AIR_FLOW_SUPPLY,
state_class=SensorStateClass.MEASUREMENT,
name="Supply airflow",
native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
icon="mdi:fan-plus",
sensor_id=SENSOR_FAN_SUPPLY_FLOW,
),
ComfoconnectSensorEntityDescription(
key=ATTR_AIR_FLOW_EXHAUST,
state_class=SensorStateClass.MEASUREMENT,
name="Exhaust airflow",
native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
icon="mdi:fan-minus",
sensor_id=SENSOR_FAN_EXHAUST_FLOW,
),
ComfoconnectSensorEntityDescription(
key=ATTR_BYPASS_STATE,
state_class=SensorStateClass.MEASUREMENT,
name="Bypass state",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:camera-iris",
sensor_id=SENSOR_BYPASS_STATE,
),
ComfoconnectSensorEntityDescription(
key=ATTR_DAYS_TO_REPLACE_FILTER,
name="Days to replace filter",
native_unit_of_measurement=UnitOfTime.DAYS,
icon="mdi:calendar",
sensor_id=SENSOR_DAYS_TO_REPLACE_FILTER,
),
ComfoconnectSensorEntityDescription(
key=ATTR_POWER_CURRENT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
name="Power usage",
native_unit_of_measurement=UnitOfPower.WATT,
sensor_id=SENSOR_POWER_CURRENT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_POWER_TOTAL,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
name="Energy total",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
sensor_id=SENSOR_POWER_TOTAL,
),
ComfoconnectSensorEntityDescription(
key=ATTR_PREHEATER_POWER_CURRENT,
device_class=SensorDeviceClass.POWER,
state_class=SensorStateClass.MEASUREMENT,
name="Preheater power usage",
native_unit_of_measurement=UnitOfPower.WATT,
sensor_id=SENSOR_PREHEATER_POWER_CURRENT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_PREHEATER_POWER_TOTAL,
device_class=SensorDeviceClass.ENERGY,
state_class=SensorStateClass.TOTAL_INCREASING,
name="Preheater energy total",
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
sensor_id=SENSOR_PREHEATER_POWER_TOTAL,
),
)
PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In([desc.key for desc in SENSOR_TYPES])]
)
}
)
def setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the ComfoConnect sensor platform."""
ccb = hass.data[DOMAIN]
sensors = [
ComfoConnectSensor(ccb=ccb, description=description)
for description in SENSOR_TYPES
if description.key in config[CONF_RESOURCES]
]
add_entities(sensors, True)
class ComfoConnectSensor(SensorEntity):
"""Representation of a ComfoConnect sensor."""
_attr_should_poll = False
entity_description: ComfoconnectSensorEntityDescription
def __init__(
self,
ccb: ComfoConnectBridge,
description: ComfoconnectSensorEntityDescription,
) -> None:
"""Initialize the ComfoConnect sensor."""
self._ccb = ccb
self.entity_description = description
self._attr_name = f"{ccb.name} {description.name}"
self._attr_unique_id = f"{ccb.unique_id}-{description.key}"
async def async_added_to_hass(self) -> None:
"""Register for sensor updates."""
_LOGGER.debug(
"Registering for sensor %s (%d)",
self.entity_description.key,
self.entity_description.sensor_id,
)
self.async_on_remove(
async_dispatcher_connect(
self.hass,
SIGNAL_COMFOCONNECT_UPDATE_RECEIVED.format(
self.entity_description.sensor_id
),
self._handle_update,
)
)
await self.hass.async_add_executor_job(
self._ccb.comfoconnect.register_sensor, self.entity_description.sensor_id
)
def _handle_update(self, value: float) -> None:
"""Handle update callbacks."""
_LOGGER.debug(
"Handle update for sensor %s (%d): %s",
self.entity_description.key,
self.entity_description.sensor_id,
value,
)
self._attr_native_value = round(value * self.entity_description.multiplier, 2)
self.schedule_update_ha_state()