]> git.basschouten.com Git - openhab-addons.git/commitdiff
[openwebnet] Fix update of Thermo Central Unit atLeastOneProbeX channels and refactor...
authorM Valla <12682715+mvalla@users.noreply.github.com>
Tue, 18 Jul 2023 20:15:33 +0000 (22:15 +0200)
committerGitHub <noreply@github.com>
Tue, 18 Jul 2023 20:15:33 +0000 (22:15 +0200)
* [openwebnet] Fixes changing and startup value for Weekly/Scenario modes
Fixes #12599
* [openwebnet] Thermo: Fixed CU setpointTemp not restored
Fixes #14449
* [openwebnet] fix update of atLeastOneProbeX channels for CU Fixes #15103
Bumped lib openwebnet4j to 0.10.1

Signed-off-by: Massimo Valla <mvcode00@gmail.com>
bundles/org.openhab.binding.openwebnet/pom.xml
bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java

index 92637aae27fe6302d5755371ae9bd6b7c62943ab..f14136a456550de42ddafedfd82072afcfb8cf92 100644 (file)
@@ -23,7 +23,7 @@
     <dependency>
       <groupId>io.github.openwebnet4j</groupId>
       <artifactId>openwebnet4j</artifactId>
-      <version>0.10.0</version>
+      <version>0.10.1</version>
       <scope>compile</scope>
     </dependency>
 
index 19d9b0d4dc87295232ab7ab319e8f6aa0c19d963..deaef021191dfba7431c1a103527f3c02fb4ad78 100644 (file)
@@ -14,10 +14,12 @@ package org.openhab.binding.openwebnet.internal.handler;
 
 import static org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants.*;
 
-import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
 
 import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.openwebnet.internal.OpenWebNetBindingConstants;
 import org.openhab.core.library.types.DecimalType;
 import org.openhab.core.library.types.OnOffType;
@@ -36,6 +38,7 @@ import org.openwebnet4j.message.BaseOpenMessage;
 import org.openwebnet4j.message.FrameException;
 import org.openwebnet4j.message.MalformedFrameException;
 import org.openwebnet4j.message.Thermoregulation;
+import org.openwebnet4j.message.Thermoregulation.DimThermo;
 import org.openwebnet4j.message.Thermoregulation.WhatThermo;
 import org.openwebnet4j.message.Where;
 import org.openwebnet4j.message.WhereThermo;
@@ -45,12 +48,13 @@ import org.slf4j.LoggerFactory;
 
 /**
  * The {@link OpenWebNetThermoregulationHandler} is responsible for handling
- * commands/messages for Thermoregulation
- * Things. It extends the abstract {@link OpenWebNetThingHandler}.
+ * commands/messages for Thermoregulation Things. It extends the abstract
+ * {@link OpenWebNetThingHandler}.
  *
- * @author Massimo Valla - Initial contribution. Added support for 4-zone CU
- * @author Andrea Conte - Thermoregulation
- * @author Gilberto Cocchi - Thermoregulation
+ * @author Massimo Valla - Initial contribution. Added support for 4-zones CU.
+ *         Rafactoring and fixed CU state channels updates.
+ * @author Gilberto Cocchi - Initial contribution.
+ * @author Andrea Conte - Added support for 99-zone CU and CU state channels.
  */
 @NonNullByDefault
 public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
@@ -59,27 +63,30 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
 
     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = OpenWebNetBindingConstants.THERMOREGULATION_SUPPORTED_THING_TYPES;
 
-    private double currentSetPointTemp = 11.5d; // 11.5 is the default setTemp used in MyHomeUP mobile app
+    private double currentSetPointTemp = 20.0d;
 
-    private Thermoregulation.Function currentFunction = Thermoregulation.Function.GENERIC;
-    private Thermoregulation.OperationMode currentMode = Thermoregulation.OperationMode.MANUAL;
+    private Thermoregulation.@Nullable Function currentFunction = null;
+    private Thermoregulation.@Nullable OperationMode currentMode = null;
+    private int currentWeeklyPrgNum = 1;
+    private int currentScenarioPrgNum = 1;
 
     private boolean isStandAlone = true; // true if zone is not associated to a CU
-
     private boolean isCentralUnit = false;
 
