"""Number platform for IronOS integration.""" from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass from enum import StrEnum from pynecil import CharSetting, CommunicationError, LiveDataResponse from homeassistant.components.number import ( NumberDeviceClass, NumberEntity, NumberEntityDescription, NumberMode, ) from homeassistant.const import UnitOfTemperature from homeassistant.core import HomeAssistant from homeassistant.exceptions import ServiceValidationError from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import IronOSConfigEntry from .const import DOMAIN, MAX_TEMP, MIN_TEMP from .entity import IronOSBaseEntity @dataclass(frozen=True, kw_only=True) class IronOSNumberEntityDescription(NumberEntityDescription): """Describes IronOS number entity.""" value_fn: Callable[[LiveDataResponse], float | int | None] max_value_fn: Callable[[LiveDataResponse], float | int] set_key: CharSetting class PinecilNumber(StrEnum): """Number controls for Pinecil device.""" SETPOINT_TEMP = "setpoint_temperature" PINECIL_NUMBER_DESCRIPTIONS: tuple[IronOSNumberEntityDescription, ...] = ( IronOSNumberEntityDescription( key=PinecilNumber.SETPOINT_TEMP, translation_key=PinecilNumber.SETPOINT_TEMP, native_unit_of_measurement=UnitOfTemperature.CELSIUS, device_class=NumberDeviceClass.TEMPERATURE, value_fn=lambda data: data.setpoint_temp, set_key=CharSetting.SETPOINT_TEMP, mode=NumberMode.BOX, native_min_value=MIN_TEMP, native_step=5, max_value_fn=lambda data: min(data.max_tip_temp_ability or MAX_TEMP, MAX_TEMP), ), ) async def async_setup_entry( hass: HomeAssistant, entry: IronOSConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up number entities from a config entry.""" coordinator = entry.runtime_data async_add_entities( IronOSNumberEntity(coordinator, description) for description in PINECIL_NUMBER_DESCRIPTIONS ) class IronOSNumberEntity(IronOSBaseEntity, NumberEntity): """Implementation of a IronOS number entity.""" entity_description: IronOSNumberEntityDescription async def async_set_native_value(self, value: float) -> None: """Update the current value.""" try: await self.coordinator.device.write(self.entity_description.set_key, value) except CommunicationError as e: raise ServiceValidationError( translation_domain=DOMAIN, translation_key="submit_setting_failed", ) from e self.async_write_ha_state() @property def native_value(self) -> float | int | None: """Return sensor state.""" return self.entity_description.value_fn(self.coordinator.data) @property def native_max_value(self) -> float: """Return sensor state.""" return self.entity_description.max_value_fn(self.coordinator.data)