22from typing import Callable
33from dataclasses import dataclass
44
5- from homeassistant .const import PERCENTAGE
5+ from homeassistant .const import PERCENTAGE , UnitOfTemperature
6+
7+ _LOGGER = logging .getLogger (__name__ )
68from homeassistant .core import HomeAssistant
79from homeassistant .components .number import (
810 NumberDeviceClass ,
1214)
1315
1416from aio_panasonic_comfort_cloud import PanasonicDevice , PanasonicDeviceZone , ChangeRequestBuilder
17+ from aioaquarea import Device as AquareaDevice
18+ from aioaquarea import ExtendedOperationMode
1519
1620from . import DOMAIN
17- from .const import DATA_COORDINATORS
18- from .coordinator import PanasonicDeviceCoordinator
19- from .base import PanasonicDataEntity
21+ from .const import DATA_COORDINATORS , AQUAREA_COORDINATORS
22+ from .coordinator import PanasonicDeviceCoordinator , AquareaDeviceCoordinator
23+ from .base import PanasonicDataEntity , AquareaDataEntity
2024
2125@dataclass (frozen = True , kw_only = True )
2226class PanasonicNumberEntityDescription (NumberEntityDescription ):
2327 """Describes Panasonic Number entity."""
2428 get_value : Callable [[PanasonicDevice ], int ]
2529 set_value : Callable [[ChangeRequestBuilder , int ], ChangeRequestBuilder ]
2630
31+ @dataclass (frozen = True , kw_only = True )
32+ class AquareaNumberEntityDescription (NumberEntityDescription ):
33+ """Describes Aquarea Number entity."""
34+ zone_id : int
35+
2736def create_zone_damper_description (zone : PanasonicDeviceZone ):
2837 return PanasonicNumberEntityDescription (
2938 key = f"zone-{ zone .id } -damper" ,
@@ -49,9 +58,51 @@ async def async_setup_entry(hass: HomeAssistant, entry, async_add_entities):
4958 data_coordinator ,
5059 create_zone_damper_description (zone )))
5160
61+ # Aquarea Number entities for temperature targets
62+ aquarea_coordinators : list [AquareaDeviceCoordinator ] = hass .data [DOMAIN ][AQUAREA_COORDINATORS ]
63+ for coordinator in aquarea_coordinators :
64+ for zone_id in coordinator .device .zones :
65+ zone = coordinator .device .zones .get (zone_id )
66+ # Add heat target temperature
67+ devices .append (AquareaNumberEntity (
68+ coordinator ,
69+ AquareaNumberEntityDescription (
70+ zone_id = zone_id ,
71+ key = f"zone-{ zone_id } -heat-target" ,
72+ translation_key = f"zone-{ zone_id } -heat-target" ,
73+ name = f"{ zone .name } Heat Target" ,
74+ icon = "mdi:thermometer" ,
75+ device_class = NumberDeviceClass .TEMPERATURE ,
76+ native_unit_of_measurement = UnitOfTemperature .CELSIUS ,
77+ native_max_value = zone .heat_max if zone .heat_max is not None else 30 ,
78+ native_min_value = zone .heat_min if zone .heat_min is not None else 10 ,
79+ native_step = 1 ,
80+ mode = NumberMode .BOX ,
81+ )
82+ ))
83+ # Add cool target temperature if supported
84+ if zone .cool_max and zone .cool_min :
85+ devices .append (AquareaNumberEntity (
86+ coordinator ,
87+ AquareaNumberEntityDescription (
88+ zone_id = zone_id ,
89+ key = f"zone-{ zone_id } -cool-target" ,
90+ translation_key = f"zone-{ zone_id } -cool-target" ,
91+ name = f"{ zone .name } Cool Target" ,
92+ icon = "mdi:thermometer" ,
93+ device_class = NumberDeviceClass .TEMPERATURE ,
94+ native_unit_of_measurement = UnitOfTemperature .CELSIUS ,
95+ native_max_value = zone .cool_max if zone .cool_max is not None else 30 ,
96+ native_min_value = zone .cool_min if zone .cool_min is not None else 16 ,
97+ native_step = 1 ,
98+ mode = NumberMode .BOX ,
99+ )
100+ ))
101+
52102 async_add_entities (devices )
53103
54104class PanasonicNumberEntity (PanasonicDataEntity , NumberEntity ):
105+ """Representation of a Panasonic Number."""
55106
56107 entity_description : PanasonicNumberEntityDescription
57108
@@ -70,4 +121,57 @@ async def async_set_native_value(self, value: float) -> None:
70121 self .async_write_ha_state ()
71122
72123 def _async_update_attrs (self ) -> None :
73- self ._attr_native_value = self .entity_description .get_value (self .coordinator .device )
124+ self ._attr_native_value = self .entity_description .get_value (self .coordinator .device )
125+
126+
127+ class AquareaNumberEntity (AquareaDataEntity , NumberEntity ):
128+ """Aquarea Number entity for setting target temperatures."""
129+
130+ entity_description : AquareaNumberEntityDescription
131+
132+ def __init__ (self , coordinator : AquareaDeviceCoordinator , description : AquareaNumberEntityDescription ):
133+ """Initialize the number entity."""
134+ self .entity_description = description
135+ super ().__init__ (coordinator , description .key )
136+
137+ async def async_set_native_value (self , value : float ) -> None :
138+ """Set new target temperature value."""
139+ zone_id = self .entity_description .zone_id
140+ temperature = int (value )
141+
142+ # Determine if we're setting heat or cool based on key
143+ if "heat-target" in self .entity_description .key :
144+ # Temporarily switch mode to HEAT if needed
145+ original_mode = self .coordinator .device .mode
146+ if original_mode not in (ExtendedOperationMode .HEAT , ExtendedOperationMode .AUTO_HEAT ):
147+ _LOGGER .debug (f"Switching to HEAT mode to set heat target for zone { zone_id } " )
148+ await self .coordinator .device .set_temperature (temperature , zone_id )
149+ elif "cool-target" in self .entity_description .key :
150+ # Temporarily switch mode to COOL if needed
151+ original_mode = self .coordinator .device .mode
152+ if original_mode not in (ExtendedOperationMode .COOL , ExtendedOperationMode .AUTO_COOL ):
153+ _LOGGER .debug (f"Switching to COOL mode to set cool target for zone { zone_id } " )
154+ await self .coordinator .device .set_temperature (temperature , zone_id )
155+
156+ self ._attr_native_value = temperature
157+ self .async_write_ha_state ()
158+ await self .coordinator .async_request_refresh ()
159+
160+ def _async_update_attrs (self ) -> None :
161+ """Update the current value."""
162+ zone = self .coordinator .device .zones .get (self .entity_description .zone_id )
163+ if zone :
164+ # Si heatSet/coolSet n'est pas disponible dans l'API,
165+ # on affiche la température actuelle comme référence
166+ if "heat-target" in self .entity_description .key :
167+ # Try to get target temperature first, fallback to current temperature
168+ temp = zone .heat_target_temperature
169+ if temp is None :
170+ # L'API ne retourne pas la consigne, on utilise la temp actuelle comme ref
171+ temp = zone .temperature
172+ self ._attr_native_value = temp
173+ elif "cool-target" in self .entity_description .key :
174+ temp = zone .cool_target_temperature
175+ if temp is None :
176+ temp = zone .temperature
177+ self ._attr_native_value = temp
0 commit comments