1 """Support for HomematicIP Cloud sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable
8 from homematicip.aio.device
import (
9 AsyncBrandSwitchMeasuring,
10 AsyncEnergySensorsInterface,
11 AsyncFloorTerminalBlock6,
12 AsyncFloorTerminalBlock10,
13 AsyncFloorTerminalBlock12,
14 AsyncFullFlushSwitchMeasuring,
15 AsyncHeatingThermostat,
16 AsyncHeatingThermostatCompact,
17 AsyncHeatingThermostatEvo,
18 AsyncHomeControlAccessPoint,
20 AsyncMotionDetectorIndoor,
21 AsyncMotionDetectorOutdoor,
22 AsyncMotionDetectorPushButton,
24 AsyncPlugableSwitchMeasuring,
25 AsyncPresenceDetectorIndoor,
26 AsyncRoomControlDeviceAnalog,
27 AsyncTemperatureDifferenceSensor2,
28 AsyncTemperatureHumiditySensorDisplay,
29 AsyncTemperatureHumiditySensorOutdoor,
30 AsyncTemperatureHumiditySensorWithoutDisplay,
32 AsyncWeatherSensorPlus,
33 AsyncWeatherSensorPro,
34 AsyncWiredFloorTerminalBlock12,
36 from homematicip.base.enums
import FunctionalChannelType, ValveState
37 from homematicip.base.functionalChannels
import (
38 FloorTerminalBlockMechanicChannel,
53 UnitOfPrecipitationDepth,
63 from .const
import DOMAIN
64 from .entity
import HomematicipGenericEntity
65 from .hap
import HomematicipHAP
66 from .helpers
import get_channels_from_device
68 ATTR_CURRENT_ILLUMINATION =
"current_illumination"
69 ATTR_LOWEST_ILLUMINATION =
"lowest_illumination"
70 ATTR_HIGHEST_ILLUMINATION =
"highest_illumination"
71 ATTR_LEFT_COUNTER =
"left_counter"
72 ATTR_RIGHT_COUNTER =
"right_counter"
73 ATTR_TEMPERATURE_OFFSET =
"temperature_offset"
74 ATTR_WIND_DIRECTION =
"wind_direction"
75 ATTR_WIND_DIRECTION_VARIATION =
"wind_direction_variation_in_degree"
76 ATTR_ESI_TYPE =
"type"
77 ESI_TYPE_UNKNOWN =
"UNKNOWN"
78 ESI_CONNECTED_SENSOR_TYPE_IEC =
"ES_IEC"
79 ESI_CONNECTED_SENSOR_TYPE_GAS =
"ES_GAS"
80 ESI_CONNECTED_SENSOR_TYPE_LED =
"ES_LED"
82 ESI_TYPE_CURRENT_POWER_CONSUMPTION =
"CurrentPowerConsumption"
83 ESI_TYPE_ENERGY_COUNTER_USAGE_HIGH_TARIFF =
"ENERGY_COUNTER_USAGE_HIGH_TARIFF"
84 ESI_TYPE_ENERGY_COUNTER_USAGE_LOW_TARIFF =
"ENERGY_COUNTER_USAGE_LOW_TARIFF"
85 ESI_TYPE_ENERGY_COUNTER_INPUT_SINGLE_TARIFF =
"ENERGY_COUNTER_INPUT_SINGLE_TARIFF"
86 ESI_TYPE_CURRENT_GAS_FLOW =
"CurrentGasFlow"
87 ESI_TYPE_CURRENT_GAS_VOLUME =
"GasVolume"
89 ILLUMINATION_DEVICE_ATTRIBUTES = {
90 "currentIllumination": ATTR_CURRENT_ILLUMINATION,
91 "lowestIllumination": ATTR_LOWEST_ILLUMINATION,
92 "highestIllumination": ATTR_HIGHEST_ILLUMINATION,
98 config_entry: ConfigEntry,
99 async_add_entities: AddEntitiesCallback,
101 """Set up the HomematicIP Cloud sensors from a config entry."""
102 hap = hass.data[DOMAIN][config_entry.unique_id]
103 entities: list[HomematicipGenericEntity] = []
104 for device
in hap.home.devices:
105 if isinstance(device, AsyncHomeControlAccessPoint):
110 AsyncHeatingThermostat,
111 AsyncHeatingThermostatCompact,
112 AsyncHeatingThermostatEvo,
120 AsyncTemperatureHumiditySensorDisplay,
121 AsyncTemperatureHumiditySensorWithoutDisplay,
122 AsyncTemperatureHumiditySensorOutdoor,
124 AsyncWeatherSensorPlus,
125 AsyncWeatherSensorPro,
130 elif isinstance(device, (AsyncRoomControlDeviceAnalog,)):
136 AsyncMotionDetectorIndoor,
137 AsyncMotionDetectorOutdoor,
138 AsyncMotionDetectorPushButton,
139 AsyncPresenceDetectorIndoor,
141 AsyncWeatherSensorPlus,
142 AsyncWeatherSensorPro,
149 AsyncPlugableSwitchMeasuring,
150 AsyncBrandSwitchMeasuring,
151 AsyncFullFlushSwitchMeasuring,
157 device, (AsyncWeatherSensor, AsyncWeatherSensorPlus, AsyncWeatherSensorPro)
160 if isinstance(device, (AsyncWeatherSensorPlus, AsyncWeatherSensorPro)):
162 if isinstance(device, AsyncPassageDetector):
164 if isinstance(device, AsyncTemperatureDifferenceSensor2):
168 if isinstance(device, AsyncEnergySensorsInterface):
170 device, FunctionalChannelType.ENERGY_SENSORS_INTERFACE_CHANNEL
172 if ch.connectedEnergySensorType == ESI_CONNECTED_SENSOR_TYPE_IEC:
173 if ch.currentPowerConsumption
is not None:
175 if ch.energyCounterOneType != ESI_TYPE_UNKNOWN:
177 if ch.energyCounterTwoType != ESI_TYPE_UNKNOWN:
179 if ch.energyCounterThreeType != ESI_TYPE_UNKNOWN:
184 if ch.connectedEnergySensorType == ESI_CONNECTED_SENSOR_TYPE_GAS:
185 if ch.currentGasFlow
is not None:
187 if ch.gasVolume
is not None:
190 if ch.connectedEnergySensorType == ESI_CONNECTED_SENSOR_TYPE_LED:
191 if ch.currentPowerConsumption
is not None:
197 AsyncFloorTerminalBlock6,
198 AsyncFloorTerminalBlock10,
199 AsyncFloorTerminalBlock12,
200 AsyncWiredFloorTerminalBlock12,
205 hap, device, channel=channel.index
207 for channel
in device.functionalChannels
208 if isinstance(channel, FloorTerminalBlockMechanicChannel)
209 and getattr(channel,
"valvePosition",
None)
is not None
216 HomematicipGenericEntity, SensorEntity
218 """Representation of the HomematicIP floor terminal block."""
220 _attr_native_unit_of_measurement = PERCENTAGE
221 _attr_state_class = SensorStateClass.MEASUREMENT
224 self, hap: HomematicipHAP, device, channel, is_multi_channel=
True
226 """Initialize floor terminal block 12 device."""
231 is_multi_channel=is_multi_channel,
232 post=
"Valve Position",
237 """Return the icon."""
242 for channel
in self.
_device_device.functionalChannels
243 if channel.index == self.
_channel_channel
245 if channel.valveState != ValveState.ADAPTION_DONE:
247 return "mdi:heating-coil"
251 """Return the state of the floor terminal block mechanical channel valve position."""
254 for channel
in self.
_device_device.functionalChannels
255 if channel.index == self.
_channel_channel
257 if channel.valveState != ValveState.ADAPTION_DONE:
259 return round(channel.valvePosition * 100)
263 """Representation of then HomeMaticIP access point."""
265 _attr_icon =
"mdi:access-point-network"
266 _attr_native_unit_of_measurement = PERCENTAGE
267 _attr_state_class = SensorStateClass.MEASUREMENT
269 def __init__(self, hap: HomematicipHAP, device) ->
None:
270 """Initialize access point status entity."""
271 super().
__init__(hap, device, post=
"Duty Cycle")
275 """Return the state of the access point."""
276 return self.
_device_device.dutyCycleLevel
280 """Representation of the HomematicIP heating thermostat."""
282 _attr_native_unit_of_measurement = PERCENTAGE
284 def __init__(self, hap: HomematicipHAP, device) ->
None:
285 """Initialize heating thermostat device."""
286 super().
__init__(hap, device, post=
"Heating")
290 """Return the icon."""
293 if self.
_device_device.valveState != ValveState.ADAPTION_DONE:
295 return "mdi:radiator"
299 """Return the state of the radiator valve."""
300 if self.
_device_device.valveState != ValveState.ADAPTION_DONE:
302 return round(self.
_device_device.valvePosition * 100)
306 """Representation of the HomematicIP humidity sensor."""
308 _attr_device_class = SensorDeviceClass.HUMIDITY
309 _attr_native_unit_of_measurement = PERCENTAGE
310 _attr_state_class = SensorStateClass.MEASUREMENT
312 def __init__(self, hap: HomematicipHAP, device) ->
None:
313 """Initialize the thermometer device."""
314 super().
__init__(hap, device, post=
"Humidity")
318 """Return the state."""
319 return self.
_device_device.humidity
323 """Representation of the HomematicIP thermometer."""
325 _attr_device_class = SensorDeviceClass.TEMPERATURE
326 _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
327 _attr_state_class = SensorStateClass.MEASUREMENT
329 def __init__(self, hap: HomematicipHAP, device) ->
None:
330 """Initialize the thermometer device."""
331 super().
__init__(hap, device, post=
"Temperature")
335 """Return the state."""
336 if hasattr(self.
_device_device,
"valveActualTemperature"):
337 return self.
_device_device.valveActualTemperature
339 return self.
_device_device.actualTemperature
343 """Return the state attributes of the windspeed sensor."""
344 state_attr = super().extra_state_attributes
346 temperature_offset = getattr(self.
_device_device,
"temperatureOffset",
None)
347 if temperature_offset:
348 state_attr[ATTR_TEMPERATURE_OFFSET] = temperature_offset
354 """Representation of the HomematicIP Illuminance sensor."""
356 _attr_device_class = SensorDeviceClass.ILLUMINANCE
357 _attr_native_unit_of_measurement = LIGHT_LUX
358 _attr_state_class = SensorStateClass.MEASUREMENT
360 def __init__(self, hap: HomematicipHAP, device) ->
None:
361 """Initialize the device."""
362 super().
__init__(hap, device, post=
"Illuminance")
366 """Return the state."""
367 if hasattr(self.
_device_device,
"averageIllumination"):
368 return self.
_device_device.averageIllumination
370 return self.
_device_device.illumination
374 """Return the state attributes of the wind speed sensor."""
375 state_attr = super().extra_state_attributes
377 for attr, attr_key
in ILLUMINATION_DEVICE_ATTRIBUTES.items():
378 if attr_value := getattr(self.
_device_device, attr,
None):
379 state_attr[attr_key] = attr_value
385 """Representation of the HomematicIP power measuring sensor."""
387 _attr_device_class = SensorDeviceClass.POWER
388 _attr_native_unit_of_measurement = UnitOfPower.WATT
389 _attr_state_class = SensorStateClass.MEASUREMENT
391 def __init__(self, hap: HomematicipHAP, device) ->
None:
392 """Initialize the device."""
393 super().
__init__(hap, device, post=
"Power")
397 """Return the power consumption value."""
398 return self.
_device_device.currentPowerConsumption
402 """Representation of the HomematicIP energy measuring sensor."""
404 _attr_device_class = SensorDeviceClass.ENERGY
405 _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
406 _attr_state_class = SensorStateClass.TOTAL_INCREASING
408 def __init__(self, hap: HomematicipHAP, device) ->
None:
409 """Initialize the device."""
410 super().
__init__(hap, device, post=
"Energy")
414 """Return the energy counter value."""
415 return self.
_device_device.energyCounter
419 """Representation of the HomematicIP wind speed sensor."""
421 _attr_device_class = SensorDeviceClass.WIND_SPEED
422 _attr_native_unit_of_measurement = UnitOfSpeed.KILOMETERS_PER_HOUR
423 _attr_state_class = SensorStateClass.MEASUREMENT
425 def __init__(self, hap: HomematicipHAP, device) ->
None:
426 """Initialize the windspeed sensor."""
427 super().
__init__(hap, device, post=
"Windspeed")
431 """Return the wind speed value."""
432 return self.
_device_device.windSpeed
436 """Return the state attributes of the wind speed sensor."""
437 state_attr = super().extra_state_attributes
439 wind_direction = getattr(self.
_device_device,
"windDirection",
None)
440 if wind_direction
is not None:
443 wind_direction_variation = getattr(self.
_device_device,
"windDirectionVariation",
None)
444 if wind_direction_variation:
445 state_attr[ATTR_WIND_DIRECTION_VARIATION] = wind_direction_variation
451 """Representation of the HomematicIP rain counter of a day sensor."""
453 _attr_device_class = SensorDeviceClass.PRECIPITATION
454 _attr_native_unit_of_measurement = UnitOfPrecipitationDepth.MILLIMETERS
455 _attr_state_class = SensorStateClass.MEASUREMENT
457 def __init__(self, hap: HomematicipHAP, device) ->
None:
458 """Initialize the device."""
459 super().
__init__(hap, device, post=
"Today Rain")
463 """Return the today's rain value."""
464 return round(self.
_device_device.todayRainCounter, 2)
468 """Representation of the HomematicIP device HmIP-STE2-PCB."""
470 _attr_device_class = SensorDeviceClass.TEMPERATURE
471 _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
472 _attr_state_class = SensorStateClass.MEASUREMENT
474 def __init__(self, hap: HomematicipHAP, device) ->
None:
475 """Initialize the device."""
476 super().
__init__(hap, device, post=
"Channel 1 Temperature")
480 """Return the state."""
481 return self.
_device_device.temperatureExternalOne
485 """Representation of the HomematicIP device HmIP-STE2-PCB."""
487 _attr_device_class = SensorDeviceClass.TEMPERATURE
488 _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
489 _attr_state_class = SensorStateClass.MEASUREMENT
491 def __init__(self, hap: HomematicipHAP, device) ->
None:
492 """Initialize the device."""
493 super().
__init__(hap, device, post=
"Channel 2 Temperature")
497 """Return the state."""
498 return self.
_device_device.temperatureExternalTwo
502 """Representation of the HomematicIP device HmIP-STE2-PCB."""
504 _attr_device_class = SensorDeviceClass.TEMPERATURE
505 _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
506 _attr_state_class = SensorStateClass.MEASUREMENT
508 def __init__(self, hap: HomematicipHAP, device) ->
None:
509 """Initialize the device."""
510 super().
__init__(hap, device, post=
"Delta Temperature")
514 """Return the state."""
515 return self.
_device_device.temperatureExternalDelta
519 """EntityDescription for HmIP-ESI Sensors."""
524 device: HomematicipGenericEntity,
526 value_fn: Callable[[FunctionalChannel], StateType],
527 type_fn: Callable[[FunctionalChannel], str],
529 """Initialize Sensor Entity."""
535 is_multi_channel=
False,
543 """Return the state attributes of the esi sensor."""
544 state_attr = super().extra_state_attributes
551 """Return the state of the sensor."""
556 """Representation of the Hmip-ESI IEC currentPowerConsumption sensor."""
558 _attr_device_class = SensorDeviceClass.POWER
559 _attr_native_unit_of_measurement = UnitOfPower.WATT
560 _attr_state_class = SensorStateClass.MEASUREMENT
562 def __init__(self, hap: HomematicipHAP, device) ->
None:
563 """Initialize the device."""
567 key=
"CurrentPowerConsumption",
568 value_fn=
lambda channel: channel.currentPowerConsumption,
569 type_fn=
lambda channel:
"CurrentPowerConsumption",
574 """Representation of the Hmip-ESI IEC energyCounterOne sensor."""
576 _attr_device_class = SensorDeviceClass.ENERGY
577 _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
578 _attr_state_class = SensorStateClass.TOTAL_INCREASING
580 def __init__(self, hap: HomematicipHAP, device) ->
None:
581 """Initialize the device."""
585 key=ESI_TYPE_ENERGY_COUNTER_USAGE_HIGH_TARIFF,
586 value_fn=
lambda channel: channel.energyCounterOne,
587 type_fn=
lambda channel: channel.energyCounterOneType,
592 """Representation of the Hmip-ESI IEC energyCounterTwo sensor."""
594 _attr_device_class = SensorDeviceClass.ENERGY
595 _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
596 _attr_state_class = SensorStateClass.TOTAL_INCREASING
598 def __init__(self, hap: HomematicipHAP, device) ->
None:
599 """Initialize the device."""
603 key=ESI_TYPE_ENERGY_COUNTER_USAGE_LOW_TARIFF,
604 value_fn=
lambda channel: channel.energyCounterTwo,
605 type_fn=
lambda channel: channel.energyCounterTwoType,
610 """Representation of the Hmip-ESI IEC energyCounterThree sensor."""
612 _attr_device_class = SensorDeviceClass.ENERGY
613 _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
614 _attr_state_class = SensorStateClass.TOTAL_INCREASING
616 def __init__(self, hap: HomematicipHAP, device) ->
None:
617 """Initialize the device."""
621 key=ESI_TYPE_ENERGY_COUNTER_INPUT_SINGLE_TARIFF,
622 value_fn=
lambda channel: channel.energyCounterThree,
623 type_fn=
lambda channel: channel.energyCounterThreeType,
628 """Representation of the Hmip-ESI Gas currentGasFlow sensor."""
630 _attr_device_class = SensorDeviceClass.VOLUME_FLOW_RATE
631 _attr_native_unit_of_measurement = UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR
632 _attr_state_class = SensorStateClass.MEASUREMENT
634 def __init__(self, hap: HomematicipHAP, device) ->
None:
635 """Initialize the device."""
639 key=
"CurrentGasFlow",
640 value_fn=
lambda channel: channel.currentGasFlow,
641 type_fn=
lambda channel:
"CurrentGasFlow",
646 """Representation of the Hmip-ESI Gas gasVolume sensor."""
648 _attr_device_class = SensorDeviceClass.GAS
649 _attr_native_unit_of_measurement = UnitOfVolume.CUBIC_METERS
650 _attr_state_class = SensorStateClass.TOTAL_INCREASING
652 def __init__(self, hap: HomematicipHAP, device) ->
None:
653 """Initialize the device."""
658 value_fn=
lambda channel: channel.gasVolume,
659 type_fn=
lambda channel:
"GasVolume",
664 """Representation of the Hmip-ESI LED currentPowerConsumption sensor."""
666 _attr_device_class = SensorDeviceClass.POWER
667 _attr_native_unit_of_measurement = UnitOfPower.WATT
668 _attr_state_class = SensorStateClass.MEASUREMENT
670 def __init__(self, hap: HomematicipHAP, device) ->
None:
671 """Initialize the device."""
675 key=
"CurrentPowerConsumption",
676 value_fn=
lambda channel: channel.currentPowerConsumption,
677 type_fn=
lambda channel:
"CurrentPowerConsumption",
682 """Representation of the Hmip-ESI LED energyCounterOne sensor."""
684 _attr_device_class = SensorDeviceClass.ENERGY
685 _attr_native_unit_of_measurement = UnitOfEnergy.KILO_WATT_HOUR
686 _attr_state_class = SensorStateClass.TOTAL_INCREASING
688 def __init__(self, hap: HomematicipHAP, device) ->
None:
689 """Initialize the device."""
693 key=ESI_TYPE_ENERGY_COUNTER_USAGE_HIGH_TARIFF,
694 value_fn=
lambda channel: channel.energyCounterOne,
695 type_fn=
lambda channel: ESI_TYPE_ENERGY_COUNTER_USAGE_HIGH_TARIFF,
700 """Representation of the HomematicIP passage detector delta counter."""
704 """Return the passage detector delta counter value."""
705 return self.
_device_device.leftRightCounterDelta
709 """Return the state attributes of the delta counter."""
710 state_attr = super().extra_state_attributes
712 state_attr[ATTR_LEFT_COUNTER] = self.
_device_device.leftCounter
713 state_attr[ATTR_RIGHT_COUNTER] = self.
_device_device.rightCounter
719 """Convert wind direction degree to named direction."""
720 if 11.25 <= wind_direction_degree < 33.75:
722 if 33.75 <= wind_direction_degree < 56.25:
724 if 56.25 <= wind_direction_degree < 78.75:
726 if 78.75 <= wind_direction_degree < 101.25:
728 if 101.25 <= wind_direction_degree < 123.75:
730 if 123.75 <= wind_direction_degree < 146.25:
732 if 146.25 <= wind_direction_degree < 168.75:
734 if 168.75 <= wind_direction_degree < 191.25:
736 if 191.25 <= wind_direction_degree < 213.75:
738 if 213.75 <= wind_direction_degree < 236.25:
740 if 236.25 <= wind_direction_degree < 258.75:
742 if 258.75 <= wind_direction_degree < 281.25:
744 if 281.25 <= wind_direction_degree < 303.75:
746 if 303.75 <= wind_direction_degree < 326.25:
748 if 326.25 <= wind_direction_degree < 348.75:
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
str|None native_value(self)
dict[str, Any] extra_state_attributes(self)
None __init__(self, HomematicipHAP hap, HomematicipGenericEntity device, str key, Callable[[FunctionalChannel], StateType] value_fn, Callable[[FunctionalChannel], str] type_fn)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device, channel, is_multi_channel=True)
int|None native_value(self)
None __init__(self, HomematicipHAP hap, device)
int|None native_value(self)
None __init__(self, HomematicipHAP hap, device)
dict[str, Any] extra_state_attributes(self)
None __init__(self, HomematicipHAP hap, device)
dict[str, Any] extra_state_attributes(self)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
dict[str, Any] extra_state_attributes(self)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
dict[str, Any] extra_state_attributes(self)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
None __init__(self, HomematicipHAP hap, device)
def get_channels_from_device(Device device, FunctionalChannelType channel_type)
str _get_wind_direction(float wind_direction_degree)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)