-    private String programNumber = "1";
+    private boolean cuAtLeastOneProbeOff = false;
+    private boolean cuAtLeastOneProbeProtection = false;
+    private boolean cuAtLeastOneProbeManual = false;
+    private String cuBatteryStatus = CU_BATTERY_OK;
+    private boolean cuFailureDiscovered = false;
+
+    private @Nullable ScheduledFuture<?> cuStateChannelsUpdateSchedule;
 
-    private static Set<String> probesInProtection = new HashSet<String>();
-    private static Set<String> probesInOFF = new HashSet<String>();
-    private static Set<String> probesInManual = new HashSet<String>();
+    public static final int CU_STATE_CHANNELS_UPDATE_DELAY = 1500; // msec
 
     private static final String CU_REMOTE_CONTROL_ENABLED = "ENABLED";
     private static final String CU_REMOTE_CONTROL_DISABLED = "DISABLED";
     private static final String CU_BATTERY_OK = "OK";
     private static final String CU_BATTERY_KO = "KO";
-    private static final Integer UNDOCUMENTED_WHAT_4001 = 4001;
-    private static final Integer UNDOCUMENTED_WHAT_4002 = 4002;
 
     public OpenWebNetThermoregulationHandler(Thing thing) {
         super(thing);
@@ -88,18 +95,17 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     @Override
     public void initialize() {
         super.initialize();
-
         ThingTypeUID thingType = thing.getThingTypeUID();
         isCentralUnit = OpenWebNetBindingConstants.THING_TYPE_BUS_THERMO_CU.equals(thingType);
-
         if (!isCentralUnit) {
-            Object standAloneConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE);
-            if (standAloneConfig != null) {
-                isStandAlone = Boolean.parseBoolean(standAloneConfig.toString());
+            if (!((WhereThermo) deviceWhere).isProbe()) {
+                Object standAloneConfig = getConfig().get(OpenWebNetBindingConstants.CONFIG_PROPERTY_STANDALONE);
+                if (standAloneConfig != null) {
+                    isStandAlone = Boolean.parseBoolean(standAloneConfig.toString());
+                }
+                logger.debug("@@@@  THERMO ZONE INITIALIZE isStandAlone={}", isStandAlone);
             }
-            logger.debug("@@@@  THERMO ZONE INITIALIZE isStandAlone={}", isStandAlone);
         } else {
-
             // central unit must have WHERE=#0 or WHERE=0 or WHERE=#0#n
             String w = deviceWhere.value();
             if (w == null || !("0".equals(w) || "#0".equals(w) || w.startsWith("#0#"))) {
@@ -108,14 +114,6 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
                         "@text/offline.conf-error-where");
                 return;
             }
-            // reset state of signal channels (they will be setted when specific messages
-            // are received)
-            updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, OnOffType.OFF);
-            updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, OnOffType.OFF);
-            updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, OnOffType.OFF);
-            updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(programNumber));
-            updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(programNumber));
-            updateState(CHANNEL_CU_FAILURE_DISCOVERED, OnOffType.OFF);
         }
     }
 
@@ -136,7 +134,7 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
                 break;
             case CHANNEL_CU_WEEKLY_PROGRAM_NUMBER:
             case CHANNEL_CU_SCENARIO_PROGRAM_NUMBER:
-                handleSetProgramNumber(command);
+                handleSetProgramNumber(channel, command);
                 break;
             default: {
                 logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId());
@@ -180,23 +178,32 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         }
     }
 
