diff --git a/homeassistant/components/daikin/const.py b/homeassistant/components/daikin/const.py index b03c8eb113d..e0222d308ea 100644 --- a/homeassistant/components/daikin/const.py +++ b/homeassistant/components/daikin/const.py @@ -1,21 +1,4 @@ """Constants for Daikin.""" -from homeassistant.const import ( - CONF_DEVICE_CLASS, - CONF_ICON, - CONF_NAME, - CONF_TYPE, - CONF_UNIT_OF_MEASUREMENT, - DEVICE_CLASS_ENERGY, - DEVICE_CLASS_HUMIDITY, - DEVICE_CLASS_POWER, - DEVICE_CLASS_TEMPERATURE, - ENERGY_KILO_WATT_HOUR, - FREQUENCY_HERTZ, - PERCENTAGE, - POWER_KILO_WATT, - TEMP_CELSIUS, -) - DOMAIN = "daikin" ATTR_TARGET_TEMPERATURE = "target_temperature" @@ -31,65 +14,6 @@ ATTR_COMPRESSOR_FREQUENCY = "compressor_frequency" ATTR_STATE_ON = "on" ATTR_STATE_OFF = "off" -SENSOR_TYPE_TEMPERATURE = "temperature" -SENSOR_TYPE_HUMIDITY = "humidity" -SENSOR_TYPE_POWER = "power" -SENSOR_TYPE_ENERGY = "energy" -SENSOR_TYPE_FREQUENCY = "frequency" - -SENSOR_TYPES = { - ATTR_INSIDE_TEMPERATURE: { - CONF_NAME: "Inside Temperature", - CONF_TYPE: SENSOR_TYPE_TEMPERATURE, - CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - CONF_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, - }, - ATTR_OUTSIDE_TEMPERATURE: { - CONF_NAME: "Outside Temperature", - CONF_TYPE: SENSOR_TYPE_TEMPERATURE, - CONF_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - CONF_UNIT_OF_MEASUREMENT: TEMP_CELSIUS, - }, - ATTR_HUMIDITY: { - CONF_NAME: "Humidity", - CONF_TYPE: SENSOR_TYPE_HUMIDITY, - CONF_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, - CONF_UNIT_OF_MEASUREMENT: PERCENTAGE, - }, - ATTR_TARGET_HUMIDITY: { - CONF_NAME: "Target Humidity", - CONF_TYPE: SENSOR_TYPE_HUMIDITY, - CONF_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, - CONF_UNIT_OF_MEASUREMENT: PERCENTAGE, - }, - ATTR_TOTAL_POWER: { - CONF_NAME: "Total Power Consumption", - CONF_TYPE: SENSOR_TYPE_POWER, - CONF_DEVICE_CLASS: DEVICE_CLASS_POWER, - CONF_UNIT_OF_MEASUREMENT: POWER_KILO_WATT, - }, - ATTR_COOL_ENERGY: { - CONF_NAME: "Cool Energy Consumption", - CONF_TYPE: SENSOR_TYPE_ENERGY, - CONF_ICON: "mdi:snowflake", - CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY, - CONF_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR, - }, - ATTR_HEAT_ENERGY: { - CONF_NAME: "Heat Energy Consumption", - CONF_TYPE: SENSOR_TYPE_ENERGY, - CONF_ICON: "mdi:fire", - CONF_DEVICE_CLASS: DEVICE_CLASS_ENERGY, - CONF_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR, - }, - ATTR_COMPRESSOR_FREQUENCY: { - CONF_NAME: "Compressor Frequency", - CONF_TYPE: SENSOR_TYPE_FREQUENCY, - CONF_ICON: "mdi:fan", - CONF_UNIT_OF_MEASUREMENT: FREQUENCY_HERTZ, - }, -} - CONF_UUID = "uuid" KEY_MAC = "mac" diff --git a/homeassistant/components/daikin/sensor.py b/homeassistant/components/daikin/sensor.py index 0defa633387..1b590b261b7 100644 --- a/homeassistant/components/daikin/sensor.py +++ b/homeassistant/components/daikin/sensor.py @@ -1,11 +1,22 @@ """Support for Daikin AC sensors.""" -from homeassistant.components.sensor import SensorEntity +from __future__ import annotations + +from dataclasses import dataclass +from typing import Callable + +from pydaikin.daikin_base import Appliance + +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.const import ( - CONF_DEVICE_CLASS, - CONF_ICON, - CONF_NAME, - CONF_TYPE, - CONF_UNIT_OF_MEASUREMENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_TEMPERATURE, + ENERGY_KILO_WATT_HOUR, + FREQUENCY_HERTZ, + PERCENTAGE, + POWER_KILO_WATT, + TEMP_CELSIUS, ) from . import DOMAIN as DAIKIN_DOMAIN, DaikinApi @@ -18,12 +29,80 @@ from .const import ( ATTR_OUTSIDE_TEMPERATURE, ATTR_TARGET_HUMIDITY, ATTR_TOTAL_POWER, - SENSOR_TYPE_ENERGY, - SENSOR_TYPE_FREQUENCY, - SENSOR_TYPE_HUMIDITY, - SENSOR_TYPE_POWER, - SENSOR_TYPE_TEMPERATURE, - SENSOR_TYPES, +) + + +@dataclass +class DaikinRequiredKeysMixin: + """Mixin for required keys.""" + + value_func: Callable[[Appliance], float | None] + + +@dataclass +class DaikinSensorEntityDescription(SensorEntityDescription, DaikinRequiredKeysMixin): + """Describes Daikin sensor entity.""" + + +SENSOR_TYPES: tuple[DaikinSensorEntityDescription, ...] = ( + DaikinSensorEntityDescription( + key=ATTR_INSIDE_TEMPERATURE, + name="Inside Temperature", + device_class=DEVICE_CLASS_TEMPERATURE, + native_unit_of_measurement=TEMP_CELSIUS, + value_func=lambda device: device.inside_temperature, + ), + DaikinSensorEntityDescription( + key=ATTR_OUTSIDE_TEMPERATURE, + name="Outside Temperature", + device_class=DEVICE_CLASS_TEMPERATURE, + native_unit_of_measurement=TEMP_CELSIUS, + value_func=lambda device: device.outside_temperature, + ), + DaikinSensorEntityDescription( + key=ATTR_HUMIDITY, + name="Humidity", + device_class=DEVICE_CLASS_HUMIDITY, + native_unit_of_measurement=PERCENTAGE, + value_func=lambda device: device.humidity, + ), + DaikinSensorEntityDescription( + key=ATTR_TARGET_HUMIDITY, + name="Target Humidity", + device_class=DEVICE_CLASS_HUMIDITY, + native_unit_of_measurement=PERCENTAGE, + value_func=lambda device: device.humidity, + ), + DaikinSensorEntityDescription( + key=ATTR_TOTAL_POWER, + name="Total Power Consumption", + device_class=DEVICE_CLASS_POWER, + native_unit_of_measurement=POWER_KILO_WATT, + value_func=lambda device: round(device.current_total_power_consumption, 2), + ), + DaikinSensorEntityDescription( + key=ATTR_COOL_ENERGY, + name="Cool Energy Consumption", + icon="mdi:snowflake", + device_class=DEVICE_CLASS_ENERGY, + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + value_func=lambda device: round(device.last_hour_cool_energy_consumption, 2), + ), + DaikinSensorEntityDescription( + key=ATTR_HEAT_ENERGY, + name="Heat Energy Consumption", + icon="mdi:fire", + device_class=DEVICE_CLASS_ENERGY, + native_unit_of_measurement=ENERGY_KILO_WATT_HOUR, + value_func=lambda device: round(device.last_hour_heat_energy_consumption, 2), + ), + DaikinSensorEntityDescription( + key=ATTR_COMPRESSOR_FREQUENCY, + name="Compressor Frequency", + icon="mdi:fan", + native_unit_of_measurement=FREQUENCY_HERTZ, + value_func=lambda device: device.compressor_frequency, + ), ) @@ -50,60 +129,37 @@ async def async_setup_entry(hass, entry, async_add_entities): sensors.append(ATTR_TARGET_HUMIDITY) if daikin_api.device.support_compressor_frequency: sensors.append(ATTR_COMPRESSOR_FREQUENCY) - async_add_entities([DaikinSensor.factory(daikin_api, sensor) for sensor in sensors]) + + entities = [ + DaikinSensor(daikin_api, description) + for description in SENSOR_TYPES + if description.key in sensors + ] + async_add_entities(entities) class DaikinSensor(SensorEntity): """Representation of a Sensor.""" - @staticmethod - def factory(api: DaikinApi, monitored_state: str): - """Initialize any DaikinSensor.""" - cls = { - SENSOR_TYPE_TEMPERATURE: DaikinClimateSensor, - SENSOR_TYPE_HUMIDITY: DaikinClimateSensor, - SENSOR_TYPE_POWER: DaikinPowerSensor, - SENSOR_TYPE_ENERGY: DaikinPowerSensor, - SENSOR_TYPE_FREQUENCY: DaikinClimateSensor, - }[SENSOR_TYPES[monitored_state][CONF_TYPE]] - return cls(api, monitored_state) + entity_description: DaikinSensorEntityDescription - def __init__(self, api: DaikinApi, monitored_state: str) -> None: + def __init__( + self, api: DaikinApi, description: DaikinSensorEntityDescription + ) -> None: """Initialize the sensor.""" + self.entity_description = description self._api = api - self._sensor = SENSOR_TYPES[monitored_state] - self._name = f"{api.name} {self._sensor[CONF_NAME]}" - self._device_attribute = monitored_state + self._attr_name = f"{api.name} {description.name}" @property def unique_id(self): """Return a unique ID.""" - return f"{self._api.device.mac}-{self._device_attribute}" + return f"{self._api.device.mac}-{self.entity_description.key}" @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def native_value(self): + def native_value(self) -> float | None: """Return the state of the sensor.""" - raise NotImplementedError - - @property - def device_class(self): - """Return the class of this device.""" - return self._sensor.get(CONF_DEVICE_CLASS) - - @property - def icon(self): - """Return the icon of this device.""" - return self._sensor.get(CONF_ICON) - - @property - def native_unit_of_measurement(self): - """Return the unit of measurement.""" - return self._sensor[CONF_UNIT_OF_MEASUREMENT] + return self.entity_description.value_func(self._api.device) async def async_update(self): """Retrieve latest state.""" @@ -113,40 +169,3 @@ class DaikinSensor(SensorEntity): def device_info(self): """Return a device description for device registry.""" return self._api.device_info - - -class DaikinClimateSensor(DaikinSensor): - """Representation of a Climate Sensor.""" - - @property - def native_value(self): - """Return the internal state of the sensor.""" - if self._device_attribute == ATTR_INSIDE_TEMPERATURE: - return self._api.device.inside_temperature - if self._device_attribute == ATTR_OUTSIDE_TEMPERATURE: - return self._api.device.outside_temperature - - if self._device_attribute == ATTR_HUMIDITY: - return self._api.device.humidity - if self._device_attribute == ATTR_TARGET_HUMIDITY: - return self._api.device.target_humidity - - if self._device_attribute == ATTR_COMPRESSOR_FREQUENCY: - return self._api.device.compressor_frequency - - return None - - -class DaikinPowerSensor(DaikinSensor): - """Representation of a power/energy consumption sensor.""" - - @property - def native_value(self): - """Return the state of the sensor.""" - if self._device_attribute == ATTR_TOTAL_POWER: - return round(self._api.device.current_total_power_consumption, 2) - if self._device_attribute == ATTR_COOL_ENERGY: - return round(self._api.device.last_hour_cool_energy_consumption, 2) - if self._device_attribute == ATTR_HEAT_ENERGY: - return round(self._api.device.last_hour_heat_energy_consumption, 2) - return None