From: M Valla <12682715+mvalla@users.noreply.github.com> Date: Sun, 14 Apr 2024 17:32:48 +0000 (+0200) Subject: [openwebnet] Thermo: added support for HOLIDAY/VACATION central unit modes (#16605) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=5cf2a99fe33f9d2f96eb1a769fa6ae0fa9eaf3a6;p=openhab-addons.git [openwebnet] Thermo: added support for HOLIDAY/VACATION central unit modes (#16605) * [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 --- diff --git a/bundles/org.openhab.binding.openwebnet/README.md b/bundles/org.openhab.binding.openwebnet/README.md index e076f49e13..bc608a6c23 100644 --- a/bundles/org.openhab.binding.openwebnet/README.md +++ b/bundles/org.openhab.binding.openwebnet/README.md @@ -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 | diff --git a/bundles/org.openhab.binding.openwebnet/pom.xml b/bundles/org.openhab.binding.openwebnet/pom.xml index 392345816e..2d867df83c 100644 --- a/bundles/org.openhab.binding.openwebnet/pom.xml +++ b/bundles/org.openhab.binding.openwebnet/pom.xml @@ -19,7 +19,7 @@ io.github.openwebnet4j openwebnet4j - 0.12.0 + 0.13.0 compile diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java index 991d09400c..7e0f281cf1 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/OpenWebNetBindingConstants.java @@ -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"; diff --git a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java index c0e6002717..9eb2af59d7 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java +++ b/bundles/org.openhab.binding.openwebnet/src/main/java/org/openhab/binding/openwebnet/internal/handler/OpenWebNetThermoregulationHandler.java @@ -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()); } } diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties index f1b8c18200..5c34e1c5f5 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/i18n/openwebnet.properties @@ -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 diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml index e7c0815348..7e6e4b4508 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/BusThermoCentralUnit.xml @@ -27,12 +27,14 @@ + BTicino/Legrand BTicino Central Unit 3550 (99 zones) or L/N/NT/HD/HC/HS4695 (4 zones) 430 + 1 ownId diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml index 37732d63b5..3ae800b1e5 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/thing/channels.xml @@ -116,7 +116,7 @@ String - Set mode of the zone (read/write) + The zone operation mode (read/write) @@ -230,7 +230,7 @@ String - Set mode of the Central Unit (read/write) + The Central Unit operation mode (read/write) @@ -238,6 +238,8 @@ + + @@ -282,6 +284,13 @@ + + Number + + Number of days the Central Unit will be set to Antifreeze / Heat Protection target temperature before + returning to mode WEEKLY (read/write) + + String diff --git a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml index 87a1a34d12..bc53c452a3 100644 --- a/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml +++ b/bundles/org.openhab.binding.openwebnet/src/main/resources/OH-INF/update/update.xml @@ -20,4 +20,13 @@ + + + + + openwebnet:vacationDays + + + +