33"""
44from __future__ import annotations
55
6+ from typing import Any
7+
68import aiohttp
79from defusedxml import ElementTree as etree
810
2022 DOMAIN_OBJECTS ,
2123 LOCATIONS ,
2224 LOGGER ,
25+ MAX_SETPOINT ,
26+ MIN_SETPOINT ,
2327 MODULES ,
2428 NOTIFICATIONS ,
2529 RULES ,
2832 SWITCH_GROUP_TYPES ,
2933 SYSTEM ,
3034 THERMOSTAT_CLASSES ,
35+ ZONE_THERMOSTATS ,
3136 ApplianceData ,
3237 DeviceData ,
3338 GatewayData ,
4752class SmileData (SmileHelper ):
4853 """The Plugwise Smile main class."""
4954
55+ def update_for_cooling (self , devices : dict [str , DeviceData ]) -> None :
56+ """Helper-function for adding/updating various cooling-related values."""
57+ for _ , device in devices .items ():
58+ # For Anna + cooling, modify cooling_state based on provided info by Plugwise
59+ if self .smile_name == "Anna" :
60+ if device ["dev_class" ] == "heater_central" and self ._cooling_present :
61+ device ["binary_sensors" ]["cooling_state" ] = False
62+ if self ._elga_cooling_active or self ._lortherm_cooling_active :
63+ device ["binary_sensors" ]["cooling_state" ] = True
64+
65+ # Add setpoint_low and setpoint_high when cooling is enabled
66+ if device ["dev_class" ] not in ZONE_THERMOSTATS :
67+ continue
68+
69+ if self .elga_cooling_enabled :
70+ sensors = device ["sensors" ]
71+ sensors ["setpoint_low" ] = sensors ["setpoint" ]
72+ sensors ["setpoint_high" ] = MAX_SETPOINT
73+ if self ._elga_cooling_active :
74+ sensors ["setpoint_low" ] = MIN_SETPOINT
75+ sensors ["setpoint_high" ] = sensors ["setpoint" ]
76+ if self ._sched_setpoints is not None :
77+ sensors ["setpoint_low" ] = self ._sched_setpoints [0 ]
78+ sensors ["setpoint_high" ] = self ._sched_setpoints [1 ]
79+
80+ # For Adam + on/off cooling, modify heating_state and cooling_state
81+ # based on provided info by Plugwise
82+ if (
83+ self .smile_name == "Adam"
84+ and device ["dev_class" ] == "heater_central"
85+ and self ._on_off_device
86+ and self ._adam_cooling_enabled
87+ and device ["binary_sensors" ]["heating_state" ]
88+ ):
89+ device ["binary_sensors" ]["cooling_state" ] = True
90+ device ["binary_sensors" ]["heating_state" ] = False
91+
5092 def _all_device_data (self ) -> None :
5193 """Helper-function for get_all_devices().
5294 Collect initial data for each device and add to self.gw_data and self.gw_devices.
@@ -60,6 +102,9 @@ def _all_device_data(self) -> None:
60102 device_id , data , device , bs_dict , s_dict , sw_dict
61103 )
62104
105+ # After all device data has been determined, add/update for cooling
106+ self .update_for_cooling (self .gw_devices )
107+
63108 self .gw_data .update (
64109 {"smile_name" : self .smile_name , "gateway_id" : self .gateway_id }
65110 )
@@ -87,17 +132,24 @@ def get_all_devices(self) -> None:
87132 self ._opentherm_device = open_therm_boiler is not None
88133
89134 # Determine if the Adam or Anna has cooling capability
90- locator = "./gateway/features/cooling"
91- anna_cooling_present_1 = adam_cooling_present = (
92- self ._domain_objects .find (locator ) is not None
93- )
94- # Alternative method for the Anna with Elga
135+ locator_1 = "./gateway/features/cooling"
95136 locator_2 = "./gateway/features/elga_support"
96- anna_cooling_present_2 = self ._domain_objects .find (locator_2 ) is not None
97- if self .smile_name == "Anna" :
98- self ._anna_cooling_present = (
99- anna_cooling_present_1 or anna_cooling_present_2
100- )
137+ locator_3 = "./module[vendor_name='Atlantic']"
138+ locator_4 = "./module[vendor_model='Loria']"
139+ search = self ._domain_objects
140+ self ._anna_cooling_present = adam_cooling_present = False
141+ if search .find (locator_1 ) is not None :
142+ if self .smile_name == "Anna" :
143+ self ._anna_cooling_present = True
144+ else :
145+ adam_cooling_present = True
146+ # Alternative method for the Anna with Elga, or alternative method for the Anna with Loria/Thermastage
147+ elif search .find (locator_2 ) is not None or (
148+ search .find (locator_3 ) is not None
149+ and search .find (locator_4 ) is not None
150+ ):
151+ self ._anna_cooling_present = True
152+
101153 self ._cooling_present = self ._anna_cooling_present or adam_cooling_present
102154
103155 # Gather all the device and initial data
@@ -109,29 +161,6 @@ def get_all_devices(self) -> None:
109161 # Collect data for each device via helper function
110162 self ._all_device_data ()
111163
112- # Anna: indicate possible active heating/cooling operation-mode
113- # Actual ongoing heating/cooling is shown via heating_state/cooling_state
114- if self ._anna_cooling_present and not self .anna_cool_ena_indication :
115- if (
116- not self ._anna_cooling_derived
117- and self ._outdoor_temp > self ._cooling_activation_outdoor_temp
118- ):
119- self ._anna_cooling_derived = True
120- if (
121- self ._anna_cooling_derived
122- and self ._outdoor_temp < self ._cooling_deactivation_threshold
123- ):
124- self ._anna_cooling_derived = False
125-
126- # Don't show cooling_state when no cooling present
127- for _ , device in self .gw_devices .items ():
128- if (
129- not self ._cooling_present
130- and "binary_sensors" in device
131- and "cooling_state" in device ["binary_sensors" ]
132- ):
133- device ["binary_sensors" ].pop ("cooling_state" )
134-
135164 def _device_data_switching_group (
136165 self , details : ApplianceData , device_data : DeviceData
137166 ) -> DeviceData :
@@ -181,27 +210,18 @@ def _device_data_climate(
181210 device_data ["active_preset" ] = self ._preset (loc_id )
182211
183212 # Schedule
184- avail_schedules , sel_schedule , sched_setpoints , last_active = self ._schedules (
185- loc_id
186- )
213+ (
214+ avail_schedules ,
215+ sel_schedule ,
216+ self ._sched_setpoints ,
217+ last_active ,
218+ ) = self ._schedules (loc_id )
187219 device_data ["available_schedules" ] = avail_schedules
188220 device_data ["selected_schedule" ] = sel_schedule
189221 if self ._smile_legacy :
190222 device_data ["last_used" ] = "" .join (map (str , avail_schedules ))
191223 else :
192224 device_data ["last_used" ] = last_active
193- if self ._anna_cooling_present :
194- if sched_setpoints is None :
195- device_data ["setpoint_low" ] = device_data ["setpoint" ]
196- device_data ["setpoint_high" ] = float (40 )
197- if self ._anna_cooling_derived or self .anna_cooling_enabled :
198- device_data ["setpoint_low" ] = float (0 )
199- device_data ["setpoint_high" ] = device_data ["setpoint" ]
200- else :
201- device_data ["setpoint_low" ] = sched_setpoints [0 ]
202- device_data ["setpoint_high" ] = sched_setpoints [1 ]
203-
204- device_data .pop ("setpoint" )
205225
206226 # Control_state, only for Adam master thermostats
207227 if ctrl_state := self ._control_state (loc_id ):
@@ -211,9 +231,9 @@ def _device_data_climate(
211231 device_data ["mode" ] = "auto"
212232 if sel_schedule == "None" :
213233 device_data ["mode" ] = "heat"
214- if self ._anna_cooling_present :
234+ if self .elga_cooling_enabled :
215235 device_data ["mode" ] = "heat_cool"
216- if self .smile_name == "Adam" and self ._adam_cooling_enabled :
236+ if self ._adam_cooling_enabled or self .lortherm_cooling_enabled :
217237 device_data ["mode" ] = "cool"
218238
219239 return device_data
@@ -495,6 +515,9 @@ async def async_update(self) -> list[GatewayData | dict[str, DeviceData]]:
495515 notifs ,
496516 )
497517
518+ # After all device data has been determined, add/update for cooling
519+ self .update_for_cooling (self .gw_devices )
520+
498521 return [self .gw_data , self .gw_devices ]
499522
500523 async def _set_schedule_state_legacy (self , name : str , status : str ) -> None :
@@ -616,9 +639,16 @@ async def set_preset(self, loc_id: str, preset: str) -> None:
616639
617640 await self ._request (uri , method = "put" , data = data )
618641
619- async def set_temperature (self , loc_id : str , temperature : float ) -> None :
642+ async def set_temperature (self , loc_id : str , temps : dict [ str , Any ] ) -> None :
620643 """Set the given Temperature on the relevant Thermostat."""
621- temp = str (temperature )
644+ if "setpoint" in temps :
645+ setpoint = temps ["setpoint" ]
646+ elif self ._elga_cooling_active :
647+ setpoint = temps ["setpoint_high" ]
648+ else :
649+ setpoint = temps ["setpoint_low" ]
650+
651+ temp = str (setpoint )
622652 uri = self ._thermostat_uri (loc_id )
623653 data = (
624654 "<thermostat_functionality><setpoint>"
0 commit comments