2021-12-23 18:34:35 +00:00
""" Support for Overkiz sensors. """
from __future__ import annotations
2021-12-27 17:26:55 +00:00
from collections . abc import Callable
from dataclasses import dataclass
2021-12-31 17:35:15 +00:00
from typing import cast
2021-12-27 17:26:55 +00:00
2021-12-23 18:34:35 +00:00
from pyoverkiz . enums import OverkizAttribute , OverkizState , UIWidget
2022-01-13 01:23:20 +00:00
from pyoverkiz . types import StateType as OverkizStateType
2021-12-23 18:34:35 +00:00
from homeassistant . components . sensor import (
SensorDeviceClass ,
SensorEntity ,
2021-12-27 17:26:55 +00:00
SensorEntityDescription ,
2021-12-23 18:34:35 +00:00
SensorStateClass ,
)
from homeassistant . config_entries import ConfigEntry
from homeassistant . const import (
CONCENTRATION_PARTS_PER_MILLION ,
ENERGY_WATT_HOUR ,
LIGHT_LUX ,
PERCENTAGE ,
POWER_WATT ,
SIGNAL_STRENGTH_DECIBELS ,
TEMP_CELSIUS ,
TIME_SECONDS ,
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR ,
VOLUME_LITERS ,
)
from homeassistant . core import HomeAssistant
from homeassistant . helpers . entity import DeviceInfo , EntityCategory
from homeassistant . helpers . entity_platform import AddEntitiesCallback
2021-12-30 14:22:35 +00:00
from homeassistant . helpers . typing import StateType
2021-12-23 18:34:35 +00:00
2021-12-23 23:28:01 +00:00
from . import HomeAssistantOverkizData
2022-01-17 20:47:42 +00:00
from . const import DOMAIN , IGNORED_OVERKIZ_DEVICES , OVERKIZ_STATE_TO_TRANSLATION
2021-12-23 18:34:35 +00:00
from . coordinator import OverkizDataUpdateCoordinator
2022-01-17 20:47:42 +00:00
from . entity import OverkizDescriptiveEntity , OverkizDeviceClass , OverkizEntity
2021-12-27 17:26:55 +00:00
@dataclass
class OverkizSensorDescription ( SensorEntityDescription ) :
""" Class to describe an Overkiz sensor. """
2022-01-08 09:53:15 +00:00
native_value : Callable [ [ OverkizStateType ] , StateType ] | None = None
2021-12-27 17:26:55 +00:00
2021-12-23 18:34:35 +00:00
SENSOR_DESCRIPTIONS : list [ OverkizSensorDescription ] = [
OverkizSensorDescription (
key = OverkizState . CORE_BATTERY_LEVEL ,
name = " Battery Level " ,
native_unit_of_measurement = PERCENTAGE ,
device_class = SensorDeviceClass . BATTERY ,
state_class = SensorStateClass . MEASUREMENT ,
entity_category = EntityCategory . DIAGNOSTIC ,
2022-01-26 16:31:17 +00:00
native_value = lambda value : int ( float ( str ( value ) . strip ( " % " ) ) ) ,
2021-12-23 18:34:35 +00:00
) ,
OverkizSensorDescription (
key = OverkizState . CORE_BATTERY ,
name = " Battery " ,
entity_category = EntityCategory . DIAGNOSTIC ,
2022-01-17 20:47:42 +00:00
icon = " mdi:battery " ,
device_class = OverkizDeviceClass . BATTERY ,
2021-12-23 18:34:35 +00:00
) ,
OverkizSensorDescription (
key = OverkizState . CORE_RSSI_LEVEL ,
name = " RSSI Level " ,
native_unit_of_measurement = SIGNAL_STRENGTH_DECIBELS ,
device_class = SensorDeviceClass . SIGNAL_STRENGTH ,
state_class = SensorStateClass . MEASUREMENT ,
2022-01-08 09:53:15 +00:00
native_value = lambda value : round ( cast ( float , value ) ) ,
2021-12-23 18:34:35 +00:00
entity_category = EntityCategory . DIAGNOSTIC ,
2021-12-30 14:22:35 +00:00
entity_registry_enabled_default = False ,
2021-12-23 18:34:35 +00:00
) ,
OverkizSensorDescription (
key = OverkizState . CORE_EXPECTED_NUMBER_OF_SHOWER ,
name = " Expected Number Of Shower " ,
icon = " mdi:shower-head " ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_NUMBER_OF_SHOWER_REMAINING ,
name = " Number of Shower Remaining " ,
icon = " mdi:shower-head " ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# V40 is measured in litres (L) and shows the amount of warm (mixed) water with a temperature of 40 C, which can be drained from a switched off electric water heater.
OverkizSensorDescription (
key = OverkizState . CORE_V40_WATER_VOLUME_ESTIMATION ,
name = " Water Volume Estimation at 40 °C " ,
icon = " mdi:water " ,
native_unit_of_measurement = VOLUME_LITERS ,
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_WATER_CONSUMPTION ,
name = " Water Consumption " ,
icon = " mdi:water " ,
native_unit_of_measurement = VOLUME_LITERS ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . IO_OUTLET_ENGINE ,
name = " Outlet Engine " ,
icon = " mdi:fan-chevron-down " ,
native_unit_of_measurement = VOLUME_LITERS ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . IO_INLET_ENGINE ,
name = " Inlet Engine " ,
icon = " mdi:fan-chevron-up " ,
native_unit_of_measurement = VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . HLRRWIFI_ROOM_TEMPERATURE ,
name = " Room Temperature " ,
device_class = SensorDeviceClass . TEMPERATURE ,
state_class = SensorStateClass . MEASUREMENT ,
native_unit_of_measurement = TEMP_CELSIUS ,
) ,
OverkizSensorDescription (
key = OverkizState . IO_MIDDLE_WATER_TEMPERATURE ,
name = " Middle Water Temperature " ,
device_class = SensorDeviceClass . TEMPERATURE ,
state_class = SensorStateClass . MEASUREMENT ,
native_unit_of_measurement = TEMP_CELSIUS ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_FOSSIL_ENERGY_CONSUMPTION ,
name = " Fossil Energy Consumption " ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_GAS_CONSUMPTION ,
name = " Gas Consumption " ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_THERMAL_ENERGY_CONSUMPTION ,
name = " Thermal Energy Consumption " ,
) ,
# LightSensor/LuminanceSensor
OverkizSensorDescription (
key = OverkizState . CORE_LUMINANCE ,
name = " Luminance " ,
device_class = SensorDeviceClass . ILLUMINANCE ,
native_unit_of_measurement = LIGHT_LUX , # core:MeasuredValueType = core:LuminanceInLux
state_class = SensorStateClass . MEASUREMENT ,
) ,
# ElectricitySensor/CumulativeElectricPowerConsumptionSensor
OverkizSensorDescription (
key = OverkizState . CORE_ELECTRIC_ENERGY_CONSUMPTION ,
name = " Electric Energy Consumption " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh (not for modbus:YutakiV2DHWElectricalEnergyConsumptionComponent)
state_class = SensorStateClass . TOTAL_INCREASING , # core:MeasurementCategory attribute = electric/overall
) ,
OverkizSensorDescription (
key = OverkizState . CORE_ELECTRIC_POWER_CONSUMPTION ,
name = " Electric Power Consumption " ,
device_class = SensorDeviceClass . POWER ,
native_unit_of_measurement = POWER_WATT , # core:MeasuredValueType = core:ElectricalEnergyInWh (not for modbus:YutakiV2DHWElectricalEnergyConsumptionComponent)
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF1 ,
name = " Consumption Tariff 1 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF2 ,
name = " Consumption Tariff 2 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF3 ,
name = " Consumption Tariff 3 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF4 ,
name = " Consumption Tariff 4 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF5 ,
name = " Consumption Tariff 5 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF6 ,
name = " Consumption Tariff 6 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF7 ,
name = " Consumption Tariff 7 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF8 ,
name = " Consumption Tariff 8 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_CONSUMPTION_TARIFF9 ,
name = " Consumption Tariff 9 " ,
device_class = SensorDeviceClass . ENERGY ,
native_unit_of_measurement = ENERGY_WATT_HOUR , # core:MeasuredValueType = core:ElectricalEnergyInWh
entity_registry_enabled_default = False ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# HumiditySensor/RelativeHumiditySensor
OverkizSensorDescription (
key = OverkizState . CORE_RELATIVE_HUMIDITY ,
name = " Relative Humidity " ,
2022-01-08 09:53:15 +00:00
native_value = lambda value : round ( cast ( float , value ) , 2 ) ,
2021-12-23 18:34:35 +00:00
device_class = SensorDeviceClass . HUMIDITY ,
native_unit_of_measurement = PERCENTAGE , # core:MeasuredValueType = core:RelativeValueInPercentage
state_class = SensorStateClass . MEASUREMENT ,
) ,
# TemperatureSensor/TemperatureSensor
OverkizSensorDescription (
key = OverkizState . CORE_TEMPERATURE ,
name = " Temperature " ,
2022-01-08 09:53:15 +00:00
native_value = lambda value : round ( cast ( float , value ) , 2 ) ,
2021-12-23 18:34:35 +00:00
device_class = SensorDeviceClass . TEMPERATURE ,
native_unit_of_measurement = TEMP_CELSIUS , # core:MeasuredValueType = core:TemperatureInCelcius
state_class = SensorStateClass . MEASUREMENT ,
) ,
# WeatherSensor/WeatherForecastSensor
OverkizSensorDescription (
key = OverkizState . CORE_WEATHER_STATUS ,
name = " Weather Status " ,
device_class = SensorDeviceClass . TEMPERATURE ,
native_unit_of_measurement = TEMP_CELSIUS ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_MINIMUM_TEMPERATURE ,
name = " Minimum Temperature " ,
device_class = SensorDeviceClass . TEMPERATURE ,
native_unit_of_measurement = TEMP_CELSIUS ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_MAXIMUM_TEMPERATURE ,
name = " Maximum Temperature " ,
device_class = SensorDeviceClass . TEMPERATURE ,
native_unit_of_measurement = TEMP_CELSIUS ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# AirSensor/COSensor
OverkizSensorDescription (
key = OverkizState . CORE_CO_CONCENTRATION ,
name = " CO Concentration " ,
device_class = SensorDeviceClass . CO ,
native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# AirSensor/CO2Sensor
OverkizSensorDescription (
key = OverkizState . CORE_CO2_CONCENTRATION ,
name = " CO2 Concentration " ,
device_class = SensorDeviceClass . CO2 ,
native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# SunSensor/SunEnergySensor
OverkizSensorDescription (
key = OverkizState . CORE_SUN_ENERGY ,
name = " Sun Energy " ,
2022-01-08 09:53:15 +00:00
native_value = lambda value : round ( cast ( float , value ) , 2 ) ,
2021-12-23 18:34:35 +00:00
icon = " mdi:solar-power " ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# WindSensor/WindSpeedSensor
OverkizSensorDescription (
key = OverkizState . CORE_WIND_SPEED ,
name = " Wind Speed " ,
2022-01-08 09:53:15 +00:00
native_value = lambda value : round ( cast ( float , value ) , 2 ) ,
2021-12-23 18:34:35 +00:00
icon = " mdi:weather-windy " ,
state_class = SensorStateClass . MEASUREMENT ,
) ,
# SmokeSensor/SmokeSensor
OverkizSensorDescription (
key = OverkizState . IO_SENSOR_ROOM ,
name = " Sensor Room " ,
2022-01-17 20:47:42 +00:00
device_class = OverkizDeviceClass . SENSOR_ROOM ,
entity_category = EntityCategory . DIAGNOSTIC ,
icon = " mdi:spray-bottle " ,
2021-12-23 18:34:35 +00:00
) ,
OverkizSensorDescription (
key = OverkizState . IO_PRIORITY_LOCK_ORIGINATOR ,
name = " Priority Lock Originator " ,
2022-01-17 20:47:42 +00:00
device_class = OverkizDeviceClass . PRIORITY_LOCK_ORIGINATOR ,
2021-12-23 18:34:35 +00:00
icon = " mdi:lock " ,
entity_registry_enabled_default = False ,
2022-01-17 20:47:42 +00:00
native_value = lambda value : OVERKIZ_STATE_TO_TRANSLATION . get (
cast ( str , value ) , cast ( str , value )
) ,
2021-12-23 18:34:35 +00:00
) ,
OverkizSensorDescription (
key = OverkizState . CORE_PRIORITY_LOCK_TIMER ,
name = " Priority Lock Timer " ,
icon = " mdi:lock-clock " ,
native_unit_of_measurement = TIME_SECONDS ,
entity_registry_enabled_default = False ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_DISCRETE_RSSI_LEVEL ,
name = " Discrete RSSI Level " ,
entity_registry_enabled_default = False ,
entity_category = EntityCategory . DIAGNOSTIC ,
2022-01-17 20:47:42 +00:00
device_class = OverkizDeviceClass . DISCRETE_RSSI_LEVEL ,
icon = " mdi:wifi " ,
) ,
OverkizSensorDescription (
key = OverkizState . CORE_SENSOR_DEFECT ,
name = " Sensor Defect " ,
entity_registry_enabled_default = False ,
entity_category = EntityCategory . DIAGNOSTIC ,
device_class = OverkizDeviceClass . SENSOR_DEFECT ,
native_value = lambda value : OVERKIZ_STATE_TO_TRANSLATION . get (
cast ( str , value ) , cast ( str , value )
) ,
2021-12-23 18:34:35 +00:00
) ,
# DomesticHotWaterProduction/WaterHeatingSystem
OverkizSensorDescription (
key = OverkizState . IO_HEAT_PUMP_OPERATING_TIME ,
name = " Heat Pump Operating Time " ,
) ,
OverkizSensorDescription (
key = OverkizState . IO_ELECTRIC_BOOSTER_OPERATING_TIME ,
name = " Electric Booster Operating Time " ,
) ,
2022-02-15 20:24:33 +00:00
# Cover
OverkizSensorDescription (
key = OverkizState . CORE_TARGET_CLOSURE ,
name = " Target Closure " ,
native_unit_of_measurement = PERCENTAGE ,
entity_registry_enabled_default = False ,
) ,
2022-06-21 15:31:26 +00:00
# ThreeWayWindowHandle/WindowHandle
OverkizSensorDescription (
key = OverkizState . CORE_THREE_WAY_HANDLE_DIRECTION ,
name = " Three Way Handle Direction " ,
device_class = OverkizDeviceClass . THREE_WAY_HANDLE_DIRECTION ,
) ,
2021-12-23 18:34:35 +00:00
]
2022-01-17 20:25:24 +00:00
SUPPORTED_STATES = { description . key : description for description in SENSOR_DESCRIPTIONS }
2021-12-23 18:34:35 +00:00
async def async_setup_entry (
hass : HomeAssistant ,
entry : ConfigEntry ,
async_add_entities : AddEntitiesCallback ,
2021-12-30 14:22:35 +00:00
) - > None :
2021-12-23 18:34:35 +00:00
""" Set up the Overkiz sensors from a config entry. """
data : HomeAssistantOverkizData = hass . data [ DOMAIN ] [ entry . entry_id ]
entities : list [ SensorEntity ] = [ ]
for device in data . coordinator . data . values ( ) :
if device . widget == UIWidget . HOMEKIT_STACK :
entities . append (
OverkizHomeKitSetupCodeSensor (
device . device_url ,
data . coordinator ,
)
)
2021-12-27 17:26:55 +00:00
if (
device . widget in IGNORED_OVERKIZ_DEVICES
or device . ui_class in IGNORED_OVERKIZ_DEVICES
) :
continue
for state in device . definition . states :
2022-01-17 20:25:24 +00:00
if description := SUPPORTED_STATES . get ( state . qualified_name ) :
2021-12-27 17:26:55 +00:00
entities . append (
OverkizStateSensor (
device . device_url ,
data . coordinator ,
description ,
)
)
2021-12-23 18:34:35 +00:00
async_add_entities ( entities )
class OverkizStateSensor ( OverkizDescriptiveEntity , SensorEntity ) :
""" Representation of an Overkiz Sensor. """
2021-12-27 17:26:55 +00:00
entity_description : OverkizSensorDescription
2021-12-23 18:34:35 +00:00
@property
2021-12-30 14:22:35 +00:00
def native_value ( self ) - > StateType :
2021-12-23 18:34:35 +00:00
""" Return the value of the sensor. """
state = self . device . states . get ( self . entity_description . key )
2022-01-08 09:53:15 +00:00
if not state or not state . value :
2021-12-23 18:34:35 +00:00
return None
# Transform the value with a lambda function
2021-12-27 17:26:55 +00:00
if self . entity_description . native_value :
2021-12-23 18:34:35 +00:00
return self . entity_description . native_value ( state . value )
2022-01-13 01:23:20 +00:00
if isinstance ( state . value , ( dict , list ) ) :
return None
2022-01-08 09:53:15 +00:00
return state . value
2021-12-23 18:34:35 +00:00
class OverkizHomeKitSetupCodeSensor ( OverkizEntity , SensorEntity ) :
""" Representation of an Overkiz HomeKit Setup Code. """
_attr_icon = " mdi:shield-home "
_attr_entity_category = EntityCategory . DIAGNOSTIC
def __init__ (
self , device_url : str , coordinator : OverkizDataUpdateCoordinator
) - > None :
""" Initialize the device. """
super ( ) . __init__ ( device_url , coordinator )
self . _attr_name = " HomeKit Setup Code "
@property
2021-12-31 17:35:15 +00:00
def native_value ( self ) - > str | None :
2021-12-23 18:34:35 +00:00
""" Return the value of the sensor. """
2021-12-31 17:35:15 +00:00
if state := self . device . attributes . get ( OverkizAttribute . HOMEKIT_SETUP_CODE ) :
return cast ( str , state . value )
return None
2021-12-23 18:34:35 +00:00
@property
def device_info ( self ) - > DeviceInfo :
""" Return device registry information for this entity. """
# By default this sensor will be listed at a virtual HomekitStack device,
# but it makes more sense to show this at the gateway device in the entity registry.
return {
" identifiers " : { ( DOMAIN , self . executor . get_gateway_id ( ) ) } ,
}