Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Platform to control a Zehnder ComfoAir Q350/450/600 ventilation unit."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 import logging
7 
8 from pycomfoconnect import (
9  SENSOR_BYPASS_STATE,
10  SENSOR_CURRENT_RMOT,
11  SENSOR_DAYS_TO_REPLACE_FILTER,
12  SENSOR_FAN_EXHAUST_DUTY,
13  SENSOR_FAN_EXHAUST_FLOW,
14  SENSOR_FAN_EXHAUST_SPEED,
15  SENSOR_FAN_SUPPLY_DUTY,
16  SENSOR_FAN_SUPPLY_FLOW,
17  SENSOR_FAN_SUPPLY_SPEED,
18  SENSOR_HUMIDITY_EXHAUST,
19  SENSOR_HUMIDITY_EXTRACT,
20  SENSOR_HUMIDITY_OUTDOOR,
21  SENSOR_HUMIDITY_SUPPLY,
22  SENSOR_POWER_CURRENT,
23  SENSOR_POWER_TOTAL,
24  SENSOR_PREHEATER_POWER_CURRENT,
25  SENSOR_PREHEATER_POWER_TOTAL,
26  SENSOR_TEMPERATURE_EXHAUST,
27  SENSOR_TEMPERATURE_EXTRACT,
28  SENSOR_TEMPERATURE_OUTDOOR,
29  SENSOR_TEMPERATURE_SUPPLY,
30 )
31 import voluptuous as vol
32 
34  PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
35  SensorDeviceClass,
36  SensorEntity,
37  SensorEntityDescription,
38  SensorStateClass,
39 )
40 from homeassistant.const import (
41  CONF_RESOURCES,
42  PERCENTAGE,
43  REVOLUTIONS_PER_MINUTE,
44  UnitOfEnergy,
45  UnitOfPower,
46  UnitOfTemperature,
47  UnitOfTime,
48  UnitOfVolumeFlowRate,
49 )
50 from homeassistant.core import HomeAssistant
52 from homeassistant.helpers.dispatcher import async_dispatcher_connect
53 from homeassistant.helpers.entity_platform import AddEntitiesCallback
54 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
55 
56 from . import DOMAIN, SIGNAL_COMFOCONNECT_UPDATE_RECEIVED, ComfoConnectBridge
57 
58 ATTR_AIR_FLOW_EXHAUST = "air_flow_exhaust"
59 ATTR_AIR_FLOW_SUPPLY = "air_flow_supply"
60 ATTR_BYPASS_STATE = "bypass_state"
61 ATTR_CURRENT_HUMIDITY = "current_humidity"
62 ATTR_CURRENT_RMOT = "current_rmot"
63 ATTR_CURRENT_TEMPERATURE = "current_temperature"
64 ATTR_DAYS_TO_REPLACE_FILTER = "days_to_replace_filter"
65 ATTR_EXHAUST_FAN_DUTY = "exhaust_fan_duty"
66 ATTR_EXHAUST_FAN_SPEED = "exhaust_fan_speed"
67 ATTR_EXHAUST_HUMIDITY = "exhaust_humidity"
68 ATTR_EXHAUST_TEMPERATURE = "exhaust_temperature"
69 ATTR_OUTSIDE_HUMIDITY = "outside_humidity"
70 ATTR_OUTSIDE_TEMPERATURE = "outside_temperature"
71 ATTR_POWER_CURRENT = "power_usage"
72 ATTR_POWER_TOTAL = "power_total"
73 ATTR_PREHEATER_POWER_CURRENT = "preheater_power_usage"
74 ATTR_PREHEATER_POWER_TOTAL = "preheater_power_total"
75 ATTR_SUPPLY_FAN_DUTY = "supply_fan_duty"
76 ATTR_SUPPLY_FAN_SPEED = "supply_fan_speed"
77 ATTR_SUPPLY_HUMIDITY = "supply_humidity"
78 ATTR_SUPPLY_TEMPERATURE = "supply_temperature"
79 
80 _LOGGER = logging.getLogger(__name__)
81 
82 
83 @dataclass(frozen=True, kw_only=True)
85  """Describes Comfoconnect sensor entity."""
86 
87  sensor_id: int
88  multiplier: float = 1
89 
90 
91 SENSOR_TYPES = (
93  key=ATTR_CURRENT_TEMPERATURE,
94  device_class=SensorDeviceClass.TEMPERATURE,
95  state_class=SensorStateClass.MEASUREMENT,
96  name="Inside temperature",
97  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
98  sensor_id=SENSOR_TEMPERATURE_EXTRACT,
99  multiplier=0.1,
100  ),
102  key=ATTR_CURRENT_HUMIDITY,
103  device_class=SensorDeviceClass.HUMIDITY,
104  state_class=SensorStateClass.MEASUREMENT,
105  name="Inside humidity",
106  native_unit_of_measurement=PERCENTAGE,
107  sensor_id=SENSOR_HUMIDITY_EXTRACT,
108  ),
110  key=ATTR_CURRENT_RMOT,
111  device_class=SensorDeviceClass.TEMPERATURE,
112  state_class=SensorStateClass.MEASUREMENT,
113  name="Current RMOT",
114  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
115  sensor_id=SENSOR_CURRENT_RMOT,
116  multiplier=0.1,
117  ),
119  key=ATTR_OUTSIDE_TEMPERATURE,
120  device_class=SensorDeviceClass.TEMPERATURE,
121  state_class=SensorStateClass.MEASUREMENT,
122  name="Outside temperature",
123  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
124  sensor_id=SENSOR_TEMPERATURE_OUTDOOR,
125  multiplier=0.1,
126  ),
128  key=ATTR_OUTSIDE_HUMIDITY,
129  device_class=SensorDeviceClass.HUMIDITY,
130  state_class=SensorStateClass.MEASUREMENT,
131  name="Outside humidity",
132  native_unit_of_measurement=PERCENTAGE,
133  sensor_id=SENSOR_HUMIDITY_OUTDOOR,
134  ),
136  key=ATTR_SUPPLY_TEMPERATURE,
137  device_class=SensorDeviceClass.TEMPERATURE,
138  state_class=SensorStateClass.MEASUREMENT,
139  name="Supply temperature",
140  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
141  sensor_id=SENSOR_TEMPERATURE_SUPPLY,
142  multiplier=0.1,
143  ),
145  key=ATTR_SUPPLY_HUMIDITY,
146  device_class=SensorDeviceClass.HUMIDITY,
147  state_class=SensorStateClass.MEASUREMENT,
148  name="Supply humidity",
149  native_unit_of_measurement=PERCENTAGE,
150  sensor_id=SENSOR_HUMIDITY_SUPPLY,
151  ),
153  key=ATTR_SUPPLY_FAN_SPEED,
154  state_class=SensorStateClass.MEASUREMENT,
155  name="Supply fan speed",
156  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
157  icon="mdi:fan-plus",
158  sensor_id=SENSOR_FAN_SUPPLY_SPEED,
159  ),
161  key=ATTR_SUPPLY_FAN_DUTY,
162  state_class=SensorStateClass.MEASUREMENT,
163  name="Supply fan duty",
164  native_unit_of_measurement=PERCENTAGE,
165  icon="mdi:fan-plus",
166  sensor_id=SENSOR_FAN_SUPPLY_DUTY,
167  ),
169  key=ATTR_EXHAUST_FAN_SPEED,
170  state_class=SensorStateClass.MEASUREMENT,
171  name="Exhaust fan speed",
172  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
173  icon="mdi:fan-minus",
174  sensor_id=SENSOR_FAN_EXHAUST_SPEED,
175  ),
177  key=ATTR_EXHAUST_FAN_DUTY,
178  state_class=SensorStateClass.MEASUREMENT,
179  name="Exhaust fan duty",
180  native_unit_of_measurement=PERCENTAGE,
181  icon="mdi:fan-minus",
182  sensor_id=SENSOR_FAN_EXHAUST_DUTY,
183  ),
185  key=ATTR_EXHAUST_TEMPERATURE,
186  device_class=SensorDeviceClass.TEMPERATURE,
187  state_class=SensorStateClass.MEASUREMENT,
188  name="Exhaust temperature",
189  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
190  sensor_id=SENSOR_TEMPERATURE_EXHAUST,
191  multiplier=0.1,
192  ),
194  key=ATTR_EXHAUST_HUMIDITY,
195  device_class=SensorDeviceClass.HUMIDITY,
196  state_class=SensorStateClass.MEASUREMENT,
197  name="Exhaust humidity",
198  native_unit_of_measurement=PERCENTAGE,
199  sensor_id=SENSOR_HUMIDITY_EXHAUST,
200  ),
202  key=ATTR_AIR_FLOW_SUPPLY,
203  state_class=SensorStateClass.MEASUREMENT,
204  name="Supply airflow",
205  native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
206  icon="mdi:fan-plus",
207  sensor_id=SENSOR_FAN_SUPPLY_FLOW,
208  ),
210  key=ATTR_AIR_FLOW_EXHAUST,
211  state_class=SensorStateClass.MEASUREMENT,
212  name="Exhaust airflow",
213  native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
214  icon="mdi:fan-minus",
215  sensor_id=SENSOR_FAN_EXHAUST_FLOW,
216  ),
218  key=ATTR_BYPASS_STATE,
219  state_class=SensorStateClass.MEASUREMENT,
220  name="Bypass state",
221  native_unit_of_measurement=PERCENTAGE,
222  icon="mdi:camera-iris",
223  sensor_id=SENSOR_BYPASS_STATE,
224  ),
226  key=ATTR_DAYS_TO_REPLACE_FILTER,
227  name="Days to replace filter",
228  native_unit_of_measurement=UnitOfTime.DAYS,
229  icon="mdi:calendar",
230  sensor_id=SENSOR_DAYS_TO_REPLACE_FILTER,
231  ),
233  key=ATTR_POWER_CURRENT,
234  device_class=SensorDeviceClass.POWER,
235  state_class=SensorStateClass.MEASUREMENT,
236  name="Power usage",
237  native_unit_of_measurement=UnitOfPower.WATT,
238  sensor_id=SENSOR_POWER_CURRENT,
239  ),
241  key=ATTR_POWER_TOTAL,
242  device_class=SensorDeviceClass.ENERGY,
243  state_class=SensorStateClass.TOTAL_INCREASING,
244  name="Energy total",
245  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
246  sensor_id=SENSOR_POWER_TOTAL,
247  ),
249  key=ATTR_PREHEATER_POWER_CURRENT,
250  device_class=SensorDeviceClass.POWER,
251  state_class=SensorStateClass.MEASUREMENT,
252  name="Preheater power usage",
253  native_unit_of_measurement=UnitOfPower.WATT,
254  sensor_id=SENSOR_PREHEATER_POWER_CURRENT,
255  ),
257  key=ATTR_PREHEATER_POWER_TOTAL,
258  device_class=SensorDeviceClass.ENERGY,
259  state_class=SensorStateClass.TOTAL_INCREASING,
260  name="Preheater energy total",
261  native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
262  sensor_id=SENSOR_PREHEATER_POWER_TOTAL,
263  ),
264 )
265 
266 PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend(
267  {
268  vol.Optional(CONF_RESOURCES, default=[]): vol.All(
269  cv.ensure_list, [vol.In([desc.key for desc in SENSOR_TYPES])]
270  )
271  }
272 )
273 
274 
276  hass: HomeAssistant,
277  config: ConfigType,
278  add_entities: AddEntitiesCallback,
279  discovery_info: DiscoveryInfoType | None = None,
280 ) -> None:
281  """Set up the ComfoConnect sensor platform."""
282  ccb = hass.data[DOMAIN]
283 
284  sensors = [
285  ComfoConnectSensor(ccb=ccb, description=description)
286  for description in SENSOR_TYPES
287  if description.key in config[CONF_RESOURCES]
288  ]
289 
290  add_entities(sensors, True)
291 
292 
294  """Representation of a ComfoConnect sensor."""
295 
296  _attr_should_poll = False
297  entity_description: ComfoconnectSensorEntityDescription
298 
299  def __init__(
300  self,
301  ccb: ComfoConnectBridge,
302  description: ComfoconnectSensorEntityDescription,
303  ) -> None:
304  """Initialize the ComfoConnect sensor."""
305  self._ccb_ccb = ccb
306  self.entity_descriptionentity_description = description
307  self._attr_name_attr_name = f"{ccb.name} {description.name}"
308  self._attr_unique_id_attr_unique_id = f"{ccb.unique_id}-{description.key}"
309 
310  async def async_added_to_hass(self) -> None:
311  """Register for sensor updates."""
312  _LOGGER.debug(
313  "Registering for sensor %s (%d)",
314  self.entity_descriptionentity_description.key,
315  self.entity_descriptionentity_description.sensor_id,
316  )
317  self.async_on_removeasync_on_remove(
319  self.hasshass,
320  SIGNAL_COMFOCONNECT_UPDATE_RECEIVED.format(
321  self.entity_descriptionentity_description.sensor_id
322  ),
323  self._handle_update_handle_update,
324  )
325  )
326  await self.hasshass.async_add_executor_job(
327  self._ccb_ccb.comfoconnect.register_sensor, self.entity_descriptionentity_description.sensor_id
328  )
329 
330  def _handle_update(self, value: float) -> None:
331  """Handle update callbacks."""
332  _LOGGER.debug(
333  "Handle update for sensor %s (%d): %s",
334  self.entity_descriptionentity_description.key,
335  self.entity_descriptionentity_description.sensor_id,
336  value,
337  )
338  self._attr_native_value_attr_native_value = round(value * self.entity_descriptionentity_description.multiplier, 2)
339  self.schedule_update_ha_stateschedule_update_ha_state()
None __init__(self, ComfoConnectBridge ccb, ComfoconnectSensorEntityDescription description)
Definition: sensor.py:303
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
None schedule_update_ha_state(self, bool force_refresh=False)
Definition: entity.py:1244
None setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: sensor.py:280
def add_entities(account, async_add_entities, tracked)
Definition: sensor.py:40
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103