""" Implement the Number entities of this implementation """ from __future__ import annotations import sys from home_connect_async import Appliance, HomeConnect, HomeConnectError, Events from homeassistant.components.number import NumberEntity from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import ConfigType from .common import Configuration, InteractiveEntityBase, EntityManager from .const import DOMAIN async def async_setup_entry(hass:HomeAssistant , config_entry:ConfigType, async_add_entities:AddEntitiesCallback) -> None: """Add Numbers for passed config_entry in HA.""" #auth = hass.data[DOMAIN][config_entry.entry_id] #homeconnect:HomeConnect = hass.data[DOMAIN]['homeconnect'] entry_conf:Configuration = hass.data[DOMAIN][config_entry.entry_id] homeconnect:HomeConnect = entry_conf["homeconnect"] entity_manager = EntityManager(async_add_entities, "Number") number_types = ["Int", "Float", "Double"] def add_appliance(appliance:Appliance) -> None: conf = entry_conf.get_config() if appliance.available_programs: for program in appliance.available_programs.values(): if program.options: for option in program.options.values(): if (not conf.has_entity_setting(option.key, "type") and option.type in number_types) or conf.has_entity_setting(option.key, "type") in number_types: device = OptionNumber(appliance, option.key, conf, hc_obj=option) entity_manager.add(device) if appliance.settings: for setting in appliance.settings.values(): if ((not conf.has_entity_setting(setting.key, "type") and setting.type in number_types) or conf.has_entity_setting(setting.key, "type") in number_types) \ and setting.access != "read" : device = SettingsNumber(appliance, setting.key, conf, hc_obj=setting) entity_manager.add(device) entity_manager.register() def remove_appliance(appliance:Appliance) -> None: entity_manager.remove_appliance(appliance) homeconnect.register_callback(add_appliance,[Events.PAIRED, Events.DATA_CHANGED, Events.PROGRAM_STARTED, Events.PROGRAM_SELECTED]) homeconnect.register_callback(remove_appliance, Events.DEPAIRED) for appliance in homeconnect.appliances.values(): add_appliance(appliance) class OptionNumber(InteractiveEntityBase, NumberEntity): """ Class for numeric options """ @property def device_class(self) -> str: return f"{DOMAIN}__options" @property def name_ext(self) -> str|None: if self._appliance.available_programs: for program in self._appliance.available_programs.values(): if program.options and self._key in program.options and program.options[self._key].name: return program.options[self._key].name return None @property def icon(self) -> str: return self.get_entity_setting('icon', 'mdi:office-building-cog') @property def available(self) -> bool: return self.program_option_available @property def native_min_value(self) -> float: """Return the minimum value.""" if self._hc_obj.min: return self._hc_obj.min return 0 @property def native_max_value(self) -> float: """Return the maximum value.""" if self._hc_obj.max: return self._hc_obj.max return sys.maxsize @property def native_step(self) -> float: """Return the increment/decrement step.""" return self._hc_obj.stepsize @property def native_unit_of_measurement(self) -> str: if self.has_entity_setting("unit"): return self.get_entity_setting("unit") if self._hc_obj.unit: return self._hc_obj.unit return "" @property def native_value(self) -> float: """Return the entity value to represent the entity state.""" option = self._appliance.get_applied_program_option(self._key) if option: return option.value return None async def async_set_native_value(self, value: float) -> None: """Set new value.""" try: if self._hc_obj.type == 'Int': value = int(value) await self._appliance.async_set_option(self._key, value) except HomeConnectError as ex: if ex.error_description: raise HomeAssistantError(f"Failed to set the option value: {ex.error_description} ({ex.code} - {self._key}={value})") raise HomeAssistantError(f"Failed to set the option value: ({ex.code} - {self._key}={value})") async def async_on_update(self, appliance:Appliance, key:str, value) -> None: self.async_write_ha_state() class SettingsNumber(InteractiveEntityBase, NumberEntity): """ Class for numeric settings """ @property def device_class(self) -> str: return f"{DOMAIN}__settings" @property def name_ext(self) -> str|None: return self._hc_obj.name @property def icon(self) -> str: return self.get_entity_setting('icon', 'mdi:tune') @property def native_min_value(self) -> float: """Return the minimum value.""" if self._hc_obj.min: return self._hc_obj.min return 0 @property def native_max_value(self) -> float: """Return the maximum value.""" if self._hc_obj.max: return self._hc_obj.max return sys.maxsize @property def native_step(self) -> float: """Return the increment/decrement step.""" return self._hc_obj.stepsize @property def native_unit_of_measurement(self) -> str: if self.has_entity_setting("unit"): return self.get_entity_setting("unit") if self._hc_obj.unit: return self._hc_obj.unit return "" @property def native_value(self) -> float: """Return the entity value to represent the entity state.""" return self._hc_obj.value async def async_set_native_value(self, value: float) -> None: try: await self._appliance.async_apply_setting(self._key, value) except HomeConnectError as ex: if ex.error_description: raise HomeAssistantError(f"Failed to apply the setting value: {ex.error_description} ({ex.code})") raise HomeAssistantError(f"Failed to apply the setting value: ({ex.code})") async def async_on_update(self, appliance:Appliance, key:str, value) -> None: self.async_write_ha_state()