2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.openwebnet.internal.handler;
15 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*;
17 import java.util.HashSet;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
22 import org.openhab.core.library.types.DecimalType;
23 import org.openhab.core.library.types.OnOffType;
24 import org.openhab.core.library.types.QuantityType;
25 import org.openhab.core.library.types.StringType;
26 import org.openhab.core.library.unit.SIUnits;
27 import org.openhab.core.thing.ChannelUID;
28 import org.openhab.core.thing.Thing;
29 import org.openhab.core.thing.ThingStatus;
30 import org.openhab.core.thing.ThingStatusDetail;
31 import org.openhab.core.thing.ThingTypeUID;
32 import org.openhab.core.types.Command;
33 import org.openhab.core.types.UnDefType;
34 import org.openwebnet4j.communication.OWNException;
35 import org.openwebnet4j.message.BaseOpenMessage;
36 import org.openwebnet4j.message.FrameException;
37 import org.openwebnet4j.message.MalformedFrameException;
38 import org.openwebnet4j.message.Thermoregulation;
39 import org.openwebnet4j.message.Thermoregulation.WhatThermo;
40 import org.openwebnet4j.message.Where;
41 import org.openwebnet4j.message.WhereThermo;
42 import org.openwebnet4j.message.Who;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 * The {@link OpenWebNetThermoregulationHandler} is responsible for handling
48 * commands/messages for Thermoregulation
49 * Things. It extends the abstract {@link OpenWebNetThingHandler}.
51 * @author Massimo Valla - Initial contribution. Added support for 4-zone CU
52 * @author Andrea Conte - Thermoregulation
53 * @author Gilberto Cocchi - Thermoregulation
56 public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
58 private final Logger logger = LoggerFactory.getLogger(OpenWebNetThermoregulationHandler.class);
60 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.THERMOREGULATION_SUPPORTED_THING_TYPES;
62 private double currentSetPointTemp = 11.5d; // 11.5 is the default setTemp used in MyHomeUP mobile app
64 private Thermoregulation.Function currentFunction = Thermoregulation.Function.GENERIC;
65 private Thermoregulation.OperationMode currentMode = Thermoregulation.OperationMode.MANUAL;
67 private boolean isStandAlone = true; // true if zone is not associated to a CU
69 private boolean isCentralUnit = false;
71 private String programNumber = "1";
73 private static Set<String> probesInProtection = new HashSet<String>();
74 private static Set<String> probesInOFF = new HashSet<String>();
75 private static Set<String> probesInManual = new HashSet<String>();
77 private static final String CU_REMOTE_CONTROL_ENABLED = "ENABLED";
78 private static final String CU_REMOTE_CONTROL_DISABLED = "DISABLED";
79 private static final String CU_BATTERY_OK = "OK";
80 private static final String CU_BATTERY_KO = "KO";
81 private static final Integer UNDOCUMENTED_WHAT_4001 = 4001;
82 private static final Integer UNDOCUMENTED_WHAT_4002 = 4002;
84 public OpenWebNetThermoregulationHandler(Thing thing) {
89 public void initialize() {
92 ThingTypeUID thingType = thing.getThingTypeUID();
93 isCentralUnit = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingType);
96 Object standAloneConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE);
97 if (standAloneConfig != null) {
98 isStandAlone = Boolean.parseBoolean(standAloneConfig.toString());
100 logger.debug("@@@@ THERMO ZONE INITIALIZE isStandAlone={}", isStandAlone);
103 // central unit must have WHERE=#0 or WHERE=0 or WHERE=#0#n
104 String w = deviceWhere.value();
105 if (w == null || !("0".equals(w) || "#0".equals(w) || w.startsWith("#0#"))) {
106 logger.warn("initialize() Invalid WHERE={} for Central Unit.", deviceWhere.value());
107 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
108 "@text/offline.conf-error-where");
111 // reset state of signal channels (they will be setted when specific messages
113 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, OnOffType.OFF);
114 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, OnOffType.OFF);
115 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, OnOffType.OFF);
116 updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(programNumber));
117 updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(programNumber));
118 updateState(CHANNEL_CU_FAILURE_DISCOVERED, OnOffType.OFF);
123 protected void handleChannelCommand(ChannelUID channel, Command command) {
124 switch (channel.getId()) {
125 case CHANNEL_TEMP_SETPOINT:
126 handleSetpoint(command);
128 case CHANNEL_FUNCTION:
129 handleFunction(command);
134 case CHANNEL_FAN_SPEED:
135 handleSetFanSpeed(command);
137 case CHANNEL_CU_WEEKLY_PROGRAM_NUMBER:
138 case CHANNEL_CU_SCENARIO_PROGRAM_NUMBER:
139 handleSetProgramNumber(command);
142 logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId());
148 protected void requestChannelState(ChannelUID channel) {
149 super.requestChannelState(channel);
150 refreshDevice(false);
154 protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
155 return new WhereThermo(wStr);
159 protected String ownIdPrefix() {
160 return Who.THERMOREGULATION.value().toString();
163 private void handleSetFanSpeed(Command command) {
164 if (command instanceof StringType) {
165 Where w = deviceWhere;
168 Thermoregulation.FanCoilSpeed speed = Thermoregulation.FanCoilSpeed.valueOf(command.toString());
169 send(Thermoregulation.requestWriteFanCoilSpeed(w.value(), speed));
170 } catch (OWNException e) {
171 logger.warn("handleSetFanSpeed() {}", e.getMessage());
172 } catch (IllegalArgumentException e) {
173 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command,
174 getThing().getUID());
179 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command, getThing().getUID());
183 private void handleSetProgramNumber(Command command) {
184 if (command instanceof DecimalType) {
185 if (!isCentralUnit) {
186 logger.warn("handleSetProgramNumber() This command can be sent only for a Central Unit.");
190 programNumber = command.toString();
191 logger.debug("handleSetProgramNumber() Program number set to {}", programNumber);
193 // force OperationMode update if we are already in SCENARIO o WEEKLY mode
194 if (currentMode.isScenario() || currentMode.isWeekly()) {
196 Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode
197 .valueOf(currentMode.mode() + "_" + programNumber);
198 logger.debug("handleSetProgramNumber() new mode {}", new_mode);
199 send(Thermoregulation.requestWriteMode(getWhere(""), new_mode, currentFunction,
200 currentSetPointTemp));
201 } catch (OWNException e) {
202 logger.warn("handleSetProgramNumber() {}", e.getMessage());
203 } catch (IllegalArgumentException e) {
204 logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command,
205 getThing().getUID());
210 logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command, getThing().getUID());
214 private void handleSetpoint(Command command) {
215 if (command instanceof QuantityType || command instanceof DecimalType) {
216 Where w = deviceWhere;
219 if (command instanceof QuantityType) {
220 QuantityType<?> tempCelsius = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
221 if (tempCelsius != null) {
222 newTemp = tempCelsius.doubleValue();
225 newTemp = ((DecimalType) command).doubleValue();
228 send(Thermoregulation.requestWriteSetpointTemperature(getWhere(w.value()), newTemp,
230 } catch (MalformedFrameException | OWNException e) {
231 logger.warn("handleSetpoint() {}", e.getMessage());
235 logger.warn("handleSetpoint() Unsupported command {} for thing {}", command, getThing().getUID());
239 private void handleMode(Command command) {
240 if (command instanceof StringType) {
241 Where w = deviceWhere;
244 Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode.OFF;
246 if (isCentralUnit && WhatThermo.isComplex(command.toString())) {
247 new_mode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber);
249 // store current mode
250 currentMode = new_mode;
252 new_mode = Thermoregulation.OperationMode.valueOf(command.toString());
254 send(Thermoregulation.requestWriteMode(getWhere(w.value()), new_mode, currentFunction,
255 currentSetPointTemp));
256 } catch (OWNException e) {
257 logger.warn("handleMode() {}", e.getMessage());
258 } catch (IllegalArgumentException e) {
259 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
264 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
268 private String getWhere(String where) {
272 return isStandAlone ? where : "#" + where;
276 private void handleFunction(Command command) {
277 if (command instanceof StringType) {
278 Where w = deviceWhere;
281 Thermoregulation.Function function = Thermoregulation.Function.valueOf(command.toString());
282 send(Thermoregulation.requestWriteFunction(w.value(), function));
283 } catch (OWNException e) {
284 logger.warn("handleFunction() {}", e.getMessage());
285 } catch (IllegalArgumentException e) {
286 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
291 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
296 protected void handleMessage(BaseOpenMessage msg) {
297 super.handleMessage(msg);
299 logger.debug("@@@@ Thermo.handleMessage(): {}", msg.toStringVerbose());
302 if (msg.getWhat() == null) {
306 // there isn't a message used for setting OK for battery status so let's assume
307 // it's OK and then change to KO if according message is received
308 updateCUBatteryStatus(CU_BATTERY_OK);
310 // same in case of Failure Discovered
311 updateCUFailureDiscovered(OnOffType.OFF);
313 if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_DISABLED) {
314 updateCURemoteControlStatus(CU_REMOTE_CONTROL_DISABLED);
315 } else if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_ENABLED) {
316 updateCURemoteControlStatus(CU_REMOTE_CONTROL_ENABLED);
317 } else if (msg.getWhat() == Thermoregulation.WhatThermo.BATTERY_KO) {
318 updateCUBatteryStatus(CU_BATTERY_KO);
319 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_OFF) {
320 updateCUAtLeastOneProbeOff(OnOffType.ON);
321 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_ANTIFREEZE) {
322 updateCUAtLeastOneProbeProtection(OnOffType.ON);
323 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_MANUAL) {
324 updateCUAtLeastOneProbeManual(OnOffType.ON);
325 } else if (msg.getWhat() == Thermoregulation.WhatThermo.FAILURE_DISCOVERED) {
326 updateCUFailureDiscovered(OnOffType.ON);
327 } // must intercept all possibile WHATs
328 else if (msg.getWhat() == Thermoregulation.WhatThermo.RELEASE_SENSOR_LOCAL_ADJUST) { // will be implemented
330 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
331 } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4001) {
332 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
333 } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4002) {
334 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
336 // check and update values of other channel (mode, function, temp)
337 updateModeAndFunction((Thermoregulation) msg);
338 updateSetpoint((Thermoregulation) msg);
343 if (msg.isCommand()) {
344 updateModeAndFunction((Thermoregulation) msg);
346 if (msg.getDim() == null) {
349 if (msg.getDim() == Thermoregulation.DimThermo.TEMPERATURE
350 || msg.getDim() == Thermoregulation.DimThermo.PROBE_TEMPERATURE) {
351 updateTemperature((Thermoregulation) msg);
352 } else if (msg.getDim() == Thermoregulation.DimThermo.TEMP_SETPOINT
353 || msg.getDim() == Thermoregulation.DimThermo.COMPLETE_PROBE_STATUS) {
354 updateSetpoint((Thermoregulation) msg);
355 } else if (msg.getDim() == Thermoregulation.DimThermo.VALVES_STATUS) {
356 updateValveStatus((Thermoregulation) msg);
357 } else if (msg.getDim() == Thermoregulation.DimThermo.ACTUATOR_STATUS) {
358 updateActuatorStatus((Thermoregulation) msg);
359 } else if (msg.getDim() == Thermoregulation.DimThermo.FAN_COIL_SPEED) {
360 updateFanCoilSpeed((Thermoregulation) msg);
361 } else if (msg.getDim() == Thermoregulation.DimThermo.OFFSET) {
362 updateLocalOffset((Thermoregulation) msg);
364 logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", msg.getDim(),
365 getThing().getUID(), msg);
370 private void updateModeAndFunction(Thermoregulation tmsg) {
371 if (tmsg.getWhat() == null) {
372 logger.debug("updateModeAndFunction() Could not parse Mode or Function from {} (what is null)",
373 tmsg.getFrameValue());
376 Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
378 if (w.getMode() == null) {
379 logger.debug("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
383 if (w.getFunction() == null) {
384 logger.debug("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
388 Thermoregulation.OperationMode operationMode = w.getMode();
389 Thermoregulation.Function function = w.getFunction();
391 // keep track of thermostats (zones) status
392 if (!isCentralUnit && (!((WhereThermo) deviceWhere).isProbe())) {
393 if (operationMode == Thermoregulation.OperationMode.OFF) {
394 probesInManual.remove(tmsg.getWhere().value());
395 probesInProtection.remove(tmsg.getWhere().value());
396 if (probesInOFF.add(tmsg.getWhere().value())) {
397 logger.debug("atLeastOneProbeInOFF: added WHERE ---> {}", tmsg.getWhere());
399 } else if (operationMode == Thermoregulation.OperationMode.PROTECTION) {
400 probesInManual.remove(tmsg.getWhere().value());
401 probesInOFF.remove(tmsg.getWhere().value());
402 if (probesInProtection.add(tmsg.getWhere().value())) {
403 logger.debug("atLeastOneProbeInProtection: added WHERE ---> {}", tmsg.getWhere());
405 } else if (operationMode == Thermoregulation.OperationMode.MANUAL) {
406 probesInProtection.remove(tmsg.getWhere().value());
407 probesInOFF.remove(tmsg.getWhere().value());
408 if (probesInManual.add(tmsg.getWhere().value())) {
409 logger.debug("atLeastOneProbeInManual: added WHERE ---> {}", tmsg.getWhere());
413 if (probesInOFF.isEmpty()) {
414 updateCUAtLeastOneProbeOff(OnOffType.OFF);
416 if (probesInProtection.isEmpty()) {
417 updateCUAtLeastOneProbeProtection(OnOffType.OFF);
419 if (probesInManual.isEmpty()) {
420 updateCUAtLeastOneProbeManual(OnOffType.OFF);
424 updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
426 // must convert from OperationMode to Mode and set ProgramNumber when necessary
427 updateState(CHANNEL_MODE, new StringType(operationMode.mode()));
428 if (operationMode.isScenario()) {
429 logger.debug("updateModeAndFunction() set SCENARIO program to: {}", operationMode.programNumber());
430 updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
432 if (operationMode.isWeekly()) {
433 logger.debug("updateModeAndFunction() set WEEKLY program to: {}", operationMode.programNumber());
434 updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
437 // store current function
438 currentFunction = function;
440 // in case of central unit store also current operation mode
442 currentMode = operationMode;
446 private void updateTemperature(Thermoregulation tmsg) {
448 double temp = Thermoregulation.parseTemperature(tmsg);
449 updateState(CHANNEL_TEMPERATURE, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
450 } catch (FrameException e) {
451 logger.warn("updateTemperature() FrameException on frame {}: {}", tmsg, e.getMessage());
452 updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF);
456 private void updateSetpoint(Thermoregulation tmsg) {
460 if (tmsg.getWhat() == null) {
461 // it should be like *4*WHAT#TTTT*#0##
462 logger.debug("updateSetpoint() Could not parse function from {} (what is null)",
463 tmsg.getFrameValue());
467 String[] parameters = tmsg.getWhatParams();
468 if (parameters.length > 0) {
469 temp = Thermoregulation.decodeTemperature(parameters[0]);
470 logger.debug("updateSetpoint() parsed temperature from {}: {} ---> {}", tmsg.toStringVerbose(),
471 parameters[0], temp);
474 temp = Thermoregulation.parseTemperature(tmsg);
476 updateState(CHANNEL_TEMP_SETPOINT, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
477 currentSetPointTemp = temp;
478 } catch (NumberFormatException e) {
479 logger.warn("updateSetpoint() NumberFormatException on frame {}: {}", tmsg, e.getMessage());
480 updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
481 } catch (FrameException e) {
482 logger.warn("updateSetpoint() FrameException on frame {}: {}", tmsg, e.getMessage());
483 updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
487 private void updateFanCoilSpeed(Thermoregulation tmsg) {
489 Thermoregulation.FanCoilSpeed speed = Thermoregulation.parseFanCoilSpeed(tmsg);
490 updateState(CHANNEL_FAN_SPEED, new StringType(speed.toString()));
491 } catch (FrameException e) {
492 logger.warn("updateFanCoilSpeed() FrameException on frame {}: {}", tmsg, e.getMessage());
493 updateState(CHANNEL_FAN_SPEED, UnDefType.UNDEF);
497 private void updateValveStatus(Thermoregulation tmsg) {
499 Thermoregulation.ValveOrActuatorStatus cv = Thermoregulation.parseValveStatus(tmsg,
500 Thermoregulation.WhatThermo.CONDITIONING);
501 updateState(CHANNEL_CONDITIONING_VALVES, new StringType(cv.toString()));
503 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseValveStatus(tmsg,
504 Thermoregulation.WhatThermo.HEATING);
505 updateState(CHANNEL_HEATING_VALVES, new StringType(hv.toString()));
506 } catch (FrameException e) {
507 logger.warn("updateValveStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
508 updateState(CHANNEL_CONDITIONING_VALVES, UnDefType.UNDEF);
509 updateState(CHANNEL_HEATING_VALVES, UnDefType.UNDEF);
513 private void updateActuatorStatus(Thermoregulation tmsg) {
515 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseActuatorStatus(tmsg);
516 updateState(CHANNEL_ACTUATORS, new StringType(hv.toString()));
517 } catch (FrameException e) {
518 logger.warn("updateActuatorStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
519 updateState(CHANNEL_ACTUATORS, UnDefType.UNDEF);
523 private void updateLocalOffset(Thermoregulation tmsg) {
525 Thermoregulation.LocalOffset offset = Thermoregulation.parseLocalOffset(tmsg);
526 updateState(CHANNEL_LOCAL_OFFSET, new StringType(offset.toString()));
527 logger.debug("updateLocalOffset() {}: {}", tmsg, offset.toString());
529 } catch (FrameException e) {
530 logger.warn("updateLocalOffset() FrameException on frame {}: {}", tmsg, e.getMessage());
531 updateState(CHANNEL_LOCAL_OFFSET, UnDefType.UNDEF);
535 private void updateCURemoteControlStatus(String status) {
536 updateState(CHANNEL_CU_REMOTE_CONTROL, new StringType(status));
537 logger.debug("updateCURemoteControlStatus(): {}", status);
540 private void updateCUBatteryStatus(String status) {
541 updateState(CHANNEL_CU_BATTERY_STATUS, new StringType(status));
543 if (status == CU_BATTERY_KO) { // do not log default value (which is automatically setted)
544 logger.debug("updateCUBatteryStatus(): {}", status);
548 private void updateCUFailureDiscovered(OnOffType status) {
549 updateState(CHANNEL_CU_FAILURE_DISCOVERED, status);
551 if (status == OnOffType.ON) { // do not log default value (which is automatically setted)
552 logger.debug("updateCUFailureDiscovered(): {}", status);
556 private void updateCUAtLeastOneProbeOff(OnOffType status) {
557 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, status);
558 logger.debug("updateCUAtLeastOneProbeOff(): {}", status);
561 private void updateCUAtLeastOneProbeProtection(OnOffType status) {
562 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, status);
563 logger.debug("updateCUAtLeastOneProbeProtection(): {}", status);
566 private void updateCUAtLeastOneProbeManual(OnOffType status) {
567 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, status);
568 logger.debug("updateCUAtLeastOneProbeManual(): {}", status);
571 private Boolean channelExists(String channelID) {
572 return thing.getChannel(channelID) != null;
576 protected void refreshDevice(boolean refreshAll) {
577 logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
579 if (deviceWhere != null) {
580 String w = deviceWhere.value();
583 // TODO: 4 zone central -> zone #0 CAN be also a zone with its temp.. with
584 // 99-zones central no! let's assume it's a 99 zone
586 send(Thermoregulation.requestStatus(w));
587 } catch (OWNException e) {
588 logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage());
594 send(Thermoregulation.requestTemperature(w));
596 if (!((WhereThermo) deviceWhere).isProbe()) {
597 // for bus_thermo_zone request also other single channels updates
598 send(Thermoregulation.requestSetPointTemperature(w));
599 send(Thermoregulation.requestMode(w));
601 // refresh ONLY subscribed channels
602 if (channelExists(CHANNEL_FAN_SPEED)) {
603 send(Thermoregulation.requestFanCoilSpeed(w));
606 if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) {
607 send(Thermoregulation.requestValvesStatus(w));
610 if (channelExists(CHANNEL_ACTUATORS)) {
611 send(Thermoregulation.requestActuatorsStatus(w));
614 if (channelExists(CHANNEL_LOCAL_OFFSET)) {
615 send(Thermoregulation.requestLocalOffset(w));
618 } catch (OWNException e) {
619 logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage());
622 logger.debug("refreshDevice() where is null");