-    private void handleSetProgramNumber(Command command) {
+    private void handleSetProgramNumber(ChannelUID channel, Command command) {
         if (command instanceof DecimalType) {
             if (!isCentralUnit) {
                 logger.warn("handleSetProgramNumber() This command can be sent only for a Central Unit.");
                 return;
             }
+            int programNumber = ((DecimalType) command).intValue();
+            boolean updateOpMode = false;
 
-            programNumber = command.toString();
-            logger.debug("handleSetProgramNumber() Program number set to {}", programNumber);
+            if (CHANNEL_CU_WEEKLY_PROGRAM_NUMBER.equals(channel.getId())) {
+                updateOpMode = currentMode.isWeekly();
+                currentWeeklyPrgNum = programNumber;
+                logger.debug("handleSetProgramNumber() currentWeeklyPrgNum changed to: {}", programNumber);
+            } else {
+                updateOpMode = currentMode.isScenario();
+                currentScenarioPrgNum = programNumber;
+                logger.debug("handleSetProgramNumber() currentScenarioPrgNum changed to: {}", programNumber);
+            }
 
-            // force OperationMode update if we are already in SCENARIO o WEEKLY mode
-            if (currentMode.isScenario() || currentMode.isWeekly()) {
+            // force OperationMode update if we are already in SCENARIO or WEEKLY mode
+            if (updateOpMode) {
                 try {
-                    Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode
+                    Thermoregulation.OperationMode newMode = Thermoregulation.OperationMode
                             .valueOf(currentMode.mode() + "_" + programNumber);
-                    logger.debug("handleSetProgramNumber() new mode {}", new_mode);
-                    send(Thermoregulation.requestWriteMode(getWhere(deviceWhere.value()), new_mode, currentFunction,
+                    logger.debug("handleSetProgramNumber() new mode {}", newMode);
+                    send(Thermoregulation.requestWriteMode(getWhere(deviceWhere.value()), newMode, currentFunction,
                             currentSetPointTemp));
                 } catch (OWNException e) {
                     logger.warn("handleSetProgramNumber() {}", e.getMessage());
@@ -204,8 +211,9 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
                     logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command,
                             getThing().getUID());
                 }
+            } else { // just update channel
+                updateState(channel, new DecimalType(programNumber));
             }
-
         } else {
             logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command, getThing().getUID());
         }
@@ -241,17 +249,21 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
             Where w = deviceWhere;
             if (w != null) {
                 try {
-                    Thermoregulation.OperationMode new_mode = Thermoregulation.OperationMode.OFF;
+                    Thermoregulation.OperationMode newMode = Thermoregulation.OperationMode.OFF;
 
                     if (isCentralUnit && WhatThermo.isComplex(command.toString())) {
-                        new_mode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber);
-
-                        // store current mode
-                        currentMode = new_mode;
+                        int programNumber = 0;
+                        if ("WEEKLY".equalsIgnoreCase(command.toString())) {
+                            programNumber = currentWeeklyPrgNum;
+                        } else {
+                            programNumber = currentScenarioPrgNum;
+                        }
+                        newMode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber);
+                        currentMode = newMode;
                     } else {
-                        new_mode = Thermoregulation.OperationMode.valueOf(command.toString());
+                        newMode = Thermoregulation.OperationMode.valueOf(command.toString());
                     }
-                    send(Thermoregulation.requestWriteMode(getWhere(w.value()), new_mode, currentFunction,
+                    send(Thermoregulation.requestWriteMode(getWhere(w.value()), newMode, currentFunction,
                             currentSetPointTemp));
                 } catch (OWNException e) {
                     logger.warn("handleMode() {}", e.getMessage());
@@ -299,149 +311,139 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     @Override
     protected void handleMessage(BaseOpenMessage msg) {
         super.handleMessage(msg);
-
         logger.debug("@@@@ Thermo.handleMessage(): {}", msg.toStringVerbose());
-
+        Thermoregulation tmsg = (Thermoregulation) msg;
         if (isCentralUnit) {
-            if (msg.getWhat() == null) {
+            WhatThermo tWhat = (WhatThermo) msg.getWhat();
+            if (tWhat == null) {
+                logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", tWhat, msg);
                 return;
             }
-
-            // there isn't a message used for setting OK for battery status so let's assume
-            // it's OK and then change to KO if according message is received
-            updateCUBatteryStatus(CU_BATTERY_OK);
-
-            // same in case of Failure Discovered
-            updateCUFailureDiscovered(OnOffType.OFF);
-
-            if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_DISABLED) {
-                updateCURemoteControlStatus(CU_REMOTE_CONTROL_DISABLED);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.REMOTE_CONTROL_ENABLED) {
-                updateCURemoteControlStatus(CU_REMOTE_CONTROL_ENABLED);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.BATTERY_KO) {
-                updateCUBatteryStatus(CU_BATTERY_KO);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_OFF) {
-                updateCUAtLeastOneProbeOff(OnOffType.ON);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_ANTIFREEZE) {
-                updateCUAtLeastOneProbeProtection(OnOffType.ON);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.AT_LEAST_ONE_PROBE_MANUAL) {
-                updateCUAtLeastOneProbeManual(OnOffType.ON);
-            } else if (msg.getWhat() == Thermoregulation.WhatThermo.FAILURE_DISCOVERED) {
-                updateCUFailureDiscovered(OnOffType.ON);
-            } // must intercept all possibile WHATs
-            else if (msg.getWhat() == Thermoregulation.WhatThermo.RELEASE_SENSOR_LOCAL_ADJUST) { // will be implemented
-                                                                                                 // soon
-                logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
-            } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4001) {
-                logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
-            } else if (msg.getWhat().value() == UNDOCUMENTED_WHAT_4002) {
-                logger.debug("handleMessage() Ignoring unsupported WHAT {}. Frame={}", msg.getWhat(), msg);
-            } else {
-                // check and update values of other channel (mode, function, temp)
-                updateModeAndFunction((Thermoregulation) msg);
-                updateSetpoint((Thermoregulation) msg);
+            if (tWhat.value() > 40) {
+                // it's a CU mode event, CU state events will follow shortly, so let's reset
+                // their values
+                resetCUState();
+            }
+            switch (tWhat) {
+                case AT_LEAST_ONE_PROBE_ANTIFREEZE:
+                    cuAtLeastOneProbeProtection = true;
+                    break;
+                case AT_LEAST_ONE_PROBE_MANUAL:
+                    cuAtLeastOneProbeManual = true;
+                    break;
+                case AT_LEAST_ONE_PROBE_OFF:
+                    cuAtLeastOneProbeOff = true;
+                    break;
+                case BATTERY_KO:
+                    cuBatteryStatus = CU_BATTERY_KO;
+                    break;
+                case FAILURE_DISCOVERED:
+                    cuFailureDiscovered = true;
+                    break;
+                case RELEASE_SENSOR_LOCAL_ADJUST:
+                    logger.debug("handleMessage(): Ignoring unsupported WHAT {}. Frame={}", tWhat, msg);
+                    break;
+                case REMOTE_CONTROL_DISABLED:
+                    updateCURemoteControlStatus(CU_REMOTE_CONTROL_DISABLED);
+                    break;
+                case REMOTE_CONTROL_ENABLED:
+                    updateCURemoteControlStatus(CU_REMOTE_CONTROL_ENABLED);
+                    break;
+                default:
+                    // check and update values of other channels (mode, function, temp)
+                    updateModeAndFunction(tmsg);
+                    updateSetpoint(tmsg);
+                    break;
             }
             return;
         }
 
-        if (msg.isCommand()) {
-            updateModeAndFunction((Thermoregulation) msg);
+        if (tmsg.isCommand()) {
+            updateModeAndFunction(tmsg);
         } else {
-            if (msg.getDim() == null) {
-                return;
-            }
-            if (msg.getDim() == Thermoregulation.DimThermo.TEMPERATURE
-                    || msg.getDim() == Thermoregulation.DimThermo.PROBE_TEMPERATURE) {
-                updateTemperature((Thermoregulation) msg);
-            } else if (msg.getDim() == Thermoregulation.DimThermo.TEMP_SETPOINT
-                    || msg.getDim() == Thermoregulation.DimThermo.COMPLETE_PROBE_STATUS) {
-                updateSetpoint((Thermoregulation) msg);
-            } else if (msg.getDim() == Thermoregulation.DimThermo.VALVES_STATUS) {
-                updateValveStatus((Thermoregulation) msg);
-            } else if (msg.getDim() == Thermoregulation.DimThermo.ACTUATOR_STATUS) {
-                updateActuatorStatus((Thermoregulation) msg);
-            } else if (msg.getDim() == Thermoregulation.DimThermo.FAN_COIL_SPEED) {
-                updateFanCoilSpeed((Thermoregulation) msg);
-            } else if (msg.getDim() == Thermoregulation.DimThermo.OFFSET) {
-                updateLocalOffset((Thermoregulation) msg);
-            } else {
-                logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", msg.getDim(),
-                        getThing().getUID(), msg);
+            DimThermo dim = (DimThermo) tmsg.getDim();
+            switch (dim) {
+                case TEMP_SETPOINT:
+                case COMPLETE_PROBE_STATUS:
+                    updateSetpoint(tmsg);
+                    break;
+                case PROBE_TEMPERATURE:
+                case TEMPERATURE:
+                    updateTemperature(tmsg);
+                    break;
+                case ACTUATOR_STATUS:
+                    updateActuatorStatus(tmsg);
+                    break;
+                case FAN_COIL_SPEED:
+                    updateFanCoilSpeed(tmsg);
+                    break;
+                case OFFSET:
+                    updateLocalOffset(tmsg);
+                    break;
+                case VALVES_STATUS:
+                    updateValveStatus(tmsg);
+                    break;
+                default:
+                    logger.debug("handleMessage() Ignoring unsupported DIM {} for thing {}. Frame={}", tmsg.getDim(),
+                            getThing().getUID(), tmsg);
+                    break;
             }
         }
     }
 
     private void updateModeAndFunction(Thermoregulation tmsg) {
         if (tmsg.getWhat() == null) {
-            logger.debug("updateModeAndFunction() Could not parse Mode or Function from {} (what is null)",
+            logger.warn("updateModeAndFunction() Could not parse Mode or Function from {} (WHAT is null)",
                     tmsg.getFrameValue());
             return;
         }
         Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
-
         if (w.getMode() == null) {
-            logger.debug("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
+            logger.warn("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
             return;
         }
-
         if (w.getFunction() == null) {
-            logger.debug("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
+            logger.warn("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
             return;
         }
 
-        Thermoregulation.OperationMode operationMode = w.getMode();
+        Thermoregulation.OperationMode operationMode = null;
+        if (w != WhatThermo.HEATING && w != WhatThermo.CONDITIONING) {
+            // *4*1*z## and *4*0*z## do not tell us which mode is the zone now
+            operationMode = w.getMode();
+        }
         Thermoregulation.Function function = w.getFunction();
 
-        // keep track of thermostats (zones) status
-        if (!isCentralUnit && (!((WhereThermo) deviceWhere).isProbe())) {
-            if (operationMode == Thermoregulation.OperationMode.OFF) {
-                probesInManual.remove(tmsg.getWhere().value());
-                probesInProtection.remove(tmsg.getWhere().value());
-                if (probesInOFF.add(tmsg.getWhere().value())) {
-                    logger.debug("atLeastOneProbeInOFF: added WHERE ---> {}", tmsg.getWhere());
-                }
-            } else if (operationMode == Thermoregulation.OperationMode.PROTECTION) {
-                probesInManual.remove(tmsg.getWhere().value());
-                probesInOFF.remove(tmsg.getWhere().value());
-                if (probesInProtection.add(tmsg.getWhere().value())) {
-                    logger.debug("atLeastOneProbeInProtection: added WHERE ---> {}", tmsg.getWhere());
-                }
-            } else if (operationMode == Thermoregulation.OperationMode.MANUAL) {
-                probesInProtection.remove(tmsg.getWhere().value());
-                probesInOFF.remove(tmsg.getWhere().value());
-                if (probesInManual.add(tmsg.getWhere().value())) {
-                    logger.debug("atLeastOneProbeInManual: added WHERE ---> {}", tmsg.getWhere());
-                }
-            }
+        updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
 
-            if (probesInOFF.isEmpty()) {
-                updateCUAtLeastOneProbeOff(OnOffType.OFF);
+        // must convert from OperationMode to Mode and set ProgramNumber when necessary
+        if (operationMode != null) {
+            updateState(CHANNEL_MODE, new StringType(operationMode.mode()));
+            Integer programN = 0;
+            try {
+                @Nullable
+                Integer prNum = operationMode.programNumber();
+                if (prNum != null) {
+                    programN = prNum;
+                }
+            } catch (Exception e) {
+                logger.warn("updateModeAndFunction() Could not parse program number from: {}", tmsg.getFrameValue());
+                return;
             }
-            if (probesInProtection.isEmpty()) {
-                updateCUAtLeastOneProbeProtection(OnOffType.OFF);
+            if (operationMode.isScenario()) {
+                logger.debug("{} - updateModeAndFunction() set SCENARIO program to: {}", getThing().getUID(), programN);
+                updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(programN));
+                currentScenarioPrgNum = programN;
             }
-            if (probesInManual.isEmpty()) {
-                updateCUAtLeastOneProbeManual(OnOffType.OFF);
+            if (operationMode.isWeekly()) {
+                logger.debug("{} - updateModeAndFunction() set WEEKLY program to: {}", getThing().getUID(), programN);
+                updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(programN));
+                currentWeeklyPrgNum = programN;
             }
         }
-
-        updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
-
-        // must convert from OperationMode to Mode and set ProgramNumber when necessary
-        updateState(CHANNEL_MODE, new StringType(operationMode.mode()));
-        if (operationMode.isScenario()) {
-            logger.debug("updateModeAndFunction() set SCENARIO program to: {}", operationMode.programNumber());
-            updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
-        }
-        if (operationMode.isWeekly()) {
-            logger.debug("updateModeAndFunction() set WEEKLY program to: {}", operationMode.programNumber());
-            updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(operationMode.programNumber()));
-        }
-
         // store current function
         currentFunction = function;
-
-        // in case of central unit store also current operation mode
+        // in case of Central Unit store also current operation mode
         if (isCentralUnit) {
             currentMode = operationMode;
         }
@@ -459,26 +461,27 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
 
     private void updateSetpoint(Thermoregulation tmsg) {
         try {
-            double temp = 11.5d;
+            double newTemp = -1;
             if (isCentralUnit) {
                 if (tmsg.getWhat() == null) {
-                    // it should be like *4*WHAT#TTTT*#0##
-                    logger.debug("updateSetpoint() Could not parse function from {} (what is null)",
+                    logger.warn("updateSetpoint() Could not parse function from {} (what is null)",
                             tmsg.getFrameValue());
                     return;
                 }
-
                 String[] parameters = tmsg.getWhatParams();
                 if (parameters.length > 0) {
-                    temp = Thermoregulation.decodeTemperature(parameters[0]);
+                    // it should be like *4*WHAT#TTTT*#0##
+                    newTemp = Thermoregulation.decodeTemperature(parameters[0]);
                     logger.debug("updateSetpoint() parsed temperature from {}: {} ---> {}", tmsg.toStringVerbose(),
-                            parameters[0], temp);
+                            parameters[0], newTemp);
                 }
             } else {
-                temp = Thermoregulation.parseTemperature(tmsg);
+                newTemp = Thermoregulation.parseTemperature(tmsg);
+            }
+            if (newTemp > 0) {
+                updateState(CHANNEL_TEMP_SETPOINT, getAsQuantityTypeOrNull(newTemp, SIUnits.CELSIUS));
+                currentSetPointTemp = newTemp;
             }
-            updateState(CHANNEL_TEMP_SETPOINT, getAsQuantityTypeOrNull(temp, SIUnits.CELSIUS));
-            currentSetPointTemp = temp;
         } catch (NumberFormatException e) {
             logger.warn("updateSetpoint() NumberFormatException on frame {}: {}", tmsg, e.getMessage());
             updateState(CHANNEL_TEMP_SETPOINT, UnDefType.UNDEF);
@@ -492,6 +495,9 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         try {
             Thermoregulation.FanCoilSpeed speed = Thermoregulation.parseFanCoilSpeed(tmsg);
             updateState(CHANNEL_FAN_SPEED, new StringType(speed.toString()));
+        } catch (NumberFormatException e) {
+            logger.warn("updateFanCoilSpeed() NumberFormatException on frame {}: {}", tmsg, e.getMessage());
+            updateState(CHANNEL_FAN_SPEED, UnDefType.UNDEF);
         } catch (FrameException e) {
             logger.warn("updateFanCoilSpeed() FrameException on frame {}: {}", tmsg, e.getMessage());
             updateState(CHANNEL_FAN_SPEED, UnDefType.UNDEF);
@@ -541,35 +547,26 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         logger.debug("updateCURemoteControlStatus(): {}", status);
     }
 
-    private void updateCUBatteryStatus(String status) {
-        updateState(CHANNEL_CU_BATTERY_STATUS, new StringType(status));
-
-        if (status == CU_BATTERY_KO) { // do not log default value (which is automatically setted)
-            logger.debug("updateCUBatteryStatus(): {}", status);
-        }
+    private void resetCUState() {
+        logger.debug("########### resetting CU state");
+        cuAtLeastOneProbeOff = false;
+        cuAtLeastOneProbeProtection = false;
+        cuAtLeastOneProbeManual = false;
+        cuBatteryStatus = CU_BATTERY_OK;
+        cuFailureDiscovered = false;
+
+        cuStateChannelsUpdateSchedule = scheduler.schedule(() -> {
+            updateCUStateChannels();
+        }, CU_STATE_CHANNELS_UPDATE_DELAY, TimeUnit.MILLISECONDS);
     }
 
-    private void updateCUFailureDiscovered(OnOffType status) {
-        updateState(CHANNEL_CU_FAILURE_DISCOVERED, status);
-
-        if (status == OnOffType.ON) { // do not log default value (which is automatically setted)
-            logger.debug("updateCUFailureDiscovered(): {}", status);
-        }
-    }
-
-    private void updateCUAtLeastOneProbeOff(OnOffType status) {
-        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, status);
-        logger.debug("updateCUAtLeastOneProbeOff(): {}", status);
-    }
-
-    private void updateCUAtLeastOneProbeProtection(OnOffType status) {
-        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, status);
-        logger.debug("updateCUAtLeastOneProbeProtection(): {}", status);
-    }
-
-    private void updateCUAtLeastOneProbeManual(OnOffType status) {
-        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, status);
-        logger.debug("updateCUAtLeastOneProbeManual(): {}", status);
+    private void updateCUStateChannels() {
+        logger.debug("@@@@  updating CU state channels");
+        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF, OnOffType.from(cuAtLeastOneProbeOff));
+        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION, OnOffType.from(cuAtLeastOneProbeProtection));
+        updateState(CHANNEL_CU_AT_LEAST_ONE_PROBE_MANUAL, OnOffType.from(cuAtLeastOneProbeManual));
+        updateState(CHANNEL_CU_BATTERY_STATUS, new StringType(cuBatteryStatus));
+        updateState(CHANNEL_CU_FAILURE_DISCOVERED, OnOffType.from(cuFailureDiscovered));
     }
 
     private Boolean channelExists(String channelID) {
@@ -581,11 +578,11 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
 
         if (deviceWhere != null) {
-            String w = deviceWhere.value();
+            String whereStr = deviceWhere.value();
 
             if (isCentralUnit) {
                 try {
-                    send(Thermoregulation.requestStatus(getWhere(w)));
+                    send(Thermoregulation.requestStatus(getWhere(whereStr)));
                 } catch (OWNException e) {
                     logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage());
                 }
@@ -593,35 +590,42 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
             }
 
             try {
-                send(Thermoregulation.requestTemperature(w));
+                send(Thermoregulation.requestTemperature(whereStr));
 
                 if (!((WhereThermo) deviceWhere).isProbe()) {
                     // for bus_thermo_zone request also other single channels updates
-                    send(Thermoregulation.requestSetPointTemperature(w));
-                    send(Thermoregulation.requestMode(w));
+                    send(Thermoregulation.requestSetPointTemperature(whereStr));
+                    send(Thermoregulation.requestMode(whereStr));
 
                     // refresh ONLY subscribed channels
                     if (channelExists(CHANNEL_FAN_SPEED)) {
-                        send(Thermoregulation.requestFanCoilSpeed(w));
+                        send(Thermoregulation.requestFanCoilSpeed(whereStr));
                     }
-
                     if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) {
-                        send(Thermoregulation.requestValvesStatus(w));
+                        send(Thermoregulation.requestValvesStatus(whereStr));
                     }
-
                     if (channelExists(CHANNEL_ACTUATORS)) {
-                        send(Thermoregulation.requestActuatorsStatus(w));
+                        send(Thermoregulation.requestActuatorsStatus(whereStr));
                     }
-
                     if (channelExists(CHANNEL_LOCAL_OFFSET)) {
-                        send(Thermoregulation.requestLocalOffset(w));
+                        send(Thermoregulation.requestLocalOffset(whereStr));
                     }
                 }
             } catch (OWNException e) {
-                logger.warn("refreshDevice() where='{}' returned OWNException {}", w, e.getMessage());
+                logger.warn("refreshDevice() where='{}' returned OWNException {}", whereStr, e.getMessage());
             }
         } else {
             logger.debug("refreshDevice() where is null");
         }
     }
+
+    @Override
+    public void dispose() {
+        ScheduledFuture<?> s = cuStateChannelsUpdateSchedule;
+        if (s != null) {
+            s.cancel(false);
+            logger.debug("dispose() - scheduler stopped.");
+        }
+        super.dispose();
+    }
 }