4343_ZONE_INT_MODE_COOL_THERMOSTAT = 3
4444_ZONE_INT_MODE_COOL_FLOW = 4
4545
46- ZONE_OPERATION_MODE_HEAT = "heat"
47- ZONE_OPERATION_MODE_COOL = "cool"
46+ ZONE_OPERATION_MODE_HEAT_THERMOSTAT = "heat-thermostat"
47+ ZONE_OPERATION_MODE_COOL_THERMOSTAT = "cool-thermostat"
48+ ZONE_OPERATION_MODE_HEAT_FLOW = "heat-flow"
49+ ZONE_OPERATION_MODE_COOL_FLOW = "cool-flow"
50+ ZONE_OPERATION_MODE_CURVE = "curve"
4851ZONE_OPERATION_MODE_UNKNOWN = "unknown"
4952_ZONE_OPERATION_MODE_LOOKUP = {
50- _ZONE_INT_MODE_HEAT_THERMOSTAT : ZONE_OPERATION_MODE_HEAT ,
51- _ZONE_INT_MODE_HEAT_FLOW : ZONE_OPERATION_MODE_HEAT ,
52- _ZONE_INT_MODE_CURVE : ZONE_OPERATION_MODE_HEAT ,
53- _ZONE_INT_MODE_COOL_THERMOSTAT : ZONE_OPERATION_MODE_COOL ,
54- _ZONE_INT_MODE_COOL_FLOW : ZONE_OPERATION_MODE_COOL ,
53+ _ZONE_INT_MODE_HEAT_THERMOSTAT : ZONE_OPERATION_MODE_HEAT_THERMOSTAT ,
54+ _ZONE_INT_MODE_HEAT_FLOW : ZONE_OPERATION_MODE_HEAT_FLOW ,
55+ _ZONE_INT_MODE_CURVE : ZONE_OPERATION_MODE_CURVE ,
56+ _ZONE_INT_MODE_COOL_THERMOSTAT : ZONE_OPERATION_MODE_COOL_THERMOSTAT ,
57+ _ZONE_INT_MODE_COOL_FLOW : ZONE_OPERATION_MODE_COOL_FLOW ,
58+ }
59+ _REVERSE_ZONE_OPERATION_MODE_LOOKUP = {
60+ value : key for key , value in _ZONE_OPERATION_MODE_LOOKUP .items ()
5561}
5662
57- ZONE_STATUS_HEAT = ZONE_OPERATION_MODE_HEAT
63+ ZONE_STATUS_HEAT = "heat"
5864ZONE_STATUS_IDLE = "idle"
59- ZONE_STATUS_COOL = ZONE_OPERATION_MODE_COOL
65+ ZONE_STATUS_COOL = "cool"
6066ZONE_STATUS_UNKNOWN = "unknown"
6167
6268
@@ -110,9 +116,16 @@ def status(self) -> str:
110116 return ZONE_STATUS_IDLE
111117
112118 op_mode = self .operation_mode
113- if op_mode == ZONE_OPERATION_MODE_HEAT :
119+ if op_mode in [
120+ ZONE_OPERATION_MODE_HEAT_THERMOSTAT ,
121+ ZONE_OPERATION_MODE_HEAT_FLOW ,
122+ ZONE_OPERATION_MODE_CURVE ,
123+ ]:
114124 return ZONE_STATUS_HEAT
115- if op_mode == ZONE_OPERATION_MODE_COOL :
125+ if op_mode in [
126+ ZONE_OPERATION_MODE_COOL_THERMOSTAT ,
127+ ZONE_OPERATION_MODE_COOL_FLOW ,
128+ ]:
116129 return ZONE_STATUS_COOL
117130
118131 return ZONE_STATUS_UNKNOWN
@@ -166,9 +179,13 @@ def target_flow_temperature(self) -> Optional[float]:
166179 if op_mode is None :
167180 return None
168181
169- if op_mode == ZONE_OPERATION_MODE_HEAT :
170- return self .target_heat_flow_temperature
171- return self .target_cool_flow_temperature
182+ if op_mode in [
183+ ZONE_OPERATION_MODE_COOL_THERMOSTAT ,
184+ ZONE_OPERATION_MODE_COOL_FLOW ,
185+ ]:
186+ return self .target_cool_flow_temperature
187+
188+ return self .target_heat_flow_temperature
172189
173190 @property
174191 def target_heat_flow_temperature (self ) -> Optional [float ]:
@@ -194,10 +211,13 @@ async def set_target_flow_temperature(self, target_flow_temperature):
194211 if op_mode is None :
195212 return None
196213
197- if op_mode == ZONE_OPERATION_MODE_HEAT :
198- await self .set_target_heat_flow_temperature (target_flow_temperature )
199- else :
214+ if op_mode in [
215+ ZONE_OPERATION_MODE_COOL_THERMOSTAT ,
216+ ZONE_OPERATION_MODE_COOL_FLOW ,
217+ ]:
200218 await self .set_target_cool_flow_temperature (target_flow_temperature )
219+ else :
220+ await self .set_target_heat_flow_temperature (target_flow_temperature )
201221
202222 async def set_target_heat_flow_temperature (self , target_flow_temperature ):
203223 """Set target heat flow temperature of this zone."""
@@ -217,13 +237,7 @@ async def set_target_cool_flow_temperature(self, target_flow_temperature):
217237
218238 @property
219239 def operation_mode (self ) -> Optional [str ]:
220- """Return current operation mode.
221-
222- This value is not backed by "OperationMode" property of the zone. MELCloud
223- uses "OperationMode" for the temperature control mode ("Room", "Flow",
224- "Curve"). Instead this property indicates whether the device is set to heat
225- or cool.
226- """
240+ """Return current operation mode."""
227241 state = self ._device_state ()
228242 if state is None :
229243 return None
@@ -235,16 +249,20 @@ def operation_mode(self) -> Optional[str]:
235249
236250 @property
237251 def operation_modes (self ) -> List [str ]:
238- """Return list of available operation modes.
239-
240- This value is not backed by "OperationMode" property of the zone. MELCloud
241- uses "OperationMode" for the temperature control mode ("Room", "Flow",
242- "Curve"). Instead this property indicates whether the device is set to heat
243- or cool.
244- """
245- modes = [ZONE_OPERATION_MODE_HEAT ]
246- if self ._device_conf ().get ("Device" , {}).get ("CanCool" , False ):
247- modes .append (ZONE_OPERATION_MODE_COOL )
252+ """Return list of available operation modes."""
253+ modes = []
254+ device = self ._device_conf ().get ("Device" , {})
255+ if device .get ("CanHeat" , False ):
256+ modes += [
257+ ZONE_OPERATION_MODE_HEAT_THERMOSTAT ,
258+ ZONE_OPERATION_MODE_HEAT_FLOW ,
259+ ZONE_OPERATION_MODE_CURVE ,
260+ ]
261+ if device .get ("CanCool" , False ):
262+ modes += [
263+ ZONE_OPERATION_MODE_COOL_THERMOSTAT ,
264+ ZONE_OPERATION_MODE_COOL_FLOW ,
265+ ]
248266 return modes
249267
250268 async def set_operation_mode (self , mode : str ):
@@ -253,7 +271,16 @@ async def set_operation_mode(self, mode: str):
253271 if state is None :
254272 return
255273
256- raise ValueError ("Not implemented" )
274+ int_mode = _REVERSE_ZONE_OPERATION_MODE_LOOKUP .get (mode )
275+ if int_mode is None :
276+ raise ValueError (f"Invalid mode '{ mode } '" )
277+
278+ if self .zone_index == 1 :
279+ prop = PROPERTY_ZONE_1_OPERATION_MODE
280+ else :
281+ prop = PROPERTY_ZONE_2_OPERATION_MODE
282+
283+ await self ._device .set ({prop : int_mode })
257284
258285
259286class AtwDevice (Device ):
@@ -265,36 +292,34 @@ def apply_write(self, state: Dict[str, Any], key: str, value: Any):
265292
266293 if key == PROPERTY_TARGET_TANK_TEMPERATURE :
267294 state ["SetTankWaterTemperature" ] = value
268- flags = flags | 0x1000000000020
295+ flags |= 0x1000000000020
269296 elif key == PROPERTY_OPERATION_MODE :
270297 state ["ForcedHotWaterMode" ] = value == OPERATION_MODE_FORCE_HOT_WATER
271- flags = flags | 0x10000
298+ flags |= 0x10000
272299 elif key == PROPERTY_ZONE_1_TARGET_TEMPERATURE :
273300 state ["SetTemperatureZone1" ] = value
274- flags = flags | 0x200000080
301+ flags |= 0x200000080
275302 elif key == PROPERTY_ZONE_2_TARGET_TEMPERATURE :
276303 state ["SetTemperatureZone2" ] = value
277- flags = flags | 0x800000200
304+ flags |= 0x800000200
278305 elif key == PROPERTY_ZONE_1_TARGET_HEAT_FLOW_TEMPERATURE :
279306 state ["SetHeatFlowTemperatureZone1" ] = value
280- flags = flags | 0x1000000000000
307+ flags |= 0x1000000000000
281308 elif key == PROPERTY_ZONE_1_TARGET_COOL_FLOW_TEMPERATURE :
282309 state ["SetCoolFlowTemperatureZone1" ] = value
283- flags = flags | 0x1000000000000
310+ flags |= 0x1000000000000
284311 elif key == PROPERTY_ZONE_2_TARGET_HEAT_FLOW_TEMPERATURE :
285312 state ["SetHeatFlowTemperatureZone2" ] = value
286- flags = flags | 0x1000000000000
313+ flags |= 0x1000000000000
287314 elif key == PROPERTY_ZONE_2_TARGET_COOL_FLOW_TEMPERATURE :
288315 state ["SetCoolFlowTemperatureZone2" ] = value
289- flags = flags | 0x1000000000000
316+ flags |= 0x1000000000000
290317 elif key == PROPERTY_ZONE_1_OPERATION_MODE :
291- # Captures required to implement
292- # 0x08
293- pass
318+ state ["OperationModeZone1" ] = value
319+ flags |= 0x08
294320 elif key == PROPERTY_ZONE_2_OPERATION_MODE :
295- # Captures required to implement
296- # 0x10
297- pass
321+ state ["OperationModeZone2" ] = value
322+ flags |= 0x10
298323 else :
299324 raise ValueError (f"Cannot set { key } , invalid property" )
300325
0 commit comments