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
This commit is contained in:
Michaël Arnauts 2021-09-24 22:26:56 +02:00 committed by GitHub
parent 0ea5f25594
commit 5d3d6fa1cd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 255 additions and 254 deletions

View file

@ -90,7 +90,6 @@ class ComfoConnectBridge:
def __init__(self, hass, bridge, name, token, friendly_name, pin): def __init__(self, hass, bridge, name, token, friendly_name, pin):
"""Initialize the ComfoConnect bridge.""" """Initialize the ComfoConnect bridge."""
self.data = {}
self.name = name self.name = name
self.hass = hass self.hass = hass
self.unique_id = bridge.uuid.hex() self.unique_id = bridge.uuid.hex()

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import logging import logging
import math import math
from typing import Any
from pycomfoconnect import ( from pycomfoconnect import (
CMD_FAN_MODE_AWAY, CMD_FAN_MODE_AWAY,
@ -38,18 +39,19 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the ComfoConnect fan platform.""" """Set up the ComfoConnect fan platform."""
ccb = hass.data[DOMAIN] ccb = hass.data[DOMAIN]
add_entities([ComfoConnectFan(ccb.name, ccb)], True) add_entities([ComfoConnectFan(ccb)], True)
class ComfoConnectFan(FanEntity): class ComfoConnectFan(FanEntity):
"""Representation of the ComfoConnect fan platform.""" """Representation of the ComfoConnect fan platform."""
def __init__(self, name, ccb: ComfoConnectBridge) -> None: current_speed = None
def __init__(self, ccb: ComfoConnectBridge) -> None:
"""Initialize the ComfoConnect fan.""" """Initialize the ComfoConnect fan."""
self._ccb = ccb self._ccb = ccb
self._name = name
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Register for sensor updates.""" """Register for sensor updates."""
_LOGGER.debug("Registering for fan speed") _LOGGER.debug("Registering for fan speed")
self.async_on_remove( self.async_on_remove(
@ -68,7 +70,7 @@ class ComfoConnectFan(FanEntity):
_LOGGER.debug( _LOGGER.debug(
"Handle update for fan speed (%d): %s", SENSOR_FAN_SPEED_MODE, value "Handle update for fan speed (%d): %s", SENSOR_FAN_SPEED_MODE, value
) )
self._ccb.data[SENSOR_FAN_SPEED_MODE] = value self.current_speed = value
self.schedule_update_ha_state() self.schedule_update_ha_state()
@property @property
@ -84,7 +86,7 @@ class ComfoConnectFan(FanEntity):
@property @property
def name(self): def name(self):
"""Return the name of the fan.""" """Return the name of the fan."""
return self._name return self._ccb.name
@property @property
def icon(self): def icon(self):
@ -99,10 +101,9 @@ class ComfoConnectFan(FanEntity):
@property @property
def percentage(self) -> int | None: def percentage(self) -> int | None:
"""Return the current speed percentage.""" """Return the current speed percentage."""
speed = self._ccb.data.get(SENSOR_FAN_SPEED_MODE) if self.current_speed is None:
if speed is None:
return None return None
return ranged_value_to_percentage(SPEED_RANGE, speed) return ranged_value_to_percentage(SPEED_RANGE, self.current_speed)
@property @property
def speed_count(self) -> int: def speed_count(self) -> int:
@ -110,28 +111,30 @@ class ComfoConnectFan(FanEntity):
return int_states_in_range(SPEED_RANGE) return int_states_in_range(SPEED_RANGE)
def turn_on( def turn_on(
self, speed: str = None, percentage=None, preset_mode=None, **kwargs self,
speed: str | None = None,
percentage: int | None = None,
preset_mode: str | None = None,
**kwargs,
) -> None: ) -> None:
"""Turn on the fan.""" """Turn on the fan."""
self.set_percentage(percentage) if percentage is None:
self.set_percentage(1) # Set fan speed to low
else:
self.set_percentage(percentage)
def turn_off(self, **kwargs) -> None: def turn_off(self, **kwargs: Any) -> None:
"""Turn off the fan (to away).""" """Turn off the fan (to away)."""
self.set_percentage(0) self.set_percentage(0)
def set_percentage(self, percentage: int): def set_percentage(self, percentage: int) -> None:
"""Set fan speed percentage.""" """Set fan speed percentage."""
_LOGGER.debug("Changing fan speed percentage to %s", percentage) _LOGGER.debug("Changing fan speed percentage to %s", percentage)
if percentage is None: if percentage == 0:
cmd = CMD_FAN_MODE_LOW
elif percentage == 0:
cmd = CMD_FAN_MODE_AWAY cmd = CMD_FAN_MODE_AWAY
else: else:
speed = math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage)) speed = math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage))
cmd = CMD_MAPPING[speed] cmd = CMD_MAPPING[speed]
self._ccb.comfoconnect.cmd_rmi_request(cmd) self._ccb.comfoconnect.cmd_rmi_request(cmd)
# Update current mode
self.schedule_update_ha_state()

