1
mirror of https://github.com/home-assistant/core synced 2024-10-07 10:13:38 +02:00
ha-core/homeassistant/components/comfoconnect/sensor.py
Michaël Arnauts 5d3d6fa1cd
Add state_class and use SensorEntityDescription for comfoconnect (#54066)
* Add state_class=measurement and use SensorEntityDescriptions

* Use attributes from entity_description

* Improvements

* Adress remarks

* Revert changes to fan

* move method

* Fix tests

* Revert fan/__init__.py

* Revert key change

* Set default percentage in turn_on
2021-09-24 22:26:56 +02:00

340 lines
11 KiB
Python

"""Platform to control a Zehnder ComfoAir Q350/450/600 ventilation unit."""
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,
STATE_CLASS_MEASUREMENT,
STATE_CLASS_TOTAL_INCREASING,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import (
CONF_RESOURCES,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_POWER,
DEVICE_CLASS_TEMPERATURE,
ENERGY_KILO_WATT_HOUR,
PERCENTAGE,
POWER_WATT,
TEMP_CELSIUS,
TIME_DAYS,
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
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
class ComfoconnectRequiredKeysMixin:
"""Mixin for required keys."""
sensor_id: int
@dataclass
class ComfoconnectSensorEntityDescription(
SensorEntityDescription, ComfoconnectRequiredKeysMixin
):
"""Describes Comfoconnect sensor entity."""
multiplier: float = 1
SENSOR_TYPES = (
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_TEMPERATURE,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
name="Inside temperature",
native_unit_of_measurement=TEMP_CELSIUS,
sensor_id=SENSOR_TEMPERATURE_EXTRACT,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_HUMIDITY,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
name="Inside humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_EXTRACT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_CURRENT_RMOT,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
name="Current RMOT",
native_unit_of_measurement=TEMP_CELSIUS,
sensor_id=SENSOR_CURRENT_RMOT,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_OUTSIDE_TEMPERATURE,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
name="Outside temperature",
native_unit_of_measurement=TEMP_CELSIUS,
sensor_id=SENSOR_TEMPERATURE_OUTDOOR,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_OUTSIDE_HUMIDITY,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
name="Outside humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_OUTDOOR,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_TEMPERATURE,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
name="Supply temperature",
native_unit_of_measurement=TEMP_CELSIUS,
sensor_id=SENSOR_TEMPERATURE_SUPPLY,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_HUMIDITY,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
name="Supply humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_SUPPLY,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_FAN_SPEED,
state_class=STATE_CLASS_MEASUREMENT,
name="Supply fan speed",
native_unit_of_measurement="rpm",
icon="mdi:fan-plus",
sensor_id=SENSOR_FAN_SUPPLY_SPEED,
),
ComfoconnectSensorEntityDescription(
key=ATTR_SUPPLY_FAN_DUTY,
state_class=STATE_CLASS_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=STATE_CLASS_MEASUREMENT,
name="Exhaust fan speed",
native_unit_of_measurement="rpm",
icon="mdi:fan-minus",
sensor_id=SENSOR_FAN_EXHAUST_SPEED,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_FAN_DUTY,
state_class=STATE_CLASS_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=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
name="Exhaust temperature",
native_unit_of_measurement=TEMP_CELSIUS,
sensor_id=SENSOR_TEMPERATURE_EXHAUST,
multiplier=0.1,
),
ComfoconnectSensorEntityDescription(
key=ATTR_EXHAUST_HUMIDITY,
device_class=DEVICE_CLASS_HUMIDITY,
state_class=STATE_CLASS_MEASUREMENT,
name="Exhaust humidity",
native_unit_of_measurement=PERCENTAGE,
sensor_id=SENSOR_HUMIDITY_EXHAUST,
),
ComfoconnectSensorEntityDescription(
key=ATTR_AIR_FLOW_SUPPLY,
state_class=STATE_CLASS_MEASUREMENT,
name="Supply airflow",
native_unit_of_measurement=VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
icon="mdi:fan-plus",
sensor_id=SENSOR_FAN_SUPPLY_FLOW,
),
ComfoconnectSensorEntityDescription(
key=ATTR_AIR_FLOW_EXHAUST,
state_class=STATE_CLASS_MEASUREMENT,
name="Exhaust airflow",
native_unit_of_measurement=VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
icon="mdi:fan-minus",
sensor_id=SENSOR_FAN_EXHAUST_FLOW,
),
ComfoconnectSensorEntityDescription(
key=ATTR_BYPASS_STATE,
state_class=STATE_CLASS_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=TIME_DAYS,
icon="mdi:calendar",
sensor_id=SENSOR_DAYS_TO_REPLACE_FILTER,
),
ComfoconnectSensorEntityDescription(
key=ATTR_POWER_CURRENT,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
name="Power usage",
native_unit_of_measurement=POWER_WATT,
sensor_id=SENSOR_POWER_CURRENT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_POWER_TOTAL,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
name="Energy total",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
sensor_id=SENSOR_POWER_TOTAL,
),
ComfoconnectSensorEntityDescription(
key=ATTR_PREHEATER_POWER_CURRENT,
device_class=DEVICE_CLASS_POWER,
state_class=STATE_CLASS_MEASUREMENT,
name="Preheater power usage",
native_unit_of_measurement=POWER_WATT,
sensor_id=SENSOR_PREHEATER_POWER_CURRENT,
),
ComfoconnectSensorEntityDescription(
key=ATTR_PREHEATER_POWER_TOTAL,
device_class=DEVICE_CLASS_ENERGY,
state_class=STATE_CLASS_TOTAL_INCREASING,
name="Preheater energy total",
native_unit_of_measurement=ENERGY_KILO_WATT_HOUR,
sensor_id=SENSOR_PREHEATER_POWER_TOTAL,
),
)
PLATFORM_SCHEMA = 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, config, add_entities, discovery_info=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):
"""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()