]> git.basschouten.com Git - openhab-addons.git/commitdiff
[openwebnet] Thermo: added support for HOLIDAY/VACATION central unit modes (#16605)
authorM Valla <12682715+mvalla@users.noreply.github.com>
Sun, 14 Apr 2024 17:32:48 +0000 (19:32 +0200)
committerGitHub <noreply@github.com>
Sun, 14 Apr 2024 17:32:48 +0000 (19:32 +0200)
* [openwebnet] added vacationDays channel
* [openwebnet] Added support for HOLIDAY/VACATION Thermo CU modes.
Refactored Thermo mode handling using updated OWN lib.
Bump openwebnet lib to 0.13.0.
* [openwebnet] added checks for some corner cases

Signed-off-by: Massimo Valla <mvcode00@gmail.com>
bundles/org.openhab.binding.openwebnet/README.md
bundles/org.openhab.binding.openwebnet/pom.xml
bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java
bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java
bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties
bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml
bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml
bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml

index e076f49e1374ca5c1963528771078438a2e6025a..bc608a6c23a0025aa536506fe0d78ae48a393273 100644 (file)
@@ -164,8 +164,8 @@ The (optional) Central Unit can be configured defining a `bus_themo_cu` Thing wi
 ##### Thermo Central Unit integration known limitations
 
 - Read setPoint temperature and current mode
-- Central Unit Programming and Customisations settings (T1/2/3 temperature levels, date & time, weekly/scenarios/holiday programming, etc.)
-- Holiday/Vacation activation command
+- Set VACATION deadline date / time
+- Central Unit Programming and Customisations settings (T1/2/3 temperature levels, setting date & time, weekly/scenarios/holiday profiles programming, etc.)
 
 #### Configuring Alarm and Auxiliary (AUX)
 
@@ -245,7 +245,7 @@ OPEN command to execute: *5*8#134##
 | `temperature`                | `bus_thermo_zone`, `bus_thermo_sensor` | Number:Temperature | The zone currently sensed temperature                                                                                                 | R          | N        |
 | `setpointTemperature`        | `bus_thermo_zone`, `bus_thermo_cu`     | Number:Temperature | The zone or Central Unit setpoint temperature                                                                                         | R/W        | N        |
 | `function`                   | `bus_thermo_zone`, `bus_thermo_cu`     | String             | The zone set thermo function (`COOLING`, `HEATING`, `GENERIC`) or the Central Unit thermo function (`COOLING`, `HEATING`)             | R/W        | N        |
-| `mode`                       | `bus_thermo_zone`, `bus_thermo_cu`     | String             | The zone set mode (`AUTO`, `MANUAL`, `PROTECTION`, `OFF`) or the Central Unit set mode (`WEEKLY`, `SCENARIO`, `MANUAL`, `PROTECTION`, `OFF`) | R/W        | N        |
+| `mode`                       | `bus_thermo_zone`, `bus_thermo_cu`     | String             | The zone set mode (`AUTO`, `MANUAL`, `OFF`, `PROTECTION`) or the Central Unit set mode (`WEEKLY`, `MANUAL`, `SCENARIO`, `HOLIDAY`, `VACATION`, `OFF`, `PROTECTION`) | R/W        | N        |
 | `speedFanCoil`               | `bus_thermo_zone`                      | String             | The zone fancoil speed: `AUTO`, `SPEED_1`, `SPEED_2`, `SPEED_3`                                                                       | R/W        | N        |
 | `actuators`                  | `bus_thermo_zone`                      | String             | The zone actuator(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3`            | R          | Y        |
 | `heatingValves`              | `bus_thermo_zone`                      | String             | The zone heating valve(s) status: `OFF`, `ON`, `OPENED`, `CLOSED` , `STOP`, `OFF_FAN_COIL`, `ON_SPEED_1`, `ON_SPEED_2`, `ON_SPEED_3`, `OFF_SPEED_1`, `OFF_SPEED_2`, `OFF_SPEED_3`            | R          | Y        |
@@ -255,6 +255,7 @@ OPEN command to execute: *5*8#134##
 | `batteryStatus`              | `bus_thermo_cu`                        | String             | The Central Unit Battery status: `OK`, `KO`                                                                                           | R          | Y        |
 | `weeklyProgram`              | `bus_thermo_cu`                        | Number             | The weekly program number (`1`, `2`, `3`) when Central Unit mode is `WEEKLY`                                                                 | R/W        | N        |
 | `scenarioProgram`            | `bus_thermo_cu`                        | Number             | The scenario program number (`1`, `2`, ... ,  `16`) when Central Unit mode is `SCENARIO`                                                       | R/W        | N        |
+| `vacationDays`               | `bus_thermo_cu`                        | Number             | Number of days 1-255 the Central Unit will be set to Antifreeze / Heat Protection temperature before returning to mode WEEKLY (read/write)  | R/W        | N        |
 | `failureDiscovered`          | `bus_thermo_cu`                        | Switch             | Indicates if a Failure was discovered by the Central Unit: `ON`, `OFF`                                                                | R          | Y        |
 | `atLeastOneProbeOff`         | `bus_thermo_cu`                        | Switch             | Indicates if at least one probe is in OFF mode: `ON`, `OFF`                                                                           | R          | Y        |
 | `atLeastOneProbeProtection`  | `bus_thermo_cu`                        | Switch             | Indicates if at least one probe is in PROTECTION mode: `ON`, `OFF`                                                                    | R          | Y        |
index 392345816ea683ec7b01e3b0bd8d888bcc1443c1..2d867df83c0973c962bfcbe6839a05c8c177bfa3 100644 (file)
@@ -19,7 +19,7 @@
     <dependency>
       <groupId>io.github.openwebnet4j</groupId>
       <artifactId>openwebnet4j</artifactId>
-      <version>0.12.0</version>
+      <version>0.13.0</version>
       <scope>compile</scope>
     </dependency>
 
index 991d09400c254babd61b1d96641cd0bd18f28a4a..7e0f281cf1d3a9e56b5ab24d64cd7317abaff1a4 100644 (file)
@@ -151,6 +151,8 @@ public class OpenWebNetBindingConstants {
     public static final String CHANNEL_CU_BATTERY_STATUS = "batteryStatus";
     public static final String CHANNEL_CU_WEEKLY_PROGRAM_NUMBER = "weeklyProgram";
     public static final String CHANNEL_CU_SCENARIO_PROGRAM_NUMBER = "scenarioProgram";
+    public static final String CHANNEL_CU_VACATION_DAYS = "vacationDays";
+
     public static final String CHANNEL_CU_FAILURE_DISCOVERED = "failureDiscovered";
     public static final String CHANNEL_CU_AT_LEAST_ONE_PROBE_OFF = "atLeastOneProbeOff";
     public static final String CHANNEL_CU_AT_LEAST_ONE_PROBE_PROTECTION = "atLeastOneProbeProtection";
index c0e60027178beb6cdffe672a909f15d65735bc9f..9eb2af59d76c3a9d6e0db927b12b63224f816fc3 100644 (file)
@@ -39,7 +39,10 @@ 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.Function;
+import org.openwebnet4j.message.Thermoregulation.OperationMode;
 import org.openwebnet4j.message.Thermoregulation.WhatThermo;
+import org.openwebnet4j.message.Thermoregulation.WhatThermoType;
 import org.openwebnet4j.message.Where;
 import org.openwebnet4j.message.WhereThermo;
 import org.openwebnet4j.message.Who;
@@ -52,7 +55,8 @@ import org.slf4j.LoggerFactory;
  * {@link OpenWebNetThingHandler}.
  *
  * @author Massimo Valla - Initial contribution. Added support for 4-zones CU.
- *         Rafactoring and fixed CU state channels updates.
+ *         Rafactoring and fixed CU state channels updates. Completed support
+ *         for HOLIDAY/VACATION modes and refactored mode handling.
  * @author Gilberto Cocchi - Initial contribution.
  * @author Andrea Conte - Added support for 99-zone CU and CU state channels.
  */
@@ -65,10 +69,11 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
 
     private double currentSetPointTemp = 20.0d;
 
-    private Thermoregulation.@Nullable Function currentFunction = null;
-    private Thermoregulation.@Nullable OperationMode currentMode = null;
+    private Thermoregulation.@Nullable Function currentFunction = Function.HEATING;
+    private Thermoregulation.@Nullable OperationMode currentMode = OperationMode.PROTECTION;
     private int currentWeeklyPrgNum = 1;
     private int currentScenarioPrgNum = 1;
+    private int currentVacationDays = 1;
 
     private boolean isStandAlone = true; // true if zone is not associated to a CU
     private boolean isCentralUnit = false;
@@ -88,7 +93,6 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     private static final String CU_BATTERY_OK = "OK";
     private static final String CU_BATTERY_KO = "KO";
     private static final String MODE_WEEKLY = "WEEKLY";
-    private static final String MODE_AUTO = "AUTO";
 
     public OpenWebNetThermoregulationHandler(Thing thing) {
         super(thing);
@@ -138,6 +142,9 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
             case CHANNEL_CU_SCENARIO_PROGRAM_NUMBER:
                 handleSetProgramNumber(channel, command);
                 break;
+            case CHANNEL_CU_VACATION_DAYS:
+                handleVacationDays(channel, command);
+                break;
             default: {
                 logger.warn("handleChannelCommand() Unsupported ChannelUID {}", channel.getId());
             }
@@ -163,17 +170,18 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     private void handleSetFanSpeed(Command command) {
         if (command instanceof StringType) {
             Where w = deviceWhere;
-            if (w != null) {
-                try {
-                    Thermoregulation.FanCoilSpeed speed = Thermoregulation.FanCoilSpeed.valueOf(command.toString());
-                    send(Thermoregulation.requestWriteFanCoilSpeed(w.value(), speed));
-                } catch (OWNException e) {
-                    logger.warn("handleSetFanSpeed() {}", e.getMessage());
-                } catch (IllegalArgumentException e) {
-                    logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command,
-                            getThing().getUID());
-                    return;
-                }
+            if (w == null) {
+                logger.warn("handleSetFanSpeed() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+            try {
+                Thermoregulation.FanCoilSpeed speed = Thermoregulation.FanCoilSpeed.valueOf(command.toString());
+                send(Thermoregulation.requestWriteFanCoilSpeed(w.value(), speed));
+            } catch (OWNException e) {
+                logger.warn("handleSetFanSpeed() {}", e.getMessage());
+            } catch (IllegalArgumentException e) {
+                logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command, getThing().getUID());
+                return;
             }
         } else {
             logger.warn("handleSetFanSpeed() Unsupported command {} for thing {}", command, getThing().getUID());
@@ -186,15 +194,31 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
                 logger.warn("handleSetProgramNumber() This command can be sent only for a Central Unit.");
                 return;
             }
+            Where w = deviceWhere;
+            if (w == null) {
+                logger.warn("handleSetProgramNumber() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+
             int programNumber = ((DecimalType) command).intValue();
             boolean updateOpMode = false;
 
             if (CHANNEL_CU_WEEKLY_PROGRAM_NUMBER.equals(channel.getId())) {
-                updateOpMode = currentMode.isWeekly();
+                if (programNumber < 1 || programNumber > 3) {
+                    logger.warn("handleSetProgramNumber() Invalid program number {} for thing {}", command,
+                            getThing().getUID());
+                    return;
+                }
+                updateOpMode = (currentMode == Thermoregulation.OperationMode.WEEKLY);
                 currentWeeklyPrgNum = programNumber;
                 logger.debug("handleSetProgramNumber() currentWeeklyPrgNum changed to: {}", programNumber);
             } else {
-                updateOpMode = currentMode.isScenario();
+                if (programNumber < 1 || programNumber > 16) {
+                    logger.warn("handleSetProgramNumber() Invalid program number {} for thing {}", command,
+                            getThing().getUID());
+                    return;
+                }
+                updateOpMode = (currentMode == Thermoregulation.OperationMode.SCENARIO);
                 currentScenarioPrgNum = programNumber;
                 logger.debug("handleSetProgramNumber() currentScenarioPrgNum changed to: {}", programNumber);
             }
@@ -202,16 +226,10 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
             // force OperationMode update if we are already in SCENARIO or WEEKLY mode
             if (updateOpMode) {
                 try {
-                    Thermoregulation.OperationMode newMode = Thermoregulation.OperationMode
-                            .valueOf(currentMode.mode() + "_" + programNumber);
-                    logger.debug("handleSetProgramNumber() new mode {}", newMode);
-                    send(Thermoregulation.requestWriteMode(getWhere(deviceWhere.value()), newMode, currentFunction,
-                            currentSetPointTemp));
+                    send(Thermoregulation.requestWriteWeeklyScenarioMode(getWhere(w.value()), currentMode,
+                            currentFunction, programNumber));
                 } catch (OWNException e) {
                     logger.warn("handleSetProgramNumber() {}", e.getMessage());
-                } catch (IllegalArgumentException e) {
-                    logger.warn("handleSetProgramNumber() Unsupported command {} for thing {}", command,
-                            getThing().getUID());
                 }
             } else { // just update channel
                 updateState(channel, new DecimalType(programNumber));
@@ -221,25 +239,66 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         }
     }
 
+    private void handleVacationDays(ChannelUID channel, Command command) {
+        if (command instanceof DecimalType) {
+            Where w = deviceWhere;
+            if (w == null) {
+                logger.warn("handleVacationDays() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+            if (!isCentralUnit) {
+                logger.warn("handleVacationDays() This command can be sent only for a Central Unit.");
+                return;
+            }
+            int vacationDays = ((DecimalType) command).intValue();
+
+            if (vacationDays < 1 || vacationDays > 255) {
+                logger.warn("handleVacationDays() vacation days must be between 1 and 255");
+                return;
+            }
+
+            currentVacationDays = vacationDays;
+            logger.debug("handleVacationDays() currentVacationDays changed to: {}", currentVacationDays);
+
+            // force OperationMode update if we are already in VACATION mode
+            if (currentMode == Thermoregulation.OperationMode.VACATION) {
+                try {
+                    send(Thermoregulation.requestWriteVacationMode(getWhere(w.value()), currentFunction,
+                            currentVacationDays, currentWeeklyPrgNum));
+                } catch (OWNException e) {
+                    logger.warn("handleVacationDays() {}", e.getMessage());
+                } catch (IllegalArgumentException e) {
+                    logger.warn("handleVacationDays() Unsupported command {} for thing {}", command,
+                            getThing().getUID());
+                }
+            } else { // just update channel
+                updateState(channel, new DecimalType(currentVacationDays));
+            }
+        } else {
+            logger.warn("handleVacationDays() Unsupported command {} for thing {}", command, getThing().getUID());
+        }
+    }
+
     private void handleSetpoint(Command command) {
         if (command instanceof QuantityType || command instanceof DecimalType) {
             Where w = deviceWhere;
-            if (w != null) {
-                double newTemp = 0;
-                if (command instanceof QuantityType) {
-                    QuantityType<?> tempCelsius = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
-                    if (tempCelsius != null) {
-                        newTemp = tempCelsius.doubleValue();
-                    }
-                } else {
-                    newTemp = ((DecimalType) command).doubleValue();
-                }
-                try {
-                    send(Thermoregulation.requestWriteSetpointTemperature(getWhere(w.value()), newTemp,
-                            currentFunction));
-                } catch (MalformedFrameException | OWNException e) {
-                    logger.warn("handleSetpoint() {}", e.getMessage());
+            if (w == null) {
+                logger.warn("handleSetpoint() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+            double newTemp = 0;
+            if (command instanceof QuantityType) {
+                QuantityType<?> tempCelsius = ((QuantityType<?>) command).toUnit(SIUnits.CELSIUS);
+                if (tempCelsius != null) {
+                    newTemp = tempCelsius.doubleValue();
                 }
+            } else {
+                newTemp = ((DecimalType) command).doubleValue();
+            }
+            try {
+                send(Thermoregulation.requestWriteSetpointTemperature(getWhere(w.value()), newTemp, currentFunction));
+            } catch (MalformedFrameException | OWNException e) {
+                logger.warn("handleSetpoint() {}", e.getMessage());
             }
         } else {
             logger.warn("handleSetpoint() Unsupported command {} for thing {}", command, getThing().getUID());
@@ -249,37 +308,71 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     private void handleMode(Command command) {
         if (command instanceof StringType) {
             Where w = deviceWhere;
-            if (w != null) {
+            if (w == null) {
+                logger.warn("handleMode() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+
+            String whStr = getWhere(w.value());
+            String cmdStr = command.toString().toUpperCase();
+            OperationMode newMode;
+            try {
+                newMode = OperationMode.valueOf(cmdStr);
+            } catch (IllegalArgumentException e) {
+                logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
+                return;
+            }
+            Thermoregulation tMsg = null;
+            if (isCentralUnit) { // CU accepted modes: MANUAL, OFF, PROTECTION, WEEKLY, SCENARIO, HOLIDAY,
+                                 // VACATION
+                switch (newMode) {
+                    case MANUAL:
+                    case OFF:
+                    case PROTECTION:
+                        tMsg = Thermoregulation.requestWriteMode(whStr, newMode, currentFunction, currentSetPointTemp);
+                        break;
+                    case WEEKLY:
+                    case SCENARIO:
+                        int programNumber = (MODE_WEEKLY.equals(cmdStr) ? currentWeeklyPrgNum : currentScenarioPrgNum);
+                        tMsg = Thermoregulation.requestWriteWeeklyScenarioMode(whStr, newMode, currentFunction,
+                                programNumber);
+                        break;
+                    case HOLIDAY:
+                        tMsg = Thermoregulation.requestWriteHolidayMode(whStr, currentFunction, currentWeeklyPrgNum);
+                        break;
+                    case VACATION:
+                        tMsg = Thermoregulation.requestWriteVacationMode(whStr, currentFunction, currentVacationDays,
+                                currentWeeklyPrgNum);
+                        break;
+                    default:
+                        logger.warn("handleMode() Unsupported command {} for CU thing {}", command,
+                                getThing().getUID());
+                }
+            } else {// Zone accepted modes: MANUAL, OFF, PROTECTION, AUTO
+                switch (newMode) {
+                    case MANUAL:
+                        tMsg = Thermoregulation.requestWriteMode(whStr, newMode, currentFunction, currentSetPointTemp);
+                        break;
+                    case OFF:
+                    case PROTECTION:
+                    case AUTO:
+                        tMsg = Thermoregulation.requestWriteMode(whStr, newMode, Function.GENERIC, currentSetPointTemp);
+                        break;
+                    default:
+                        logger.warn("handleMode() Unsupported command {} for ZONE thing {}", command,
+                                getThing().getUID());
+                }
+            }
+
+            if (tMsg != null) {
                 try {
-                    Thermoregulation.OperationMode newMode = Thermoregulation.OperationMode.OFF;
-
-                    if (isCentralUnit && WhatThermo.isComplex(command.toString())) {
-                        int programNumber = 0;
-                        if (MODE_WEEKLY.equalsIgnoreCase(command.toString())) {
-                            programNumber = currentWeeklyPrgNum;
-                        } else {
-                            programNumber = currentScenarioPrgNum;
-                        }
-                        newMode = Thermoregulation.OperationMode.valueOf(command.toString() + "_" + programNumber);
-                        currentMode = newMode;
-                    } else {
-                        if (MODE_AUTO.equalsIgnoreCase(command.toString())) {
-                            newMode = Thermoregulation.OperationMode.PROGRAM;
-                        } else {
-                            newMode = Thermoregulation.OperationMode.valueOf(command.toString());
-                        }
-                    }
-                    send(Thermoregulation.requestWriteMode(getWhere(w.value()), newMode, currentFunction,
-                            currentSetPointTemp));
+                    send(tMsg);
                 } catch (OWNException e) {
                     logger.warn("handleMode() {}", e.getMessage());
-                } catch (IllegalArgumentException e) {
-                    logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
-                    return;
                 }
+            } else {
+                logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
             }
-        } else {
-            logger.warn("handleMode() Unsupported command {} for thing {}", command, getThing().getUID());
         }
     }
 
@@ -298,16 +391,18 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     private void handleFunction(Command command) {
         if (command instanceof StringType) {
             Where w = deviceWhere;
-            if (w != null) {
-                try {
-                    Thermoregulation.Function function = Thermoregulation.Function.valueOf(command.toString());
-                    send(Thermoregulation.requestWriteFunction(w.value(), function));
-                } catch (OWNException e) {
-                    logger.warn("handleFunction() {}", e.getMessage());
-                } catch (IllegalArgumentException e) {
-                    logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
-                    return;
-                }
+            if (w == null) {
+                logger.warn("handleFunction() Where is null for thing {}", getThing().getUID());
+                return;
+            }
+            try {
+                Thermoregulation.Function function = Thermoregulation.Function.valueOf(command.toString());
+                send(Thermoregulation.requestWriteFunction(w.value(), function));
+            } catch (OWNException e) {
+                logger.warn("handleFunction() {}", e.getMessage());
+            } catch (IllegalArgumentException e) {
+                logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
+                return;
             }
         } else {
             logger.warn("handleFunction() Unsupported command {} for thing {}", command, getThing().getUID());
@@ -330,7 +425,7 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
                 // their values
                 resetCUState();
             }
-            switch (tWhat) {
+            switch (tWhat.getType()) {
                 case AT_LEAST_ONE_PROBE_ANTIFREEZE:
                     cuAtLeastOneProbeProtection = true;
                     break;
@@ -399,65 +494,87 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
 
     private void updateModeAndFunction(Thermoregulation tmsg) {
         if (tmsg.getWhat() == null) {
-            logger.warn("updateModeAndFunction() Could not parse Mode or Function from {} (WHAT is null)",
-                    tmsg.getFrameValue());
+            logger.warn("updateModeAndFunction() Could not parse What {} (WHAT is null)", tmsg.getFrameValue());
             return;
         }
-        Thermoregulation.WhatThermo w = Thermoregulation.WhatThermo.fromValue(tmsg.getWhat().value());
-        if (w.getMode() == null) {
+        Thermoregulation.WhatThermo what = tmsg.new WhatThermo(tmsg.getWhat().value());
+        if (what.getMode() == null) {
             logger.warn("updateModeAndFunction() Could not parse Mode from: {}", tmsg.getFrameValue());
             return;
         }
-        if (w.getFunction() == null) {
+        if (what.getFunction() == null) {
             logger.warn("updateModeAndFunction() Could not parse Function from: {}", tmsg.getFrameValue());
             return;
         }
 
+        // update Function if it's not GENERIC
+        Thermoregulation.Function function = what.getFunction();
+        if (function != Function.GENERIC) {
+            updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
+            currentFunction = function;
+        }
+
+        // then update Mode
         Thermoregulation.OperationMode operationMode = null;
-        if (w != WhatThermo.HEATING && w != WhatThermo.CONDITIONING) {
+        if (what.getType() != WhatThermoType.HEATING && what.getType() != WhatThermoType.CONDITIONING) {
             // *4*1*z## and *4*0*z## do not tell us which mode is the zone now
-            operationMode = w.getMode();
+            operationMode = what.getMode();
         }
-        Thermoregulation.Function function = w.getFunction();
 
-        updateState(CHANNEL_FUNCTION, new StringType(function.toString()));
-
-        // must convert from OperationMode to Mode and set ProgramNumber when necessary
+        // set ProgramNumber/vacationDays channels when necessary
         if (operationMode != null) {
-            String newMode;
-            if (operationMode == Thermoregulation.OperationMode.PROGRAM) { // translate PROGRAM -> AUTO
-                newMode = MODE_AUTO;
-            } else {
-                newMode = operationMode.mode();
+            switch (operationMode) {
+                case VACATION:
+                    updateVacationDays(tmsg);
+                    break;
+                case WEEKLY:
+                case SCENARIO:
+                    updateProgramNumber(tmsg);
+                    break;
+                default:
+                    break;
             }
-            updateState(CHANNEL_MODE, new StringType(newMode));
-            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());
+            if (!isCentralUnit && !(operationMode == OperationMode.AUTO || operationMode == OperationMode.OFF
+                    || operationMode == OperationMode.PROTECTION || operationMode == OperationMode.MANUAL)) {
+                logger.warn("updateModeAndFunction() Unsupported mode for zone {} from message: {}",
+                        getThing().getUID(), tmsg.getFrameValue());
                 return;
+            } else {
+                updateState(CHANNEL_MODE, new StringType(operationMode.name()));
+                currentMode = operationMode;
             }
-            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 (operationMode.isWeekly()) {
-                logger.debug("{} - updateModeAndFunction() set WEEKLY program to: {}", getThing().getUID(), programN);
-                updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(programN));
-                currentWeeklyPrgNum = programN;
-            }
+        } else {
+            logger.debug("updateModeAndFunction() Unrecognized mode from message: {}", tmsg.getFrameValue());
         }
-        // store current function
-        currentFunction = function;
-        // in case of Central Unit store also current operation mode
-        if (isCentralUnit) {
-            currentMode = operationMode;
+    }
+
+    private void updateVacationDays(Thermoregulation tmsg) {
+        @Nullable
+        Integer vDays = ((WhatThermo) tmsg.getWhat()).vacationDays();
+        if (vDays != null) {
+            logger.debug("{} - updateVacationDays() set VACATION DAYS to: {}", getThing().getUID(), vDays);
+            updateState(CHANNEL_CU_VACATION_DAYS, new DecimalType(vDays));
+            currentVacationDays = vDays;
+        }
+    }
+
+    private void updateProgramNumber(Thermoregulation tmsg) {
+        @Nullable
+        WhatThermo wt = (WhatThermo) tmsg.getWhat();
+        if (wt == null) {
+            return;
+        }
+        Integer prNum = wt.programNumber();
+        if (prNum != null) {
+            if (wt.getMode() == OperationMode.SCENARIO) {
+                logger.debug("{} - updateProgramNumber() set SCENARIO program to: {}", getThing().getUID(), prNum);
+                updateState(CHANNEL_CU_SCENARIO_PROGRAM_NUMBER, new DecimalType(prNum));
+                currentScenarioPrgNum = prNum;
+            } else if (wt.getMode() == OperationMode.WEEKLY) {
+                logger.debug("{} - updateProgramNumber() set WEEKLY program to: {}", getThing().getUID(), prNum);
+                updateState(CHANNEL_CU_WEEKLY_PROGRAM_NUMBER, new DecimalType(prNum));
+                currentWeeklyPrgNum = prNum;
+            }
         }
     }
 
@@ -475,14 +592,14 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
         try {
             double newTemp = -1;
             if (isCentralUnit) {
-                if (tmsg.getWhat() == null) {
-                    logger.warn("updateSetpoint() Could not parse function from {} (what is null)",
-                            tmsg.getFrameValue());
+                WhatThermo tw = (WhatThermo) tmsg.getWhat();
+                if (tw == null) {
+                    logger.warn("updateSetpoint() Could not parse what from {} (what is null)", tmsg.getFrameValue());
                     return;
                 }
                 String[] parameters = tmsg.getWhatParams();
-                if (parameters.length > 0) {
-                    // it should be like *4*WHAT#TTTT*#0##
+                if (parameters.length > 0 && tw.getType() == WhatThermoType.MANUAL) {
+                    // it should be like *4*110#TTTT*#0##
                     newTemp = Thermoregulation.decodeTemperature(parameters[0]);
                     logger.debug("updateSetpoint() parsed temperature from {}: {} ---> {}", tmsg.toStringVerbose(),
                             parameters[0], newTemp);
@@ -519,11 +636,11 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     private void updateValveStatus(Thermoregulation tmsg) {
         try {
             Thermoregulation.ValveOrActuatorStatus cv = Thermoregulation.parseValveStatus(tmsg,
-                    Thermoregulation.WhatThermo.CONDITIONING);
+                    Thermoregulation.WhatThermoType.CONDITIONING);
             updateState(CHANNEL_CONDITIONING_VALVES, new StringType(cv.toString()));
 
             Thermoregulation.ValveOrActuatorStatus hv = Thermoregulation.parseValveStatus(tmsg,
-                    Thermoregulation.WhatThermo.HEATING);
+                    Thermoregulation.WhatThermoType.HEATING);
             updateState(CHANNEL_HEATING_VALVES, new StringType(hv.toString()));
         } catch (FrameException e) {
             logger.warn("updateValveStatus() FrameException on frame {}: {}", tmsg, e.getMessage());
@@ -573,7 +690,6 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     }
 
     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));
@@ -589,45 +705,47 @@ public class OpenWebNetThermoregulationHandler extends OpenWebNetThingHandler {
     protected void refreshDevice(boolean refreshAll) {
         logger.debug("--- refreshDevice() : refreshing SINGLE... ({})", thing.getUID());
 
-        if (deviceWhere != null) {
-            String whereStr = deviceWhere.value();
+        Where w = deviceWhere;
+        if (w == null) {
+            logger.warn("refreshDevice() Where is null for thing {}", getThing().getUID());
+            return;
+        }
 
-            if (isCentralUnit) {
-                try {
-                    send(Thermoregulation.requestStatus(getWhere(whereStr)));
-                } catch (OWNException e) {
-                    logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage());
-                }
-                return;
-            }
+        String whereStr = w.value();
 
+        if (isCentralUnit) {
             try {
-                send(Thermoregulation.requestTemperature(whereStr));
-
-                if (!((WhereThermo) deviceWhere).isProbe()) {
-                    // for bus_thermo_zone request also other single channels updates
-                    send(Thermoregulation.requestSetPointTemperature(whereStr));
-                    send(Thermoregulation.requestMode(whereStr));
-
-                    // refresh ONLY subscribed channels
-                    if (channelExists(CHANNEL_FAN_SPEED)) {
-                        send(Thermoregulation.requestFanCoilSpeed(whereStr));
-                    }
-                    if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) {
-                        send(Thermoregulation.requestValvesStatus(whereStr));
-                    }
-                    if (channelExists(CHANNEL_ACTUATORS)) {
-                        send(Thermoregulation.requestActuatorsStatus(whereStr));
-                    }
-                    if (channelExists(CHANNEL_LOCAL_OFFSET)) {
-                        send(Thermoregulation.requestLocalOffset(whereStr));
-                    }
-                }
+                send(Thermoregulation.requestStatus(getWhere(whereStr)));
             } catch (OWNException e) {
-                logger.warn("refreshDevice() where='{}' returned OWNException {}", whereStr, e.getMessage());
+                logger.warn("refreshDevice() central unit returned OWNException {}", e.getMessage());
             }
-        } else {
-            logger.debug("refreshDevice() where is null");
+            return;
+        }
+
+        try {
+            send(Thermoregulation.requestTemperature(whereStr));
+
+            if (!((WhereThermo) w).isProbe()) {
+                // for bus_thermo_zone request also other single channels updates
+                send(Thermoregulation.requestSetPointTemperature(whereStr));
+                send(Thermoregulation.requestMode(whereStr));
+
+                // refresh ONLY subscribed channels
+                if (channelExists(CHANNEL_FAN_SPEED)) {
+                    send(Thermoregulation.requestFanCoilSpeed(whereStr));
+                }
+                if (channelExists(CHANNEL_CONDITIONING_VALVES) || channelExists(CHANNEL_HEATING_VALVES)) {
+                    send(Thermoregulation.requestValvesStatus(whereStr));
+                }
+                if (channelExists(CHANNEL_ACTUATORS)) {
+                    send(Thermoregulation.requestActuatorsStatus(whereStr));
+                }
+                if (channelExists(CHANNEL_LOCAL_OFFSET)) {
+                    send(Thermoregulation.requestLocalOffset(whereStr));
+                }
+            }
+        } catch (OWNException e) {
+            logger.warn("refreshDevice() where='{}' returned OWNException {}", whereStr, e.getMessage());
         }
     }
 
index f1b8c182003d8703f514f32dfd7a32a9e4772957..5c34e1c5f543c65a470f412d12e93e6038999dbc 100644 (file)
@@ -228,18 +228,20 @@ channel-type.openwebnet.localOffset.state.option.MINUS_1 = -1
 channel-type.openwebnet.localOffset.state.option.MINUS_2 = -2
 channel-type.openwebnet.localOffset.state.option.MINUS_3 = -3
 channel-type.openwebnet.mode.label = Mode
-channel-type.openwebnet.mode.description = Set mode of the zone (read/write)
+channel-type.openwebnet.mode.description = The zone operation mode (read/write)
 channel-type.openwebnet.mode.state.option.AUTO = Automatic
 channel-type.openwebnet.mode.state.option.MANUAL = Manual
 channel-type.openwebnet.mode.state.option.PROTECTION = Antifreeze / Heat Protection
 channel-type.openwebnet.mode.state.option.OFF = Off
 channel-type.openwebnet.modeCentralUnit.label = Central Unit Mode
-channel-type.openwebnet.modeCentralUnit.description = Set mode of the Central Unit (read/write)
+channel-type.openwebnet.modeCentralUnit.description = The Central Unit operation mode (read/write)
 channel-type.openwebnet.modeCentralUnit.state.option.WEEKLY = Weekly
 channel-type.openwebnet.modeCentralUnit.state.option.SCENARIO = Scenarios
 channel-type.openwebnet.modeCentralUnit.state.option.MANUAL = Manual
 channel-type.openwebnet.modeCentralUnit.state.option.PROTECTION = Antifreeze / Heat Protection
 channel-type.openwebnet.modeCentralUnit.state.option.OFF = Off
+channel-type.openwebnet.modeCentralUnit.state.option.HOLIDAY = Holiday
+channel-type.openwebnet.modeCentralUnit.state.option.VACATION = Vacation
 channel-type.openwebnet.power.label = Power
 channel-type.openwebnet.power.description = Current active power
 channel-type.openwebnet.remoteControl.label = Remote Control
@@ -281,6 +283,8 @@ channel-type.openwebnet.switch.label = Switch
 channel-type.openwebnet.switch.description = Switch the power ON and OFF
 channel-type.openwebnet.temperature.label = Temperature
 channel-type.openwebnet.temperature.description = Current temperature (read only)
+channel-type.openwebnet.vacationDays.label = Vacation Days
+channel-type.openwebnet.vacationDays.description = Number of days the Central Unit will be set to Antifreeze / Heat Protection target temperature before returning to mode WEEKLY (read/write)
 channel-type.openwebnet.weeklyProgramCentralUnit.label = Weekly Program Number
 channel-type.openwebnet.weeklyProgramCentralUnit.description = Set weekly program number for the Central Unit, valid only with Central Unit mode = "WEEKLY" (read/write)
 channel-type.openwebnet.weeklyProgramCentralUnit.state.option.1 = Weekly Program 1
index e7c08153482abccff998c1cf2ea8d3523bb20c3e..7e6e4b45088480810c06c1e93f246c159f5db3f3 100644 (file)
                        <channel id="mode" typeId="modeCentralUnit"/>
                        <channel id="weeklyProgram" typeId="weeklyProgramCentralUnit"/>
                        <channel id="scenarioProgram" typeId="scenarioProgramCentralUnit"/>
+                       <channel id="vacationDays" typeId="vacationDays"/>
                </channels>
 
                <properties>
                        <property name="vendor">BTicino/Legrand</property>
                        <property name="model">BTicino Central Unit 3550 (99 zones) or L/N/NT/HD/HC/HS4695 (4 zones) </property>
                        <property name="ownDeviceType">430</property>
+                       <property name="thingTypeVersion">1</property>
                </properties>
 
                <representation-property>ownId</representation-property>
index 37732d63b5dce279163ee14edb156cc5b6c2c6f9..3ae800b1e5d315f5db002fdb2091ecbe02d1b98c 100644 (file)
        <channel-type id="mode">
                <item-type>String</item-type>
                <label>Mode</label>
-               <description>Set mode of the zone (read/write)</description>
+               <description>The zone operation mode (read/write)</description>
                <state>
                        <options>
                                <option value="AUTO">Automatic</option>
        <channel-type id="modeCentralUnit">
                <item-type>String</item-type>
                <label>Central Unit Mode</label>
-               <description>Set mode of the Central Unit (read/write)</description>
+               <description>The Central Unit operation mode (read/write)</description>
                <state>
                        <options>
                                <option value="WEEKLY">Weekly</option>
                                <option value="MANUAL">Manual</option>
                                <option value="PROTECTION">Antifreeze / Heat Protection</option>
                                <option value="OFF">Off</option>
+                               <option value="HOLIDAY">Holiday</option>
+                               <option value="VACATION">Vacation</option>
                        </options>
                </state>
        </channel-type>
                </state>
        </channel-type>
 
+       <channel-type id="vacationDays">
+               <item-type>Number</item-type>
+               <label>Vacation Days</label>
+               <description>Number of days the Central Unit will be set to Antifreeze / Heat Protection target temperature before
+                       returning to mode WEEKLY (read/write)</description>
+       </channel-type>
+
        <channel-type id="remoteControl" advanced="true">
                <item-type>String</item-type>
                <label>Remote Control</label>
index 87a1a34d12d4c214702073385a91d6421d4fc833..bc53c452a388f49a19a080b464c971799eaf17d3 100644 (file)
                        </add-channel>
                </instruction-set>
        </thing-type>
+
+       <thing-type uid="openwebnet:bus_thermo_cu">
+               <instruction-set targetVersion="1">
+                       <add-channel id="vacationDays">
+                               <type>openwebnet:vacationDays</type>
+                       </add-channel>
+               </instruction-set>
+       </thing-type>
+
 </update:update-descriptions>