View file

@ -1,4 +1,5 @@
"""Platform to control a Zehnder ComfoAir Q350/450/600 ventilation unit.""" """Platform to control a Zehnder ComfoAir Q350/450/600 ventilation unit."""
from dataclasses import dataclass
import logging import logging
from pycomfoconnect import ( from pycomfoconnect import (
@ -26,11 +27,14 @@ from pycomfoconnect import (
) )
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
STATE_CLASS_MEASUREMENT,
STATE_CLASS_TOTAL_INCREASING,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import ( from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_ICON,
ATTR_ID,
CONF_RESOURCES, CONF_RESOURCES,
DEVICE_CLASS_ENERGY, DEVICE_CLASS_ENERGY,
DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_HUMIDITY,
@ -72,187 +76,216 @@ ATTR_SUPPLY_TEMPERATURE = "supply_temperature"
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
ATTR_LABEL = "label"
ATTR_MULTIPLIER = "multiplier"
ATTR_UNIT = "unit"
SENSOR_TYPES = { @dataclass
ATTR_CURRENT_TEMPERATURE: { class ComfoconnectRequiredKeysMixin:
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, """Mixin for required keys."""
ATTR_LABEL: "Inside Temperature",
ATTR_UNIT: TEMP_CELSIUS, sensor_id: int
ATTR_ICON: None,
ATTR_ID: SENSOR_TEMPERATURE_EXTRACT,
ATTR_MULTIPLIER: 0.1, @dataclass
}, class ComfoconnectSensorEntityDescription(
ATTR_CURRENT_HUMIDITY: { SensorEntityDescription, ComfoconnectRequiredKeysMixin
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, ):
ATTR_LABEL: "Inside Humidity", """Describes Comfoconnect sensor entity."""
ATTR_UNIT: PERCENTAGE,
ATTR_ICON: None, multiplier: float = 1
ATTR_ID: SENSOR_HUMIDITY_EXTRACT,
},
ATTR_CURRENT_RMOT: { SENSOR_TYPES = (
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, ComfoconnectSensorEntityDescription(
ATTR_LABEL: "Current RMOT", key=ATTR_CURRENT_TEMPERATURE,
ATTR_UNIT: TEMP_CELSIUS, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_ICON: None, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ID: SENSOR_CURRENT_RMOT, name="Inside temperature",
ATTR_MULTIPLIER: 0.1, native_unit_of_measurement=TEMP_CELSIUS,
}, sensor_id=SENSOR_TEMPERATURE_EXTRACT,
ATTR_OUTSIDE_TEMPERATURE: { multiplier=0.1,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, ),
ATTR_LABEL: "Outside Temperature", ComfoconnectSensorEntityDescription(
ATTR_UNIT: TEMP_CELSIUS, key=ATTR_CURRENT_HUMIDITY,
ATTR_ICON: None, device_class=DEVICE_CLASS_HUMIDITY,
ATTR_ID: SENSOR_TEMPERATURE_OUTDOOR, state_class=STATE_CLASS_MEASUREMENT,
ATTR_MULTIPLIER: 0.1, name="Inside humidity",
}, native_unit_of_measurement=PERCENTAGE,
ATTR_OUTSIDE_HUMIDITY: { sensor_id=SENSOR_HUMIDITY_EXTRACT,
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, ),
ATTR_LABEL: "Outside Humidity", ComfoconnectSensorEntityDescription(
ATTR_UNIT: PERCENTAGE, key=ATTR_CURRENT_RMOT,
ATTR_ICON: None, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_ID: SENSOR_HUMIDITY_OUTDOOR, state_class=STATE_CLASS_MEASUREMENT,
}, name="Current RMOT",
ATTR_SUPPLY_TEMPERATURE: { native_unit_of_measurement=TEMP_CELSIUS,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, sensor_id=SENSOR_CURRENT_RMOT,
ATTR_LABEL: "Supply Temperature", multiplier=0.1,
ATTR_UNIT: TEMP_CELSIUS, ),
ATTR_ICON: None, ComfoconnectSensorEntityDescription(
ATTR_ID: SENSOR_TEMPERATURE_SUPPLY, key=ATTR_OUTSIDE_TEMPERATURE,
ATTR_MULTIPLIER: 0.1, device_class=DEVICE_CLASS_TEMPERATURE,
}, state_class=STATE_CLASS_MEASUREMENT,
ATTR_SUPPLY_HUMIDITY: { name="Outside temperature",
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, native_unit_of_measurement=TEMP_CELSIUS,
ATTR_LABEL: "Supply Humidity", sensor_id=SENSOR_TEMPERATURE_OUTDOOR,
ATTR_UNIT: PERCENTAGE, multiplier=0.1,
ATTR_ICON: None, ),
ATTR_ID: SENSOR_HUMIDITY_SUPPLY, ComfoconnectSensorEntityDescription(
}, key=ATTR_OUTSIDE_HUMIDITY,
ATTR_SUPPLY_FAN_SPEED: { device_class=DEVICE_CLASS_HUMIDITY,
ATTR_DEVICE_CLASS: None, state_class=STATE_CLASS_MEASUREMENT,
ATTR_LABEL: "Supply Fan Speed", name="Outside humidity",
ATTR_UNIT: "rpm", native_unit_of_measurement=PERCENTAGE,
ATTR_ICON: "mdi:fan", sensor_id=SENSOR_HUMIDITY_OUTDOOR,
ATTR_ID: SENSOR_FAN_SUPPLY_SPEED, ),
}, ComfoconnectSensorEntityDescription(
ATTR_SUPPLY_FAN_DUTY: { key=ATTR_SUPPLY_TEMPERATURE,
ATTR_DEVICE_CLASS: None, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_LABEL: "Supply Fan Duty", state_class=STATE_CLASS_MEASUREMENT,
ATTR_UNIT: PERCENTAGE, name="Supply temperature",
ATTR_ICON: "mdi:fan", native_unit_of_measurement=TEMP_CELSIUS,
ATTR_ID: SENSOR_FAN_SUPPLY_DUTY, sensor_id=SENSOR_TEMPERATURE_SUPPLY,
}, multiplier=0.1,
ATTR_EXHAUST_FAN_SPEED: { ),
ATTR_DEVICE_CLASS: None, ComfoconnectSensorEntityDescription(
ATTR_LABEL: "Exhaust Fan Speed", key=ATTR_SUPPLY_HUMIDITY,
ATTR_UNIT: "rpm", device_class=DEVICE_CLASS_HUMIDITY,
ATTR_ICON: "mdi:fan", state_class=STATE_CLASS_MEASUREMENT,
ATTR_ID: SENSOR_FAN_EXHAUST_SPEED, name="Supply humidity",
}, native_unit_of_measurement=PERCENTAGE,
ATTR_EXHAUST_FAN_DUTY: { sensor_id=SENSOR_HUMIDITY_SUPPLY,
ATTR_DEVICE_CLASS: None, ),
ATTR_LABEL: "Exhaust Fan Duty", ComfoconnectSensorEntityDescription(
ATTR_UNIT: PERCENTAGE, key=ATTR_SUPPLY_FAN_SPEED,
ATTR_ICON: "mdi:fan", state_class=STATE_CLASS_MEASUREMENT,
ATTR_ID: SENSOR_FAN_EXHAUST_DUTY, name="Supply fan speed",
}, native_unit_of_measurement="rpm",
ATTR_EXHAUST_TEMPERATURE: { icon="mdi:fan-plus",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, sensor_id=SENSOR_FAN_SUPPLY_SPEED,
ATTR_LABEL: "Exhaust Temperature", ),
ATTR_UNIT: TEMP_CELSIUS, ComfoconnectSensorEntityDescription(
ATTR_ICON: None, key=ATTR_SUPPLY_FAN_DUTY,
ATTR_ID: SENSOR_TEMPERATURE_EXHAUST, state_class=STATE_CLASS_MEASUREMENT,
ATTR_MULTIPLIER: 0.1, name="Supply fan duty",
}, native_unit_of_measurement=PERCENTAGE,
ATTR_EXHAUST_HUMIDITY: { icon="mdi:fan-plus",
ATTR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, sensor_id=SENSOR_FAN_SUPPLY_DUTY,
ATTR_LABEL: "Exhaust Humidity", ),
ATTR_UNIT: PERCENTAGE, ComfoconnectSensorEntityDescription(
ATTR_ICON: None, key=ATTR_EXHAUST_FAN_SPEED,
ATTR_ID: SENSOR_HUMIDITY_EXHAUST, state_class=STATE_CLASS_MEASUREMENT,
}, name="Exhaust fan speed",
ATTR_AIR_FLOW_SUPPLY: { native_unit_of_measurement="rpm",
ATTR_DEVICE_CLASS: None, icon="mdi:fan-minus",
ATTR_LABEL: "Supply airflow", sensor_id=SENSOR_FAN_EXHAUST_SPEED,
ATTR_UNIT: VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR, ),
ATTR_ICON: "mdi:fan", ComfoconnectSensorEntityDescription(
ATTR_ID: SENSOR_FAN_SUPPLY_FLOW, key=ATTR_EXHAUST_FAN_DUTY,
}, state_class=STATE_CLASS_MEASUREMENT,
ATTR_AIR_FLOW_EXHAUST: { name="Exhaust fan duty",
ATTR_DEVICE_CLASS: None, native_unit_of_measurement=PERCENTAGE,
ATTR_LABEL: "Exhaust airflow", icon="mdi:fan-minus",
ATTR_UNIT: VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR, sensor_id=SENSOR_FAN_EXHAUST_DUTY,
ATTR_ICON: "mdi:fan", ),
ATTR_ID: SENSOR_FAN_EXHAUST_FLOW, ComfoconnectSensorEntityDescription(
}, key=ATTR_EXHAUST_TEMPERATURE,
ATTR_BYPASS_STATE: { device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_DEVICE_CLASS: None, state_class=STATE_CLASS_MEASUREMENT,
ATTR_LABEL: "Bypass State", name="Exhaust temperature",
ATTR_UNIT: PERCENTAGE, native_unit_of_measurement=TEMP_CELSIUS,
ATTR_ICON: "mdi:camera-iris", sensor_id=SENSOR_TEMPERATURE_EXHAUST,
ATTR_ID: SENSOR_BYPASS_STATE, multiplier=0.1,
}, ),
ATTR_DAYS_TO_REPLACE_FILTER: { ComfoconnectSensorEntityDescription(
ATTR_DEVICE_CLASS: None, key=ATTR_EXHAUST_HUMIDITY,
ATTR_LABEL: "Days to replace filter", device_class=DEVICE_CLASS_HUMIDITY,
ATTR_UNIT: TIME_DAYS, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ICON: "mdi:calendar", name="Exhaust humidity",
ATTR_ID: SENSOR_DAYS_TO_REPLACE_FILTER, native_unit_of_measurement=PERCENTAGE,
}, sensor_id=SENSOR_HUMIDITY_EXHAUST,
ATTR_POWER_CURRENT: { ),
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER, ComfoconnectSensorEntityDescription(
ATTR_LABEL: "Power usage", key=ATTR_AIR_FLOW_SUPPLY,
ATTR_UNIT: POWER_WATT, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ICON: None, name="Supply airflow",
ATTR_ID: SENSOR_POWER_CURRENT, native_unit_of_measurement=VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
}, icon="mdi:fan-plus",
ATTR_POWER_TOTAL: { sensor_id=SENSOR_FAN_SUPPLY_FLOW,
ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY, ),
ATTR_LABEL: "Power total", ComfoconnectSensorEntityDescription(
ATTR_UNIT: ENERGY_KILO_WATT_HOUR, key=ATTR_AIR_FLOW_EXHAUST,
ATTR_ICON: None, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ID: SENSOR_POWER_TOTAL, name="Exhaust airflow",
}, native_unit_of_measurement=VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR,
ATTR_PREHEATER_POWER_CURRENT: { icon="mdi:fan-minus",
ATTR_DEVICE_CLASS: DEVICE_CLASS_POWER, sensor_id=SENSOR_FAN_EXHAUST_FLOW,
ATTR_LABEL: "Preheater power usage", ),
ATTR_UNIT: POWER_WATT, ComfoconnectSensorEntityDescription(
ATTR_ICON: None, key=ATTR_BYPASS_STATE,
ATTR_ID: SENSOR_PREHEATER_POWER_CURRENT, state_class=STATE_CLASS_MEASUREMENT,
}, name="Bypass state",
ATTR_PREHEATER_POWER_TOTAL: { native_unit_of_measurement=PERCENTAGE,
ATTR_DEVICE_CLASS: DEVICE_CLASS_ENERGY, icon="mdi:camera-iris",
ATTR_LABEL: "Preheater power total", sensor_id=SENSOR_BYPASS_STATE,
ATTR_UNIT: ENERGY_KILO_WATT_HOUR, ),
ATTR_ICON: None, ComfoconnectSensorEntityDescription(
ATTR_ID: SENSOR_PREHEATER_POWER_TOTAL, 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( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
vol.Optional(CONF_RESOURCES, default=[]): vol.All( vol.Optional(CONF_RESOURCES, default=[]): vol.All(
cv.ensure_list, [vol.In(SENSOR_TYPES)] cv.ensure_list, [vol.In([desc.key for desc in SENSOR_TYPES])]
) )
} }
) )
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the ComfoConnect fan platform.""" """Set up the ComfoConnect sensor platform."""
ccb = hass.data[DOMAIN] ccb = hass.data[DOMAIN]
sensors = [] sensors = [
for resource in config[CONF_RESOURCES]: ComfoConnectSensor(ccb=ccb, description=description)
sensors.append( for description in SENSOR_TYPES
ComfoConnectSensor( if description.key in config[CONF_RESOURCES]
name=f"{ccb.name} {SENSOR_TYPES[resource][ATTR_LABEL]}", ]
ccb=ccb,
sensor_type=resource,
)
)
add_entities(sensors, True) add_entities(sensors, True)
@ -260,76 +293,47 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
class ComfoConnectSensor(SensorEntity): class ComfoConnectSensor(SensorEntity):
"""Representation of a ComfoConnect sensor.""" """Representation of a ComfoConnect sensor."""
def __init__(self, name, ccb: ComfoConnectBridge, sensor_type) -> None: _attr_should_poll = False
entity_description: ComfoconnectSensorEntityDescription
def __init__(
self,
ccb: ComfoConnectBridge,
description: ComfoconnectSensorEntityDescription,
) -> None:
"""Initialize the ComfoConnect sensor.""" """Initialize the ComfoConnect sensor."""
self._ccb = ccb self._ccb = ccb
self._sensor_type = sensor_type self.entity_description = description
self._sensor_id = SENSOR_TYPES[self._sensor_type][ATTR_ID] self._attr_name = f"{ccb.name} {description.name}"
self._name = name self._attr_unique_id = f"{ccb.unique_id}-{description.key}"
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Register for sensor updates.""" """Register for sensor updates."""
_LOGGER.debug( _LOGGER.debug(
"Registering for sensor %s (%d)", self._sensor_type, self._sensor_id "Registering for sensor %s (%d)",
self.entity_description.key,
self.entity_description.sensor_id,
) )
self.async_on_remove( self.async_on_remove(
async_dispatcher_connect( async_dispatcher_connect(
self.hass, self.hass,
SIGNAL_COMFOCONNECT_UPDATE_RECEIVED.format(self._sensor_id), SIGNAL_COMFOCONNECT_UPDATE_RECEIVED.format(
self.entity_description.sensor_id
),
self._handle_update, self._handle_update,
) )
) )
await self.hass.async_add_executor_job( await self.hass.async_add_executor_job(
self._ccb.comfoconnect.register_sensor, self._sensor_id self._ccb.comfoconnect.register_sensor, self.entity_description.sensor_id
) )
def _handle_update(self, value): def _handle_update(self, value):
"""Handle update callbacks.""" """Handle update callbacks."""
_LOGGER.debug( _LOGGER.debug(
"Handle update for sensor %s (%d): %s", "Handle update for sensor %s (%d): %s",
self._sensor_type, self.entity_description.key,
self._sensor_id, self.entity_description.sensor_id,
value, value,
) )
self._ccb.data[self._sensor_id] = round( self._attr_native_value = round(value * self.entity_description.multiplier, 2)
value * SENSOR_TYPES[self._sensor_type].get(ATTR_MULTIPLIER, 1), 2
)
self.schedule_update_ha_state() self.schedule_update_ha_state()
@property
def native_value(self):
"""Return the state of the entity."""
try:
return self._ccb.data[self._sensor_id]
except KeyError:
return None
@property
def should_poll(self) -> bool:
"""Do not poll."""
return False
@property
def unique_id(self):
"""Return a unique_id for this entity."""
return f"{self._ccb.unique_id}-{self._sensor_type}"
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def icon(self):
"""Return the icon to use in the frontend."""
return SENSOR_TYPES[self._sensor_type][ATTR_ICON]
@property
def native_unit_of_measurement(self):
"""Return the unit of measurement of this entity."""
return SENSOR_TYPES[self._sensor_type][ATTR_UNIT]
@property
def device_class(self):
"""Return the device_class."""
return SENSOR_TYPES[self._sensor_type][ATTR_DEVICE_CLASS]

View file

@ -54,40 +54,35 @@ async def test_sensors(hass, setup_sensor):
"""Test the sensors.""" """Test the sensors."""
state = hass.states.get("sensor.comfoairq_inside_humidity") state = hass.states.get("sensor.comfoairq_inside_humidity")
assert state is not None assert state is not None
assert state.name == "ComfoAirQ Inside humidity"
assert state.name == "ComfoAirQ Inside Humidity"
assert state.attributes.get("unit_of_measurement") == "%" assert state.attributes.get("unit_of_measurement") == "%"
assert state.attributes.get("device_class") == "humidity" assert state.attributes.get("device_class") == "humidity"
assert state.attributes.get("icon") is None assert state.attributes.get("icon") is None
state = hass.states.get("sensor.comfoairq_inside_temperature") state = hass.states.get("sensor.comfoairq_inside_temperature")
assert state is not None assert state is not None
assert state.name == "ComfoAirQ Inside temperature"
assert state.name == "ComfoAirQ Inside Temperature"
assert state.attributes.get("unit_of_measurement") == "°C" assert state.attributes.get("unit_of_measurement") == "°C"
assert state.attributes.get("device_class") == "temperature" assert state.attributes.get("device_class") == "temperature"
assert state.attributes.get("icon") is None assert state.attributes.get("icon") is None
state = hass.states.get("sensor.comfoairq_supply_fan_duty") state = hass.states.get("sensor.comfoairq_supply_fan_duty")
assert state is not None assert state is not None
assert state.name == "ComfoAirQ Supply fan duty"
assert state.name == "ComfoAirQ Supply Fan Duty"
assert state.attributes.get("unit_of_measurement") == "%" assert state.attributes.get("unit_of_measurement") == "%"
assert state.attributes.get("device_class") is None assert state.attributes.get("device_class") is None
assert state.attributes.get("icon") == "mdi:fan" assert state.attributes.get("icon") == "mdi:fan-plus"
state = hass.states.get("sensor.comfoairq_power_usage") state = hass.states.get("sensor.comfoairq_power_usage")
assert state is not None assert state is not None
assert state.name == "ComfoAirQ Power usage" assert state.name == "ComfoAirQ Power usage"
assert state.attributes.get("unit_of_measurement") == "W" assert state.attributes.get("unit_of_measurement") == "W"
assert state.attributes.get("device_class") == "power" assert state.attributes.get("device_class") == "power"
assert state.attributes.get("icon") is None assert state.attributes.get("icon") is None
state = hass.states.get("sensor.comfoairq_preheater_power_total") state = hass.states.get("sensor.comfoairq_preheater_energy_total")
assert state is not None assert state is not None
assert state.name == "ComfoAirQ Preheater energy total"
assert state.name == "ComfoAirQ Preheater power total"
assert state.attributes.get("unit_of_measurement") == "kWh" assert state.attributes.get("unit_of_measurement") == "kWh"
assert state.attributes.get("device_class") == "energy" assert state.attributes.get("device_class") == "energy"
assert state.attributes.get("icon") is None assert state.attributes.get("icon") is None