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.CHANNEL_ACTUATORS;
16 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CONDITIONING_VALVES;
17 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL;
18 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF;
19 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION;
20 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_BATTERY_STATUS;
21 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_FAILURE_DISCOVERED;
22 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_REMOTE_CONTROL;
23 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_SCENARIO_PROGRAM_NUMBER;
24 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_CU_WEEKLY_PROGRAM_NUMBER;
25 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_FAN_SPEED;
26 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_FUNCTION;
27 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_HEATING_VALVES;
28 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_LOCAL_OFFSET;
29 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_MODE;
30 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_TEMPERATURE;
31 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.CHANNEL_TEMP_SETPOINT;
33 import java.util.HashSet;
36 import org.eclipse.jdt.annotation.NonNullByDefault;
37 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
38 import org.openhab.core.library.types.DecimalType;
39 import org.openhab.core.library.types.OnOffType;
40 import org.openhab.core.library.types.QuantityType;
41 import org.openhab.core.library.types.StringType;
42 import org.openhab.core.library.unit.SIUnits;
43 import org.openhab.core.thing.ChannelUID;
44 import org.openhab.core.thing.Thing;
45 import org.openhab.core.thing.ThingStatus;
46 import org.openhab.core.thing.ThingStatusDetail;
47 import org.openhab.core.thing.ThingTypeUID;
48 import org.openhab.core.types.Command;
49 import org.openhab.core.types.UnDefType;
50 import org.openwebnet4j.communication.OWNException;
51 import org.openwebnet4j.message.BaseOpenMessage;
52 import org.openwebnet4j.message.FrameException;
53 import org.openwebnet4j.message.MalformedFrameException;
54 import org.openwebnet4j.message.Thermoregulation;
55 import org.openwebnet4j.message.Thermoregulation.WhatThermo;
56 import org.openwebnet4j.message.Where;
57 import org.openwebnet4j.message.WhereThermo;
58 import org.openwebnet4j.message.Who;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
63 * The {@link OpenWebNetThermoregulationHandler} is responsible for handling commands/messages for Thermoregulation
64 * Things. It extends the abstract {@link OpenWebNetThingHandler}.
66 * @author Massimo Valla - Initial contribution
67 * @author Andrea Conte - Thermoregulation
68 * @author Gilberto Cocchi - Thermoregulation
71 public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
73 private final Logger logger = LoggerFactory.getLogger(OpenWebNetThermoregulationHandler.class);
75 public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.THERMOREGULATION_SUPPORTED_THING_TYPES;
77 private double currentSetPointTemp = 11.5d; // 11.5 is the default setTemp used in MyHomeUP mobile app
79 private Thermoregulation.Function currentFunction = Thermoregulation.Function.GENERIC;
80 private Thermoregulation.OperationMode currentMode = Thermoregulation.OperationMode.MANUAL;
82 private boolean isStandAlone = false;
84 private boolean isCentralUnit = false;
86 private String programNumber = "1";
88 private static Set<String> probesInProtection = new HashSet<String>();
89 private static Set<String> probesInOFF = new HashSet<String>();
90 private static Set<String> probesInManual = new HashSet<String>();
92 private static final String CU_REMOTE_CONTROL_ENABLED = "ENABLED";
93 private static final String CU_REMOTE_CONTROL_DISABLED = "DISABLED";
94 private static final String CU_BATTERY_OK = "OK";
95 private static final String CU_BATTERY_KO = "KO";
96 private static final Integer UNDOCUMENTED_WHAT_4001 = 4001;
97 private static final Integer UNDOCUMENTED_WHAT_4002 = 4002;
99 public OpenWebNetThermoregulationHandler(Thing thing) {
104 public void initialize() {
107 ThingTypeUID thingType = thing.getThingTypeUID();
108 isCentralUnit = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingType);
110 if (!isCentralUnit) {
111 Object standAloneConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE);
112 if (standAloneConfig != null) {
113 // null in case of thermo_sensor
114 isStandAlone = Boolean.parseBoolean(standAloneConfig.toString());
117 // central unit must have WHERE=0
118 if (!deviceWhere.value().equals("0")) {
119 logger.warn("initialize() Invalid WHERE={} for Central Unit.", deviceWhere.value());
121 updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
122 "@text/offline.conf-error-where");
125 // reset state of signal channels (they will be setted when specific messages are received)
126 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, OnOffType.OFF);
127 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, OnOffType.OFF);
128 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, OnOffType.OFF);
129 updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(programNumber));
130 updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(programNumber));
131 updateState(CHANNEL_CU_FAILURE_DISCOVERED, OnOffType.OFF);
136 protected void handleChannelCommand(ChannelUID channel, Command command) {
137 switch (channel.getId()) {
138 case CHANNEL_TEMP_SETPOINT:
139 handleSetpoint(command);
141 case CHANNEL_FUNCTION:
142 handleFunction(command);
147 case CHANNEL_FAN_SPEED:
148 handleSetFanSpeed(command);
150 case CHANNEL_CU_WEEKLY_PROGRAM_NUMBER:
151 case CHANNEL_CU_SCENARIO_PROGRAM_NUMBER:
152 handleSetProgramNumber(command);
155 logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId());
161 protected void requestChannelState(ChannelUID channel) {
162 super.requestChannelState(channel);
163 refreshDevice(false);
167 protected Where buildBusWhere(String wStr) throws IllegalArgumentException {
168 return new WhereThermo(wStr);
172 protected String ownIdPrefix() {
173 return Who.THERMOREGULATION.value().toString();
176 private void handleSetFanSpeed(Command command) {
177 if (command instanceof StringType) {
178 Where w = deviceWhere;
181 Thermoregulation.FanCoilSpeed speed = Thermoregulation.FanCoilSpeed.valueOf(command.toString());
182 send(Thermoregulation.requestWriteFanCoilSpeed(w.value(), speed));
183 } catch (OWNException e) {
184 logger.warn("handleSetFanSpeed() {}", e.getMessage());
185 } catch (IllegalArgumentException e) {
186 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command,
187 getThing().getUID());
192 logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command, getThing().getUID());
196 private void handleSetProgramNumber(Command command) {
197 if (command instanceof DecimalType) {
198 if (!isCentralUnit) {
199 logger.warn("handleSetProgramNumber() This command can be sent only for a Central Unit.");
203 programNumber = command.toString();
204 logger.debug("handleSetProgramNumber() Program number set to {}", programNumber);
206 // force OperationMode update if we are already in SCENARIO o WEEKLY mode
207 if (currentMode.isScenario() || currentMode.isWeekly()) {
209 Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode
210 .valueOf(currentMode.mode() + "_" + programNumber);
211 logger.debug("handleSetProgramNumber() new mode {}", new_mode);
212 send(Thermoregulation.requestWriteMode(getWhere(""), new_mode, currentFunction,
213 currentSetPointTemp));
214 } catch (OWNException e) {
215 logger.warn("handleSetProgramNumber() {}", e.getMessage());
216 } catch (IllegalArgumentException e) {
217 logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command,
218 getThing().getUID());
223 logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command, getThing().getUID());
227 private void handleSetpoint(Command command) {
228 if (command instanceof QuantityType || command instanceof DecimalType) {
229 Where w = deviceWhere;
232 if (command instanceof QuantityType) {
233 QuantityType<?> tempCelsius = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
234 if (tempCelsius != null) {
235 newTemp = tempCelsius.doubleValue();
238 newTemp = ((DecimalType) command).doubleValue();
241 send(Thermoregulation.requestWriteSetpointTemperature(getWhere(w.value()), newTemp,
243 } catch (MalformedFrameException | OWNException e) {
244 logger.warn("handleSetpoint() {}", e.getMessage());
248 logger.warn("handleSetpoint() Unsupported command {} for thing {}", command, getThing().getUID());
252 private void handleMode(Command command) {
253 if (command instanceof StringType) {
254 Where w = deviceWhere;
257 Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode.OFF;
259 if (isCentralUnit && WhatThermo.isComplex(command.toString())) {
260 new_mode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber);
262 // store current mode
263 currentMode = new_mode;
265 new_mode = Thermoregulation.OperationMode.valueOf(command.toString());
267 send(Thermoregulation.requestWriteMode(getWhere(w.value()), new_mode, currentFunction,
268 currentSetPointTemp));
269 } catch (OWNException e) {
270 logger.warn("handleMode() {}", e.getMessage());
271 } catch (IllegalArgumentException e) {
272 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
277 logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
281 private String getWhere(String where) {
285 return isStandAlone ? where : "#" + where;
289 private void handleFunction(Command command) {
290 if (command instanceof StringType) {
291 Where w = deviceWhere;
294 Thermoregulation.Function function = Thermoregulation.Function.valueOf(command.toString());
295 send(Thermoregulation.requestWriteFunction(w.value(), function));
296 } catch (OWNException e) {
297 logger.warn("handleFunction() {}", e.getMessage());
298 } catch (IllegalArgumentException e) {
299 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
304 logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
309 protected void handleMessage(BaseOpenMessage msg) {
310 super.handleMessage(msg);
313 if (msg.getWhat() == null) {
317 // there isn't a message used for setting OK for battery status so let's assume
318 // it's OK and then change to KO if according message is received
319 updateCUBatteryStatus(CU_BATTERY_OK);
321 // same in case of Failure Discovered
322 updateCUFailureDiscovered(OnOffType.OFF);
324 if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_DISABLED) {
325 updateCURemoteControlStatus(CU_REMOTE_CONTROL_DISABLED);
326 } else if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_ENABLED) {
327 updateCURemoteControlStatus(CU_REMOTE_CONTROL_ENABLED);
328 } else if (msg.getWhat() == Thermoregulation.WhatThermo.BATTERY_KO) {
329 updateCUBatteryStatus(CU_BATTERY_KO);
330 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_OFF) {
331 updateCUAtLeastOneProbeOff(OnOffType.ON);
332 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_ANTIFREEZE) {
333 updateCUAtLeastOneProbeProtection(OnOffType.ON);
334 } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_MANUAL) {
335 updateCUAtLeastOneProbeManual(OnOffType.ON);
336 } else if (msg.getWhat() == Thermoregulation.WhatThermo.FAILURE_DISCOVERED) {
337 updateCUFailureDiscovered(OnOffType.ON);
338 } // must intercept all possibile WHATs
339 else if (msg.getWhat() == Thermoregulation.WhatThermo.RELEASE_SENSOR_LOCAL_ADJUST) { // will be implemented
341 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
342 } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4001) {
343 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
344 } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4002) {
345 logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
347 // check and update values of other channel (mode, function, temp)
348 updateModeAndFunction((Thermoregulation) msg);
349 updateSetpoint((Thermoregulation) msg);
354 if (msg.isCommand()) {
355 updateModeAndFunction((Thermoregulation) msg);
357 if (msg.getDim() == null) {
360 if (msg.getDim() == Thermoregulation.DimThermo.TEMPERATURE
361 || msg.getDim() == Thermoregulation.DimThermo.PROBE_TEMPERATURE) {
362 updateTemperature((Thermoregulation) msg);
363 } else if (msg.getDim() == Thermoregulation.DimThermo.TEMP_SETPOINT
364 || msg.getDim() == Thermoregulation.DimThermo.COMPLETE_PROBE_STATUS) {
365 updateSetpoint((Thermoregulation) msg);
366 } else if (msg.getDim() == Thermoregulation.DimThermo.VALVES_STATUS) {
367 updateValveStatus((Thermoregulation) msg);
368 } else if (msg.getDim() == Thermoregulation.DimThermo.ACTUATOR_STATUS) {
369 updateActuatorStatus((Thermoregulation) msg);
370 } else if (msg.getDim() == Thermoregulation.DimThermo.FAN_COIL_SPEED) {
371 updateFanCoilSpeed((Thermoregulation) msg);
372 } else if (msg.getDim() == Thermoregulation.DimThermo.OFFSET) {
373 updateLocalOffset((Thermoregulation) msg);
375 logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", msg.getDim(),
376 getThing().getUID(), msg);
381 private void updateModeAndFunction(Thermoregulation tmsg) {
382 if (tmsg.getWhat() == null) {
383 logger.debug("updateModeAndFunction() Could not parse Mode or Function from {} (what is null)",
384 tmsg.getFrameValue());
387 Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
389 if (w.getMode() == null) {
390 logger.debug("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
394 if (w.getFunction() == null) {
395 logger.debug("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
399 Thermoregulation.OperationMode operationMode = w.getMode();
400 Thermoregulation.Function function = w.getFunction();
402 // keep track of thermostats (zones) status
403 if (!isCentralUnit && (!((WhereThermo) deviceWhere).isProbe())) {
404 if (operationMode == Thermoregulation.OperationMode.OFF) {
405 probesInManual.remove(tmsg.getWhere().value());
406 probesInProtection.remove(tmsg.getWhere().value());
407 if (probesInOFF.add(tmsg.getWhere().value())) {
408 logger.debug("atLeastOneProbeInOFF: added WHERE ---> {}", tmsg.getWhere());
410 } else if (operationMode == Thermoregulation.OperationMode.PROTECTION) {
411 probesInManual.remove(tmsg.getWhere().value());
412 probesInOFF.remove(tmsg.getWhere().value());
413 if (probesInProtection.add(tmsg.getWhere().value())) {
414 logger.debug("atLeastOneProbeInProtection: added WHERE ---> {}", tmsg.getWhere());
416 } else if (operationMode == Thermoregulation.OperationMode.MANUAL) {
417 probesInProtection.remove(tmsg.getWhere().value());
418 probesInOFF.remove(tmsg.getWhere().value());
419 if (probesInManual.add(tmsg.getWhere().value())) {
420 logger.debug("atLeastOneProbeInManual: added WHERE ---> {}", tmsg.getWhere());
424 if (probesInOFF.isEmpty()) {
425 updateCUAtLeastOneProbeOff(OnOffType.OFF);
427 if (probesInProtection.isEmpty()) {
428 updateCUAtLeastOneProbeProtection(OnOffType.OFF);
430 if (probesInManual.isEmpty()) {
431 updateCUAtLeastOneProbeManual(OnOffType.OFF);
435 updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
437 // must convert from OperationMode to Mode and set ProgramNumber when necessary
438 updateState(CHANNEL_MODE, new StringType(operationMode.mode()));
439 if (operationMode.isScenario()) {
440 logger.debug("updateModeAndFunction() set SCENARIO program to: {}", operationMode.programNumber());
441 updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
443 if (operationMode.isWeekly()) {
444 logger.debug("updateModeAndFunction() set WEEKLY program to: {}", operationMode.programNumber());
445 updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
448 // store current function
449 currentFunction = function;
451 // in case of central unit store also current operation mode
453 currentMode = operationMode;
457 private void updateTemperature(Thermoregulation tmsg) {
459 double temp = Thermoregulation.parseTemperature(tmsg);
460 updateState(CHANNEL_TEMPERATURE, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
461 } catch (FrameException e) {
462 logger.warn("updateTemperature() FrameException on frame {}: {}", tmsg, e.getMessage());
463 updateState(CHANNEL_TEMPERATURE, UnDefType.UNDEF);
467 private void updateSetpoint(Thermoregulation tmsg) {
471 if (tmsg.getWhat() == null) {
472 // it should be like *4*WHAT#TTTT*#0##
473 logger.debug("updateSetpoint() Could not parse function from {} (what is null)",
474 tmsg.getFrameValue());
478 String[] parameters = tmsg.getWhatParams();
479 if (parameters.length > 0) {
480 temp = Thermoregulation.decodeTemperature(parameters[0]);
481 logger.debug("updateSetpoint() parsed temperature from {}: {} ---> {}", tmsg.toStringVerbose(),
482 parameters[0], temp);
485 temp = Thermoregulation.parseTemperature(tmsg);
487 updateState(CHANNEL_TEMP_SETPOINT, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
488 currentSetPointTemp = temp;
489 } catch (NumberFormatException e) {
490 logger.warn("updateSetpoint() NumberFormatException on frame {}: {}", tmsg, e.getMessage());
491 updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
492 } catch (FrameException e) {
493 logger.warn("updateSetpoint() FrameException on frame {}: {}", tmsg, e.getMessage());
494 updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
498 private void updateFanCoilSpeed(Thermoregulation tmsg) {
500 Thermoregulation.FanCoilSpeed speed = Thermoregulation.parseFanCoilSpeed(tmsg);
501 updateState(CHANNEL_FAN_SPEED, new StringType(speed.toString()));
502 } catch (FrameException e) {
503 logger.warn("updateFanCoilSpeed() FrameException on frame {}: {}", tmsg, e.getMessage());
504 updateState(CHANNEL_FAN_SPEED, UnDefType.UNDEF);
508 private void updateValveStatus(Thermoregulation tmsg) {
510 Thermoregulation.ValveOrActuatorStatus cv = Thermoregulation.parseValveStatus(tmsg,
511 Thermoregulation.WhatThermo.CONDITIONING);
512 updateState(CHANNEL_CONDITIONING_VALVES, new StringType(cv.toString()));
514 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseValveStatus(tmsg,
515 Thermoregulation.WhatThermo.HEATING);
516 updateState(CHANNEL_HEATING_VALVES, new StringType(hv.toString()));
517 } catch (FrameException e) {
518 logger.warn("updateValveStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
519 updateState(CHANNEL_CONDITIONING_VALVES, UnDefType.UNDEF);
520 updateState(CHANNEL_HEATING_VALVES, UnDefType.UNDEF);
524 private void updateActuatorStatus(Thermoregulation tmsg) {
526 Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseActuatorStatus(tmsg);
527 updateState(CHANNEL_ACTUATORS, new StringType(hv.toString()));
528 } catch (FrameException e) {
529 logger.warn("updateActuatorStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
530 updateState(CHANNEL_ACTUATORS, UnDefType.UNDEF);
534 private void updateLocalOffset(Thermoregulation tmsg) {
536 Thermoregulation.LocalOffset offset = Thermoregulation.parseLocalOffset(tmsg);
537 updateState(CHANNEL_LOCAL_OFFSET, new StringType(offset.toString()));
538 logger.debug("updateLocalOffset() {}: {}", tmsg, offset.toString());
540 } catch (FrameException e) {
541 logger.warn("updateLocalOffset() FrameException on frame {}: {}", tmsg, e.getMessage());
542 updateState(CHANNEL_LOCAL_OFFSET, UnDefType.UNDEF);
546 private void updateCURemoteControlStatus(String status) {
547 updateState(CHANNEL_CU_REMOTE_CONTROL, new StringType(status));
548 logger.debug("updateCURemoteControlStatus(): {}", status);
551 private void updateCUBatteryStatus(String status) {
552 updateState(CHANNEL_CU_BATTERY_STATUS, new StringType(status));
554 if (status == CU_BATTERY_KO) { // do not log default value (which is automatically setted)
555 logger.debug("updateCUBatteryStatus(): {}", status);
559 private void updateCUFailureDiscovered(OnOffType status) {
560 updateState(CHANNEL_CU_FAILURE_DISCOVERED, status);
562 if (status == OnOffType.ON) { // do not log default value (which is automatically setted)
563 logger.debug("updateCUFailureDiscovered(): {}", status);
567 private void updateCUAtLeastOneProbeOff(OnOffType status) {
568 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, status);
569 logger.debug("updateCUAtLeastOneProbeOff(): {}", status);
572 private void updateCUAtLeastOneProbeProtection(OnOffType status) {
573 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, status);
574 logger.debug("updateCUAtLeastOneProbeProtection(): {}", status);
577 private void updateCUAtLeastOneProbeManual(OnOffType status) {
578 updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, status);
579 logger.debug("updateCUAtLeastOneProbeManual(): {}", status);
582 private Boolean channelExists(String channelID) {
583 return thing.getChannel("openwebnet:" + channelID) != null;
587 protected void refreshDevice(boolean refreshAll) {
588 logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
590 // TODO: 4 zone central -> zone #0 CAN be also a zone with its temp.. with 99-zones central no!
591 // let's assume it's a 99 zone
593 send(Thermoregulation.requestStatus("#0"));
594 } catch (OWNException e) {
595 logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage());
601 if (deviceWhere != null) {
603 String w = deviceWhere.value();
605 send(Thermoregulation.requestTemperature(w));
607 if (!((WhereThermo) deviceWhere).isProbe()) {
608 // for bus_thermo_zone request also other single channels updates
609 send(Thermoregulation.requestSetPointTemperature(w));
610 send(Thermoregulation.requestMode(w));
612 // refresh ONLY subscribed channels
613 if (channelExists(CHANNEL_FAN_SPEED)) {
614 send(Thermoregulation.requestFanCoilSpeed(w));
617 if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) {
618 send(Thermoregulation.requestValvesStatus(w));
621 if (channelExists(CHANNEL_ACTUATORS)) {
622 send(Thermoregulation.requestActuatorsStatus(w));
625 if (channelExists(CHANNEL_LOCAL_OFFSET)) {
626 send(Thermoregulation.requestLocalOffset(w));
629 } catch (OWNException e) {
630 logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage());