From 4dbb449a14516ee8d615885b4437ee0409ef0f68 Mon Sep 17 00:00:00 2001 From: ardanedh <803221+ardanedh@users.noreply.github.com> Date: Sat, 1 May 2021 14:20:46 +0200 Subject: [PATCH] [digitalSTROM] Shade angle support for GR things (#10444) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rouven Schürch --- .../discovery/SceneDiscoveryService.java | 15 +- .../internal/handler/DeviceHandler.java | 10 +- .../ZoneTemperatureControlHandler.java | 11 +- .../impl/TemperatureControlManager.java | 4 +- .../constants/JSONApiResponseKeysEnum.java | 3 + .../lib/structure/devices/Device.java | 15 +- .../constants/ApplicationGroup.java | 113 ++++++++++ .../constants/FuncNameAndColorGroupEnum.java | 115 ---------- .../constants/FunctionalColorGroupEnum.java | 102 --------- .../constants/OutputChannelEnum.java | 145 +++++++++++++ .../structure/devices/impl/DeviceImpl.java | 124 ++++++----- .../lib/structure/scene/SceneDiscovery.java | 7 +- .../internal/lib/util/DSJsonParser.java | 61 ++++++ .../providers/DsChannelTypeProvider.java | 63 +++--- .../constants/ApplicationGroupTest.java | 157 ++++++++++++++ .../constants/OutputChannelEnumTest.java | 196 ++++++++++++++++++ .../devices/impl/DeviceImplTest.java | 161 ++++++++++++++ .../internal/lib/util/DSJsonParserTest.java | 72 +++++++ .../internal/lib/util/JsonModel.java | 43 ++++ .../internal/lib/util/OutputChannel.java | 38 ++++ 20 files changed, 1138 insertions(+), 317 deletions(-) create mode 100644 bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroup.java delete mode 100644 bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FuncNameAndColorGroupEnum.java delete mode 100644 bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnum.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParser.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroupTest.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnumTest.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImplTest.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParserTest.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/JsonModel.java create mode 100644 bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/OutputChannel.java diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/SceneDiscoveryService.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/SceneDiscoveryService.java index c19557f3c..61e1ae2b8 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/SceneDiscoveryService.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/discovery/SceneDiscoveryService.java @@ -12,7 +12,10 @@ */ package org.openhab.binding.digitalstrom.internal.discovery; -import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.*; +import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.BINDING_ID; +import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.GROUP_ID; +import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.SCENE_ID; +import static org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants.ZONE_ID; import java.util.Arrays; import java.util.Date; @@ -21,7 +24,8 @@ import java.util.HashSet; import java.util.Map; import org.openhab.binding.digitalstrom.internal.handler.BridgeHandler; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.handler.SceneHandler; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum; import org.openhab.core.config.discovery.AbstractDiscoveryService; @@ -119,9 +123,10 @@ public class SceneDiscoveryService extends AbstractDiscoveryService { } private boolean ignoreGroup(Short groupID) { - if (FuncNameAndColorGroupEnum.getMode(groupID) != null) { - switch (FuncNameAndColorGroupEnum.getMode(groupID)) { - case TEMPERATION_CONTROL: + ApplicationGroup group = ApplicationGroup.getGroup(groupID); + if (group != null) { + switch (group) { + case TEMPERATURE_CONTROL: return true; default: return false; diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java index 2225d95d6..6228b2c98 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/DeviceHandler.java @@ -458,7 +458,8 @@ public class DeviceHandler extends BaseThingHandler implements DeviceStatusListe } else if (this.device.isBlind()) { // load channel for set the angle of jalousie devices String channelTypeID = DsChannelTypeProvider.getOutputChannelTypeID( - ((Device) device).getFunctionalColorGroup(), ((Device) device).getOutputMode()); + ((Device) device).getFunctionalColorGroup().getColor(), ((Device) device).getOutputMode(), + ((Device) device).getOutputChannels()); loadOutputChannel(new ChannelTypeUID(BINDING_ID, channelTypeID), DsChannelTypeProvider.getItemType(channelTypeID)); } @@ -712,10 +713,11 @@ public class DeviceHandler extends BaseThingHandler implements DeviceStatusListe if (!device.isDeviceWithOutput()) { loadOutputChannel(null, null); } - String channelTypeID = DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup(), - device.getOutputMode()); + String channelTypeID = DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup().getColor(), + device.getOutputMode(), device.getOutputChannels()); logger.debug("load channel: typeID={}, itemType={}", - DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup(), device.getOutputMode()), + DsChannelTypeProvider.getOutputChannelTypeID(device.getFunctionalColorGroup().getColor(), + device.getOutputMode(), device.getOutputChannels()), DsChannelTypeProvider.getItemType(channelTypeID)); if (channelTypeID != null && (currentChannel == null || !currentChannel.equals(channelTypeID))) { loadOutputChannel(new ChannelTypeUID(BINDING_ID, channelTypeID), diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java index f5f14771d..bb1bd17df 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/handler/ZoneTemperatureControlHandler.java @@ -29,7 +29,8 @@ import org.openhab.binding.digitalstrom.internal.lib.climate.jsonresponsecontain import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener; import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager; import org.openhab.binding.digitalstrom.internal.lib.manager.impl.TemperatureControlManager; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum; import org.openhab.binding.digitalstrom.internal.providers.DsChannelTypeProvider; import org.openhab.core.config.core.Configuration; @@ -280,14 +281,14 @@ public class ZoneTemperatureControlHandler extends BaseThingHandler implements T && (currentChannelID == null || !currentChannelID.contains(DsChannelTypeProvider.TEMPERATURE_CONTROLLED)) && !controlState.equals(ControlStates.EMERGENCY)) { - currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(FunctionalColorGroupEnum.BLUE, - OutputModeEnum.TEMPRETURE_PWM); + currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(ApplicationGroup.Color.BLUE, + OutputModeEnum.TEMPRETURE_PWM, new ArrayList()); loadChannel(); currentValue = tempControlStatus.getNominalValue(); updateState(currentChannelID, new DecimalType(currentValue.doubleValue())); } else if (!controlMode.equals(ControlModes.PID_CONTROL) && !controlMode.equals(ControlModes.OFF)) { - currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(FunctionalColorGroupEnum.BLUE, - OutputModeEnum.HEATING_PWM); + currentChannelID = DsChannelTypeProvider.getOutputChannelTypeID(ApplicationGroup.Color.BLUE, + OutputModeEnum.HEATING_PWM, new ArrayList()); loadChannel(); currentValue = tempControlStatus.getControlValue(); updateState(currentChannelID, new PercentType(fixPercent(currentValue.intValue()))); diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/TemperatureControlManager.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/TemperatureControlManager.java index 64d849d69..43163e07f 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/TemperatureControlManager.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/manager/impl/TemperatureControlManager.java @@ -30,7 +30,7 @@ import org.openhab.binding.digitalstrom.internal.lib.listener.SystemStateChangeL import org.openhab.binding.digitalstrom.internal.lib.listener.TemperatureControlStatusListener; import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager; import org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -406,7 +406,7 @@ public class TemperatureControlManager implements EventHandler, TemperatureContr public boolean pushControlValue(Integer zoneID, Float newValue) { if (checkAndGetTemperatureControlStatus(zoneID) != null) { if (dSapi.pushZoneSensorValue(connectionMananager.getSessionToken(), zoneID, null, - FuncNameAndColorGroupEnum.TEMPERATION_CONTROL.getFunctionalColorGroup(), null, newValue, + ApplicationGroup.TEMPERATURE_CONTROL.getId(), null, newValue, SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE)) { addEcho(zoneID, SensorEnum.ROOM_TEMPERATURE_CONTROL_VARIABLE, newValue); return true; diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java index 942cfcde7..46a7e3c1b 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/serverconnection/constants/JSONApiResponseKeysEnum.java @@ -103,6 +103,9 @@ public enum JSONApiResponseKeysEnum { TAGS("tags"), REVISION_ID("revisionID"), + // channel + OUTPUT_CHANNELS("outputChannels"), + // config CLASS("class"), INDEX("index"), diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Device.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Device.java index 4823ba273..b96875370 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Device.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/Device.java @@ -16,11 +16,14 @@ import java.util.List; import java.util.Map; import org.openhab.binding.digitalstrom.internal.lib.config.Config; +import org.openhab.binding.digitalstrom.internal.lib.event.constants.EventNames; import org.openhab.binding.digitalstrom.internal.lib.event.types.EventItem; +import org.openhab.binding.digitalstrom.internal.lib.sensorjobexecutor.sensorjob.impl.DeviceConsumptionSensorJob; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceSceneSpec; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID; @@ -133,14 +136,14 @@ public interface Device extends GeneralDeviceInformation { * * @return current functional color group */ - FunctionalColorGroupEnum getFunctionalColorGroup(); + ApplicationGroup getFunctionalColorGroup(); /** * Sets the functional color group of this device. * * @param fuctionalColorGroup to set */ - void setFunctionalColorGroup(FunctionalColorGroupEnum fuctionalColorGroup); + void setFunctionalColorGroup(ApplicationGroup fuctionalColorGroup); /** * Returns the current output mode of this device. @@ -152,6 +155,8 @@ public interface Device extends GeneralDeviceInformation { */ OutputModeEnum getOutputMode(); + List getOutputChannels(); + /** * Adds an increase command as {@link DeviceStateUpdate} to the list of outstanding commands. */ @@ -215,9 +220,9 @@ public interface Device extends GeneralDeviceInformation { short getMaxOutputValue(); /** - * Returns a list with group id's in which the device is part of. + * Returns a list with group ids which the device is part of. * - * @return List of group id's + * @return List of group ids */ List getGroups(); diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroup.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroup.java new file mode 100644 index 000000000..2581b3598 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroup.java @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; + +import java.util.HashMap; +import java.util.Map; + +/** + * digitalSTROM Application Groups. + * + *
+    | Group ID | Name                  | Color   | Application                         |
+    | -------- | --------------------- | ------- | ----------------------------------- |
+    | 1        | Lights                | Yellow  | Room lights                         |
+    | 2        | Blinds                | Gray    | Blinds, curtains, shades, awnings   |
+    | 3        | Heating               | Blue    | Heating                             |
+    | 9        | Cooling               | Blue    | Cooling                             |
+    | 10       | Ventilation           | Blue    | Ventilation                         |
+    | 11       | Window                | Blue    | Windows                             |
+    | 12       | Recirculation         | Blue    | Ceiling fan, Fan coil units         |
+    | 64       | Apartment Ventilation | Blue    | Ventilation system                  |
+    | 48       | Temperature Control   | Blue    | Single room temperature control     |
+    | 4        | Audio                 | Cyan    | Playing music or radio              |
+    | 5        | Video                 | Magenta | TV, Video                           |
+    | 8        | Joker                 | Black   | Configurable                        |
+    | n/a      | Single Device         | White   | Various, individual per device      |
+    | n/a      | Security              | Red     | Security related functions, Alarms  |
+    | n/a      | Access                | Green   | Access related functions, door bell |
+ * 
+ * + * @author Rouven Schürch - Initial contribution + * @see ds-basics.pdf (Version 1.4/1.6), + * chapter 3.2 (Group), Table 2. + * + */ +public enum ApplicationGroup { + + LIGHTS((short) 1, Color.YELLOW), + BLINDS((short) 2, Color.GREY), + HEATING((short) 3, Color.BLUE), + COOLING((short) 9, Color.BLUE), + VENTILATION((short) 10, Color.BLUE), + WINDOW((short) 11, Color.BLUE), + RECIRCULATION((short) 12, Color.BLUE), + APARTMENT_VENTILATION((short) 64, Color.BLUE), + TEMPERATURE_CONTROL((short) 48, Color.BLUE), + AUDIO((short) 4, Color.CYAN), + VIDEO((short) 5, Color.MAGENTA), + JOKER((short) 8, Color.BLACK), + SINGLE_DEVICE((short) -1, Color.WHITE), + SECURITY((short) -2, Color.RED), + ACCESS((short) -3, Color.GREEN), + UNDEFINED(null, Color.UNDEFINED); + + public enum Color { + YELLOW, + GREY, + BLUE, + CYAN, + MAGENTA, + BLACK, + WHITE, + RED, + GREEN, + UNDEFINED + } + + private Short groupId; + + static final Map APPLICATION_GROUPS = new HashMap<>(); + + private Color color; + + static { + for (ApplicationGroup applications : ApplicationGroup.values()) { + APPLICATION_GROUPS.put(applications.getId(), applications); + } + } + + private ApplicationGroup(Short groupId, Color color) { + this.groupId = groupId; + this.color = color; + } + + public Short getId() { + return groupId; + } + + /** + * Returns the corresponding ApplicationGroup or ApplicationGroup.UNDEFINED if + * there is no ApplicationGroup for the given groupId. + * + * @param groupId + * @return ApplicationGroup or ApplicationGroup.UNDEFINED + */ + public static ApplicationGroup getGroup(Short groupId) { + return APPLICATION_GROUPS.containsKey(groupId) ? APPLICATION_GROUPS.get(groupId) : ApplicationGroup.UNDEFINED; + } + + public Color getColor() { + return color; + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FuncNameAndColorGroupEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FuncNameAndColorGroupEnum.java deleted file mode 100644 index e8fb506ea..000000000 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FuncNameAndColorGroupEnum.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (c) 2010-2021 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; - -import java.util.HashMap; -import java.util.Map; - -/** - * The {@link FuncNameAndColorGroupEnum} contains all digitalSTROM functional group names and links to their - * {@link FunctionalColorGroupEnum}. - * - * @author Michael Ochel - Initial contribution - * @author Matthias Siegele - Initial contribution - * @see ds-basics.pdf - * "Table 1: digitalSTROM functional groups and their colors", page 9 - */ -public enum FuncNameAndColorGroupEnum { - /* - * | Number | Name | Color | Function | - * -------------------------------------------------------------------------------------- - * | 1 | Lights | Yellow | Room lights | - * | 2 | Blinds | Gray | Blinds or shades outside | - * | 12 | Curtains | Gray | Curtains and blinds inside | - * | 3 | Heating | Blue | Heating | - * | 9 | Cooling | Blue | Cooling | - * | 10 | Ventilation | Blue | Ventilation | - * | 11 | Window | Blue | Window | - * | 48 | Temperature Control | Blue | Single room temperature control | - * | 4 | Audio | Cyan | Playing music or radio | - * | 5 | Video | Magenta | TV, Video | - * | 8 | Joker | Black | Configurable behaviour | - * | n/a | Single Device | White | Various, individual per device | - * | n/a | Security | Red | Security related functions, Alarms | - * | n/a | Access | Green | Access related functions, door bell | - * - */ - LIGHTS((short) 1, FunctionalColorGroupEnum.getColorGroup((short) 1)), - BLINDS((short) 2, FunctionalColorGroupEnum.getColorGroup((short) 2)), - CURTAINS((short) 12, FunctionalColorGroupEnum.getColorGroup((short) 12)), - HEATING((short) 3, FunctionalColorGroupEnum.getColorGroup((short) 3)), - COOLING((short) 9, FunctionalColorGroupEnum.getColorGroup((short) 9)), - VENTILATION((short) 10, FunctionalColorGroupEnum.getColorGroup((short) 10)), - WINDOW((short) 11, FunctionalColorGroupEnum.getColorGroup((short) 11)), - TEMPERATION_CONTROL((short) 48, FunctionalColorGroupEnum.getColorGroup((short) 48)), - AUDIO((short) 4, FunctionalColorGroupEnum.getColorGroup((short) 4)), - VIDEO((short) 5, FunctionalColorGroupEnum.getColorGroup((short) 5)), - JOKER((short) 8, FunctionalColorGroupEnum.getColorGroup((short) 8)), - SINGLE_DEVICE((short) -1, FunctionalColorGroupEnum.getColorGroup((short) -1)), - SECURITY((short) -2, FunctionalColorGroupEnum.getColorGroup((short) -2)), - ACCESS((short) -3, FunctionalColorGroupEnum.getColorGroup((short) -3)); - - private final short colorGroup; - private final FunctionalColorGroupEnum color; - - static final Map COLOR_GROUPS = new HashMap<>(); - - static { - for (FuncNameAndColorGroupEnum colorGroup : FuncNameAndColorGroupEnum.values()) { - COLOR_GROUPS.put(colorGroup.getFunctionalColorGroup(), colorGroup); - } - } - - /** - * Returns true, if contains the given output mode id in DigitalSTROM, otherwise false. - * - * @param functionalNameGroupID to be checked - * @return true, if contains - */ - public static boolean containsColorGroup(Short functionalNameGroupID) { - return COLOR_GROUPS.keySet().contains(functionalNameGroupID); - } - - /** - * Returns the {@link FuncNameAndColorGroupEnum} of the given functional name group id. - * - * @param functionalNameGroupID of the {@link FuncNameAndColorGroupEnum} - * @return FunctionalNameAndColorGroupEnum - */ - public static FuncNameAndColorGroupEnum getMode(Short functionalNameGroupID) { - return COLOR_GROUPS.get(functionalNameGroupID); - } - - private FuncNameAndColorGroupEnum(short functionalColorGroupID, FunctionalColorGroupEnum functionalColorGroup) { - this.colorGroup = functionalColorGroupID; - this.color = functionalColorGroup; - } - - /** - * Returns the functional name group id form this Object. - * - * @return functional name group id - */ - public Short getFunctionalColorGroup() { - return colorGroup; - } - - /** - * Returns the {@link FunctionalColorGroupEnum} form this Object. - * - * @return FunctionalColorGroupEnum - */ - public FunctionalColorGroupEnum getFunctionalColor() { - return color; - } -} diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java deleted file mode 100644 index b9b6be17b..000000000 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/FunctionalColorGroupEnum.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright (c) 2010-2021 Contributors to the openHAB project - * - * See the NOTICE file(s) distributed with this work for additional - * information. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0 - * - * SPDX-License-Identifier: EPL-2.0 - */ -package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * The {@link FunctionalColorGroupEnum} contains all digitalSTROM functional color groups. - * - * @author Michael Ochel - Initial contribution - * @author Matthias Siegele - Initial contribution - * @see ds-basics.pdf, - * "Table 1: digitalSTROM functional groups and their colors", page 9 [04.09.2015] - */ -public enum FunctionalColorGroupEnum { - /* - * | Number | Name | Color | Function | - * -------------------------------------------------------------------------------------- - * | 1 | Lights | Yellow | Room lights | - * | 2 | Blinds | Gray | Blinds or shades outside | - * | 12 | Curtains | Gray | Curtains and blinds inside | - * | 3 | Heating | Blue | Heating | - * | 9 | Cooling | Blue | Cooling | - * | 10 | Ventilation | Blue | Ventilation | - * | 11 | Window | Blue | Window | - * | 48 | Temperature Control | Blue | Single room temperature control | - * | 4 | Audio | Cyan | Playing music or radio | - * | 5 | Video | Magenta | TV, Video | - * | 8 | Joker | Black | Configurable behaviour | - * | n/a | Single Device | White | Various, individual per device | - * | n/a | Security | Red | Security related functions, Alarms | - * | n/a | Access | Green | Access related functions, door bell | - * - */ - YELLOW(Arrays.asList((short) 1)), - GREY(Arrays.asList((short) 2, (short) 12)), - BLUE(Arrays.asList((short) 3, (short) 9, (short) 10, (short) 11, (short) 48)), - CYAN(Arrays.asList((short) 4)), - MAGENTA(Arrays.asList((short) 5)), - BLACK(Arrays.asList((short) 8)), - WHITE(Arrays.asList((short) -1)), - RED(Arrays.asList((short) -2)), - GREEN(Arrays.asList((short) -3)); - - private final List colorGroup; - - static final Map COLOR_GROUPS = new HashMap<>(); - - static { - for (FunctionalColorGroupEnum colorGroup : FunctionalColorGroupEnum.values()) { - for (Short colorGroupID : colorGroup.getFunctionalColorGroup()) { - COLOR_GROUPS.put(colorGroupID, colorGroup); - } - } - } - - /** - * Returns true, if contains the given functional color group id in digitalSTROM exits, otherwise false. - * - * @param functionalColorGroupID to be checked - * @return true, if contains - */ - public static boolean containsColorGroup(Short functionalColorGroupID) { - return COLOR_GROUPS.keySet().contains(functionalColorGroupID); - } - - /** - * Returns the {@link FunctionalColorGroupEnum} of the given color id. - * - * @param functionalColorGroupID of the {@link FunctionalColorGroupEnum} - * @return {@link FunctionalColorGroupEnum} of the id - */ - public static FunctionalColorGroupEnum getColorGroup(Short functionalColorGroupID) { - return COLOR_GROUPS.get(functionalColorGroupID); - } - - private FunctionalColorGroupEnum(List functionalColorGroupID) { - this.colorGroup = functionalColorGroupID; - } - - /** - * Returns the functional color group id's as {@link List} of this {@link FunctionalColorGroupEnum}. - * - * @return functional color group id's - */ - public List getFunctionalColorGroup() { - return colorGroup; - } -} diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnum.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnum.java new file mode 100644 index 000000000..c6a67233a --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnum.java @@ -0,0 +1,145 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; + +import java.util.HashMap; +import java.util.Map; + +/** + * The {@link OutputChannelEnum} lists all available digitalSTROM-device output + * channels: + * + *
+     | ID  | Description                           | Channel Name                                                         | Min | Max   | Unit                 |
+     | --- | ------------------------------------- | -------------------------------------------------------------------- | --- | ----- | -------------------- |
+     | 1   | Light Brightness                      | brightness                                                           | 0   | 100   | percent              |
+     | 2   | Colored Light Hue                     | hue                                                                  | 0   | 360   | degrees              |
+     | 3   | Colored Light Saturation              | saturation                                                           | 0   | 100   | percent              |
+     | 4   | Color Temperature                     | colortemp                                                            | 100 | 1000  | mired                |
+     | 5   | Light CIE Color Model x               | x                                                                    | 0   | 10000 | scaled to 0.0 to 1.0 |
+     | 6   | Light CIE Color Model y               | y                                                                    | 0   | 10000 | scaled to 0.0 to 1.0 |
+     | 7   | Shade Position Outside (blinds)       | shadePositionOutside                                                 | 0   | 100   | percent              |
+     | 8   | Shade Position Outside (curtains)     | shadePositionIndoor                                                  | 0   | 100   | percent              |
+     | 9   | Shade Opening Angle Outside (blinds)  | shadeOpeningAngleOutside                                             | 0   | 100   | percent              |
+     | 10  | Shade Opening Angle Indoor (curtains) | shadeOpeningAngleIndoor                                              | 0   | 100   | percent              |
+     | 11  | Transparency (e.g. smart glass)       | transparency                                                         | 0   | 100   | percent              |
+     | 12  | Air Flow Intensity                    | airFlowIntensity                                                     | 0   | 100   | percent              |
+     | 13  | Air Flow Direction                    | airFlowDirection - 0=both(undefined), 1=supply, (in),2=exhaust (out) | 0   | 2     | specific             |
+     | 14  | Flap Opening Angle                    | airFlapPosition                                                      | 0   | 100   | percent              |
+     | 15  | Ventilation Louver Position           | airLouverPosition                                                    | 0   | 100   | percent              |
+     | 16  | Heating Power                         | heatingPower                                                         | 0   | 100   | percent              |
+     | 17  | Cooling Capacity                      | coolingCapacity                                                      | 0   | 100   | percent              |
+     | 18  | Audio Volume (loudness)               | audioVolume                                                          | 0   | 100   | percent              |
+     | 19  | Power State                           | powerState - 0=powerOff, 1=powerOn, 2=forcedOff, 3=standby           | 0   | 2     | specific             |
+     | 20  | Ventilation swing mode                | airLouverAuto - 0=not active, 1=active                               | 0   | 1     | specific             |
+     | 21  | Ventilation auto intensity            | airFlowAuto - 0=not active, 1=active                                 | 0   | 1     | specific             |
+     | 22  | Water Temperature                     | waterTemperature                                                     | 0   | 150   | celsius              |
+     | 23  | Water Flow Rate                       | waterFlow                                                            | 0   | 100   | percent              |
+     | 24  | Power Level                           | powerLevel                                                           | 0   | 100   | percent              |
+ * 
+ * + * @author Rouven Schürch - Initial contribution + * @see ds-basics.pdf (Version 1.4/1.6), + * chapter + * 9.1 (Output Channel Types), Table 6: Output channel types + */ +public enum OutputChannelEnum { + + BRIGHTNESS(1, "brightness"), + HUE(2, "hue"), + SATURATION(3, "saturation"), + COLORTEMP(4, "colortemp"), + X(5, "x"), + Y(6, "y"), + SHADE_POSITION_OUTSIDE(7, "shadePositionOutside"), + SHADE_POSITION_INDOOR(8, "shadePositionIndoor"), + SHADE_OPENING_ANGLE_OUTSIDE(9, "shadeOpeningAngleOutside"), + SHADE_OPENING_ANGLE_INDOOR(10, "shadeOpeningAngleIndoor"), + TRANSPARENCY(11, "transparency"), + AIR_FLOW_INTENSITY(12, "airFlowIntensity"), + AIR_FLOW_DIRECTION(13, "airFlowDirection"), + AIR_FLAP_POSITION(14, "airFlapPosition"), + AIR_LOUVER_POSITION(15, "airLouverPosition"), + HEATING_POWER(16, "heatingPower"), + COOLING_CAPACITY(17, "coolingCapacity"), + AUDIO_VOLUME(18, "audioVolume"), + POWER_STATE(19, "powerState"), + AIR_LOUVER_AUTO(20, "airLouverAuto"), + AIR_FLOW_AUTO(21, "airFlowAuto"), + WATER_TEMPERATURE(22, "waterTemperature"), + WATER_FLOW(23, "waterFlow"), + POWER_LEVEL(24, "powerLevel"); + + private final int channelId; + + private final String name; + + static final Map OUTPUT_CHANNELS = new HashMap<>(); + + static { + for (OutputChannelEnum channels : OutputChannelEnum.values()) { + OUTPUT_CHANNELS.put(channels.getChannelId(), channels); + } + } + + /** + * Returns true, if the output channel id is contained in digitalSTROM, + * otherwise false. + * + * @param channelID to be checked + * @return true, if contains, otherwise false + */ + public static boolean containsChannel(Integer channelID) { + return OUTPUT_CHANNELS.keySet().contains(channelID); + } + + /** + * Returns the {@link OutputChannelEnum} for the given channelID, otherwise + * null. + * + * @param channelID of the {@link OutputChannelEnum} + * @return OutputChannelEnum or null + */ + public static OutputChannelEnum getChannel(Integer channelID) { + return OUTPUT_CHANNELS.get(channelID); + } + + private OutputChannelEnum(int channelId, String name) { + this.channelId = channelId; + this.name = name; + } + + /** + * Returns the id of this {@link OutputChannelEnum} object. + * + * @return mode id + */ + public int getChannelId() { + return channelId; + } + + /** + * + * @return the name of this {@link OutputChannelEnum} object. + */ + public String getName() { + return name; + } + + public static boolean isShadeChannel(OutputChannelEnum outputChannelEnum) { + return outputChannelEnum == OutputChannelEnum.SHADE_OPENING_ANGLE_INDOOR + || outputChannelEnum == OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE + || outputChannelEnum == OutputChannelEnum.SHADE_POSITION_INDOOR + || outputChannelEnum == OutputChannelEnum.SHADE_POSITION_OUTSIDE; + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java index 4f7969ca8..5d7f93768 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImpl.java @@ -33,10 +33,10 @@ import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceConstants; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceSceneSpec; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.DeviceStateUpdate; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ChangeableDeviceConfigEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FuncNameAndColorGroupEnum; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID; @@ -46,6 +46,7 @@ import org.openhab.binding.digitalstrom.internal.lib.structure.devices.devicepar import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.JSONDeviceSceneSpecImpl; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.InternalScene; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum; +import org.openhab.binding.digitalstrom.internal.lib.util.DSJsonParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,10 +68,8 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev private DSID meterDSID; private int zoneId = 0; - private List groupList = new LinkedList<>(); + private List groupList = new LinkedList<>(); - private FunctionalColorGroupEnum functionalGroup; - private FuncNameAndColorGroupEnum functionalName; private String hwInfo; private OutputModeEnum outputMode; @@ -93,6 +92,7 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev private final List deviceBinaryInputs = Collections.synchronizedList(new ArrayList<>()); private final List devicePowerSensorTypes = new ArrayList<>(); private final List deviceClimateSensorTypes = new ArrayList<>(); + private final List outputChannels = Collections.synchronizedList(new ArrayList<>()); // for scenes private short activeSceneNumber = -1; @@ -109,11 +109,11 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev private final List deviceStateUpdates = Collections.synchronizedList(new LinkedList<>()); /* - * Saves the refresh priorities and reading initialized flag of power sensors as an matrix. - * The first array fields are 0 = active power, 1 = output current, 2 = electric meter, 3 = power consumption and in - * each field is a - * string array with the fields 0 = refresh priority 1 = reading initial flag (true = reading is initialized, - * otherwise false) + * Saves the refresh priorities and reading initialized flag of power sensors as + * an matrix. The first array fields are 0 = active power, 1 = output current, 2 + * = electric meter, 3 = power consumption and in each field is a string array + * with the fields 0 = refresh priority 1 = reading initial flag (true = reading + * is initialized, otherwise false) */ private final Object[] powerSensorRefresh = new Object[] { new String[] { Config.REFRESH_PRIORITY_NEVER, "false" }, new String[] { Config.REFRESH_PRIORITY_NEVER, "false" }, @@ -128,9 +128,10 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev public static final int REFRESH_ELECTRIC_METER_ARRAY_FIELD = 2; public static final int REFRESH_POWER_CONSUMPTION_ARRAY_FIELD = 3; /* - * Cache the last power sensor value to get power sensor value directly - * the key is the output value and the value is an Integer array for the sensor values (0 = active power, 1 = - * output current, 2 = power consumption, 3 = output current high) + * Cache the last power sensor value to get power sensor value directly the key + * is the output value and the value is an Integer array for the sensor values + * (0 = active power, 1 = output current, 2 = power consumption, 3 = output + * current high) */ private final Map cachedSensorPowerValues = Collections.synchronizedMap(new HashMap<>()); @@ -139,14 +140,18 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev public static final int POWER_CONSUMPTION_ARRAY_FIELD = 2; public static final int OUTPUT_CURRENT_HIGH_ARRAY_FIELD = 3; - // Preparing for the advance device property setting "Turn 'switched' output off if value below:", but the - // configuration currently not work in digitalSTROM, because of that the value is fix 1. + // Preparing for the advance device property setting "Turn 'switched' output off + // if value below:", but the + // configuration currently not work in digitalSTROM, because of that the value + // is fix 1. private final int switchPercentOff = 1; /** - * Creates a new {@link DeviceImpl} from the given DigitalSTROM-Device {@link JsonObject}. + * Creates a new {@link DeviceImpl} from the given DigitalSTROM-Device + * {@link JsonObject}. * - * @param deviceJsonObject json response of the digitalSTROM-Server, must not be null + * @param deviceJsonObject json response of the digitalSTROM-Server, must not be + * null */ public DeviceImpl(JsonObject deviceJsonObject) { super(deviceJsonObject); @@ -178,13 +183,14 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev JsonArray array = deviceJsonObject.get(JSONApiResponseKeysEnum.GROUPS.getKey()).getAsJsonArray(); for (int i = 0; i < array.size(); i++) { if (array.get(i) != null) { - initAddGroup(array.get(i).getAsShort()); + addGroupToList(array.get(i).getAsShort()); } } } else if (groups != null && groups.isJsonObject()) { for (Entry entry : deviceJsonObject.get(JSONApiResponseKeysEnum.GROUPS.getKey()) .getAsJsonObject().entrySet()) { - initAddGroup(entry.getValue().getAsJsonObject().get(JSONApiResponseKeysEnum.ID.getKey()).getAsShort()); + addGroupToList( + entry.getValue().getAsJsonObject().get(JSONApiResponseKeysEnum.ID.getKey()).getAsShort()); } } if (deviceJsonObject.get(JSONApiResponseKeysEnum.OUTPUT_MODE.getKey()) != null) { @@ -220,24 +226,14 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev } } } + + outputChannels.addAll(DSJsonParser.getOutputChannels(deviceJsonObject)); + init(); } - private void initAddGroup(Short groupID) { - if (groupID != -1) { - this.groupList.add(groupID); - if (FuncNameAndColorGroupEnum.containsColorGroup(groupID)) { - if (this.functionalName == null - || !FuncNameAndColorGroupEnum.getMode(groupID).equals(FuncNameAndColorGroupEnum.JOKER)) { - this.functionalName = FuncNameAndColorGroupEnum.getMode(groupID); - this.functionalGroup = functionalName.getFunctionalColor(); - } - } - } - } - private void init() { - if (groupList.contains((short) 1)) { + if (groupList.contains(ApplicationGroup.LIGHTS)) { maxOutputValue = DeviceConstants.MAX_OUTPUT_VALUE_LIGHT; if (this.isDimmable()) { minOutputValue = DeviceConstants.MIN_DIM_VALUE; @@ -269,21 +265,41 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev @Override public List getGroups() { - return new LinkedList<>(groupList); + LinkedList linkedList = new LinkedList<>(); + groupList.forEach(group -> linkedList.add(group.getId())); + return linkedList; + } + + /** + * Adds the ApplicationGroup of the given groupId to the internal list + * + * @param groupID + * @return true if the groupId is a valid ApplicationGroup id, false otherwise + */ + private boolean addGroupToList(Short groupID) { + ApplicationGroup group = ApplicationGroup.getGroup(groupID); + if (ApplicationGroup.UNDEFINED.equals(group)) { + logger.warn("Unknown application group with ID '{}' found! Ignoring group", groupID); + } else { + if (!this.groupList.contains(group)) { + this.groupList.add(group); + } + } + + return group != null; } @Override public void addGroup(Short groupID) { - if (!this.groupList.contains(groupID)) { - this.groupList.add(groupID); - } + addGroupToList(groupID); informListenerAboutConfigChange(ChangeableDeviceConfigEnum.GROUPS); } @Override public void setGroups(List newGroupList) { if (newGroupList != null) { - this.groupList = newGroupList; + groupList.clear(); + newGroupList.forEach(groupId -> groupList.add(ApplicationGroup.getGroup(groupId))); } informListenerAboutConfigChange(ChangeableDeviceConfigEnum.GROUPS); } @@ -369,12 +385,12 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev @Override public boolean isHeatingDevice() { - return functionalName.equals(FuncNameAndColorGroupEnum.HEATING); + return groupList.contains(ApplicationGroup.HEATING); } @Override public boolean isTemperatureControlledDevice() { - return functionalName.equals(FuncNameAndColorGroupEnum.TEMPERATION_CONTROL); + return groupList.contains(ApplicationGroup.TEMPERATURE_CONTROL); } @Override @@ -384,17 +400,19 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev @Override public boolean isBlind() { - return outputMode.equals(OutputModeEnum.POSITION_CON_US); + return (outputMode == OutputModeEnum.POSITION_CON || outputMode == OutputModeEnum.POSITION_CON_US) + && (outputChannels.contains(OutputChannelEnum.SHADE_OPENING_ANGLE_INDOOR) + || outputChannels.contains(OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE)); } @Override - public synchronized FunctionalColorGroupEnum getFunctionalColorGroup() { - return this.functionalGroup; + public synchronized ApplicationGroup getFunctionalColorGroup() { + return groupList.stream().findFirst().get(); } @Override - public synchronized void setFunctionalColorGroup(FunctionalColorGroupEnum fuctionalColorGroup) { - this.functionalGroup = fuctionalColorGroup; + public synchronized void setFunctionalColorGroup(ApplicationGroup functionalColorGroup) { + groupList.add(functionalColorGroup); informListenerAboutConfigChange(ChangeableDeviceConfigEnum.FUNCTIONAL_GROUP); } @@ -403,6 +421,11 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev return outputMode; } + @Override + public List getOutputChannels() { + return outputChannels; + } + @Override public synchronized void setOutputMode(OutputModeEnum newOutputMode) { this.outputMode = newOutputMode; @@ -1423,7 +1446,8 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev } /** - * Checks output current sensor to return automatically high output current sensor, if the sensor exists. + * Checks output current sensor to return automatically high output current + * sensor, if the sensor exists. * * @param devSenVal * @return output current high DeviceSensorValue or the given DeviceSensorValue @@ -1655,7 +1679,8 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev } /** - * if an {@link DeviceStatusListener} is registered inform him about the new state otherwise do nothing. + * if an {@link DeviceStatusListener} is registered inform him about the new + * state otherwise do nothing. * * @param deviceStateUpdate */ @@ -1868,9 +1893,8 @@ public class DeviceImpl extends AbstractGeneralDeviceInformations implements Dev @Override public String toString() { - return "DeviceImpl [meterDSID=" + meterDSID + ", zoneId=" + zoneId + ", groupList=" + groupList - + ", functionalGroup=" + functionalGroup + ", functionalName=" + functionalName + ", hwInfo=" + hwInfo - + ", getName()=" + getName() + ", getDSID()=" + getDSID() + ", getDSUID()=" + getDSUID() + return "DeviceImpl [meterDSID=" + meterDSID + ", zoneId=" + zoneId + ", groupList=" + groupList + ", hwInfo=" + + hwInfo + ", getName()=" + getName() + ", getDSID()=" + getDSID() + ", getDSUID()=" + getDSUID() + ", isPresent()=" + isPresent() + ", isValide()=" + isValid() + ", getDisplayID()=" + getDisplayID() + ", outputMode=" + outputMode + ", getSensorTypes()=" + getSensorTypes() + ", getDeviceSensorValues()=" + getDeviceSensorValues() + ", powerSensorRefresh=" + powerSensorRefreshToString() + "]"; diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/SceneDiscovery.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/SceneDiscovery.java index 480600fef..320805008 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/SceneDiscovery.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/structure/scene/SceneDiscovery.java @@ -26,7 +26,7 @@ import org.openhab.binding.digitalstrom.internal.lib.manager.SceneManager; import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager; import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum; import org.openhab.binding.digitalstrom.internal.lib.serverconnection.impl.JSONResponseHandler; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.ApartmentSceneEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.SceneEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.scene.constants.ZoneSceneEnum; @@ -263,8 +263,9 @@ public class SceneDiscovery { groupIdInter = null; } if (groupID != null) { - if (FunctionalColorGroupEnum.getColorGroup(groupID) - .equals(FunctionalColorGroupEnum.YELLOW)) { + + if (ApplicationGroup.Color.YELLOW + .equals(ApplicationGroup.getGroup(groupID).getColor())) { discoverScene(SceneEnum.AUTO_OFF.getSceneNumber(), groupID); } String response = connectionManager.getHttpTransport() diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParser.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParser.java new file mode 100644 index 000000000..cb5c43a92 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParser.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.digitalstrom.internal.lib.serverconnection.constants.JSONApiResponseKeysEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.impl.DeviceImpl; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * digitalSTROM JSON Parser class. Externalizes code from {@link DeviceImpl} + * + * @author Rouven Schürch - Initial contribution + * + */ +@NonNullByDefault +public final class DSJsonParser { + + private DSJsonParser() { + } + + public static List getOutputChannels(JsonObject jsonObject) { + List outputChannels = new ArrayList<>(); + JsonElement jsonOutputChannels = jsonObject.get(JSONApiResponseKeysEnum.OUTPUT_CHANNELS.getKey()); + if (jsonOutputChannels != null && jsonOutputChannels.isJsonArray()) { + JsonArray array = jsonObject.get(JSONApiResponseKeysEnum.OUTPUT_CHANNELS.getKey()).getAsJsonArray(); + for (int i = 0; i < array.size(); i++) { + if (array.get(i) != null) { + int channelId = array.get(i).getAsJsonObject().get("channelID").getAsInt(); + outputChannels.add(OutputChannelEnum.getChannel(channelId)); + } + } + } else if (jsonOutputChannels != null && jsonOutputChannels.isJsonObject()) { + for (Entry entry : jsonObject.get(JSONApiResponseKeysEnum.OUTPUT_CHANNELS.getKey()) + .getAsJsonObject().entrySet()) { + int channelId = entry.getValue().getAsJsonObject().get("channelID").getAsInt(); + outputChannels.add(OutputChannelEnum.getChannel(channelId)); + } + } + + return outputChannels; + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsChannelTypeProvider.java b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsChannelTypeProvider.java index 15480e7ec..52bdb315b 100644 --- a/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsChannelTypeProvider.java +++ b/bundles/org.openhab.binding.digitalstrom/src/main/java/org/openhab/binding/digitalstrom/internal/providers/DsChannelTypeProvider.java @@ -25,10 +25,11 @@ import java.util.Locale; import java.util.Set; import org.openhab.binding.digitalstrom.internal.DigitalSTROMBindingConstants; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.ApplicationGroup; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.DeviceBinarayInputEnum; -import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.FunctionalColorGroupEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringTypeEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.MeteringUnitsEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum; import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.SensorEnum; import org.openhab.core.i18n.TranslationProvider; @@ -47,8 +48,8 @@ import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; /** - * The {@link DsChannelTypeProvider} implements the {@link ChannelTypeProvider} generates all supported - * {@link Channel}'s for digitalSTROM. + * The {@link DsChannelTypeProvider} implements the {@link ChannelTypeProvider} + * generates all supported {@link Channel}'s for digitalSTROM. * * @author Michael Ochel - Initial contribution * @author Matthias Siegele - Initial contribution @@ -57,7 +58,8 @@ import org.osgi.service.component.annotations.Reference; @Component(service = ChannelTypeProvider.class) public class DsChannelTypeProvider extends BaseDsI18n implements ChannelTypeProvider { - // channelID building (effect group type + (nothing || SEPERATOR + item type || SEPERATOR + extended item type) e.g. + // channelID building (effect group type + (nothing || SEPERATOR + item type || + // SEPERATOR + extended item type) e.g. // light_switch, shade or shade_angle // channel effect group type public static final String LIGHT = "light"; // and tag @@ -112,34 +114,40 @@ public class DsChannelTypeProvider extends BaseDsI18n implements ChannelTypeProv public static final String CATEGORY_MOTION = "Motion"; /** - * Returns the output channel type id as {@link String} for the given {@link FunctionalColorGroupEnum} and - * {@link OutputModeEnum} or null, if no channel type exists for the given {@link FunctionalColorGroupEnum} and + * Returns the output channel type id as {@link String} for the given + * {@link ApplicationGroup.Color} and {@link OutputModeEnum} or null, if no + * channel type exists for the given {@link ApplicationGroup.Color} and * {@link OutputModeEnum}. * * @param functionalGroup of the {@link Device} * @param outputMode of the {@link Device} * @return the output channel type id or null */ - public static String getOutputChannelTypeID(FunctionalColorGroupEnum functionalGroup, OutputModeEnum outputMode) { + public static String getOutputChannelTypeID(ApplicationGroup.Color functionalGroup, OutputModeEnum outputMode, + List outputChannels) { if (functionalGroup != null && outputMode != null) { String channelPreID = GENERAL; - if (functionalGroup.equals(FunctionalColorGroupEnum.YELLOW)) { - channelPreID = LIGHT; - } - if (functionalGroup.equals(FunctionalColorGroupEnum.GREY)) { - if (outputMode.equals(OutputModeEnum.POSITION_CON)) { - return buildIdentifier(SHADE); - } - if (outputMode.equals(OutputModeEnum.POSITION_CON_US)) { - return buildIdentifier(SHADE, ANGLE); - } - } - if (functionalGroup.equals(FunctionalColorGroupEnum.BLUE)) { - channelPreID = HEATING; - if (OutputModeEnum.outputModeIsTemperationControlled(outputMode)) { - return buildIdentifier(channelPreID, TEMPERATURE_CONTROLLED); - } + + switch (functionalGroup) { + case YELLOW: + channelPreID = LIGHT; + break; + case GREY: + if (outputChannels != null && (outputChannels.contains(OutputChannelEnum.SHADE_OPENING_ANGLE_INDOOR) + || outputChannels.contains(OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE))) { + return buildIdentifier(SHADE, ANGLE); + } else { + return buildIdentifier(SHADE); + } + case BLUE: + channelPreID = HEATING; + if (OutputModeEnum.outputModeIsTemperationControlled(outputMode)) { + return buildIdentifier(channelPreID, TEMPERATURE_CONTROLLED); + } + default: + break; } + if (OutputModeEnum.outputModeIsSwitch(outputMode)) { return buildIdentifier(channelPreID, SWITCH); } @@ -324,7 +332,8 @@ public class DsChannelTypeProvider extends BaseDsI18n implements ChannelTypeProv } private StateDescriptionFragment getSensorStateDescription(SensorEnum sensorType) { - // the digitalSTROM resolution for temperature in kelvin is not correct but sensor-events and cached values are + // the digitalSTROM resolution for temperature in kelvin is not correct but + // sensor-events and cached values are // shown in °C so we will use this unit for temperature sensors String unitShortCut = sensorType.getUnitShortcut(); if (unitShortCut.equals("%")) { @@ -424,7 +433,8 @@ public class DsChannelTypeProvider extends BaseDsI18n implements ChannelTypeProv } /** - * Returns the supported item type for the given channel type id or null, if the channel type does not exist. + * Returns the supported item type for the given channel type id or null, if the + * channel type does not exist. * * @param channelTypeID of the channel * @return item type or null @@ -542,7 +552,8 @@ public class DsChannelTypeProvider extends BaseDsI18n implements ChannelTypeProv } /** - * Returns the {@link ChannelGroupTypeUID} for the given {@link DeviceBinarayInputEnum}. + * Returns the {@link ChannelGroupTypeUID} for the given + * {@link DeviceBinarayInputEnum}. * * @param binaryInputType (must not be null) * @return the channel type uid diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroupTest.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroupTest.java new file mode 100644 index 000000000..e5a354080 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/ApplicationGroupTest.java @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +/** + * Test class for {@link ApplicationGroup} + * + * @author Rouven Schürch - Initial contribution + * + */ +@ExtendWith(MockitoExtension.class) +@NonNullByDefault +class ApplicationGroupTest { + + @Test + void test1LightsYellow() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 1); + assertThat(group.getColor(), is(ApplicationGroup.Color.YELLOW)); + assertThat(group, is(ApplicationGroup.LIGHTS)); + } + + @Test + void test2BlindsGray() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 2); + assertThat(group.getColor(), is(ApplicationGroup.Color.GREY)); + assertThat(group, is(ApplicationGroup.BLINDS)); + } + + @Test + void test3HeatingBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 3); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.HEATING)); + } + + @Test + void test9CoolingBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 9); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.COOLING)); + } + + @Test + void test10VentilationBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 10); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.VENTILATION)); + } + + @Test + void test11WindowBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 11); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.WINDOW)); + } + + @Test + void test12RecirculationBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 12); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.RECIRCULATION)); + } + + @Test + void test64ApartmentVentilationBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 64); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.APARTMENT_VENTILATION)); + } + + @Test + void test48TemperatureControlBlue() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 48); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLUE)); + assertThat(group, is(ApplicationGroup.TEMPERATURE_CONTROL)); + } + + @Test + void test4AudioCyan() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 4); + assertThat(group.getColor(), is(ApplicationGroup.Color.CYAN)); + assertThat(group, is(ApplicationGroup.AUDIO)); + } + + @Test + void test5VideoMagenta() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 5); + assertThat(group.getColor(), is(ApplicationGroup.Color.MAGENTA)); + assertThat(group, is(ApplicationGroup.VIDEO)); + } + + @Test + void test8JokerBlack() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 8); + assertThat(group.getColor(), is(ApplicationGroup.Color.BLACK)); + assertThat(group, is(ApplicationGroup.JOKER)); + } + + @Test + void testNASingleDeviceWhite() { + ApplicationGroup group = ApplicationGroup.getGroup((short) -1); + assertThat(group.getColor(), is(ApplicationGroup.Color.WHITE)); + assertThat(group, is(ApplicationGroup.SINGLE_DEVICE)); + } + + @Test + void testNASecurityRed() { + ApplicationGroup group = ApplicationGroup.getGroup((short) -2); + assertThat(group.getColor(), is(ApplicationGroup.Color.RED)); + assertThat(group, is(ApplicationGroup.SECURITY)); + } + + @Test + void testNAAccessGreen() { + ApplicationGroup group = ApplicationGroup.getGroup((short) -3); + assertThat(group.getColor(), is(ApplicationGroup.Color.GREEN)); + assertThat(group, is(ApplicationGroup.ACCESS)); + } + + @Test + void testUndefinedGroup100() { + ApplicationGroup group = ApplicationGroup.getGroup((short) 100); + assertThat(group.getColor(), is(ApplicationGroup.Color.UNDEFINED)); + assertThat(group, is(ApplicationGroup.UNDEFINED)); + } + + @Test + void testUndefinedGroupNull() { + ApplicationGroup group = ApplicationGroup.getGroup(null); + assertThat(group.getColor(), is(ApplicationGroup.Color.UNDEFINED)); + assertThat(group, is(ApplicationGroup.UNDEFINED)); + } + + @Test + void testGetShortId() { + Short id = ApplicationGroup.BLINDS.getId(); + assertThat(ApplicationGroup.getGroup(id).getId(), is(id)); + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnumTest.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnumTest.java new file mode 100644 index 000000000..acb73d314 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/deviceparameters/constants/OutputChannelEnumTest.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; + +/** + * Test class for {@link OutputChannelEnum} + * + * @author Rouven Schürch - Initial contribution + * + */ +@NonNullByDefault +class OutputChannelEnumTest { + @Test + void test1LightBrightness() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(1); + assertThat(outputChannel, is(OutputChannelEnum.BRIGHTNESS)); + assertThat(outputChannel.getName(), is("brightness")); + } + + @Test + void test2Hue() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(2); + assertThat(outputChannel, is(OutputChannelEnum.HUE)); + assertThat(outputChannel.getName(), is("hue")); + } + + @Test + void test3Saturation() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(3); + assertThat(outputChannel, is(OutputChannelEnum.SATURATION)); + assertThat(outputChannel.getName(), is("saturation")); + } + + @Test + void test4Colortemp() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(4); + assertThat(outputChannel, is(OutputChannelEnum.COLORTEMP)); + assertThat(outputChannel.getName(), is("colortemp")); + } + + @Test + void test5X() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(5); + assertThat(outputChannel, is(OutputChannelEnum.X)); + assertThat(outputChannel.getName(), is("x")); + } + + @Test + void test6Y() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(6); + assertThat(outputChannel, is(OutputChannelEnum.Y)); + assertThat(outputChannel.getName(), is("y")); + } + + @Test + void test7ShadePositionOutside() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(7); + assertThat(outputChannel, is(OutputChannelEnum.SHADE_POSITION_OUTSIDE)); + assertThat(outputChannel.getName(), is("shadePositionOutside")); + } + + @Test + void test8ShadePositionIndoor() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(8); + assertThat(outputChannel, is(OutputChannelEnum.SHADE_POSITION_INDOOR)); + assertThat(outputChannel.getName(), is("shadePositionIndoor")); + } + + @Test + void test9ShadeOpeningAngleOutside() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(9); + assertThat(outputChannel, is(OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE)); + assertThat(outputChannel.getName(), is("shadeOpeningAngleOutside")); + } + + @Test + void test10ShadeOpeningAngleIndoor() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(10); + assertThat(outputChannel, is(OutputChannelEnum.SHADE_OPENING_ANGLE_INDOOR)); + assertThat(outputChannel.getName(), is("shadeOpeningAngleIndoor")); + } + + @Test + void test11Transparency() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(11); + assertThat(outputChannel, is(OutputChannelEnum.TRANSPARENCY)); + assertThat(outputChannel.getName(), is("transparency")); + } + + @Test + void test12AirFlowIntensity() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(12); + assertThat(outputChannel, is(OutputChannelEnum.AIR_FLOW_INTENSITY)); + assertThat(outputChannel.getName(), is("airFlowIntensity")); + } + + @Test + void test13AirFlowDirection() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(13); + assertThat(outputChannel, is(OutputChannelEnum.AIR_FLOW_DIRECTION)); + assertThat(outputChannel.getName(), is("airFlowDirection")); + } + + @Test + void test14AirFlapPosition() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(14); + assertThat(outputChannel, is(OutputChannelEnum.AIR_FLAP_POSITION)); + assertThat(outputChannel.getName(), is("airFlapPosition")); + } + + @Test + void test15AirLouverPosition() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(15); + assertThat(outputChannel, is(OutputChannelEnum.AIR_LOUVER_POSITION)); + assertThat(outputChannel.getName(), is("airLouverPosition")); + } + + @Test + void test16HeatingPower() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(16); + assertThat(outputChannel, is(OutputChannelEnum.HEATING_POWER)); + assertThat(outputChannel.getName(), is("heatingPower")); + } + + @Test + void test17CoolingCapacity() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(17); + assertThat(outputChannel, is(OutputChannelEnum.COOLING_CAPACITY)); + assertThat(outputChannel.getName(), is("coolingCapacity")); + } + + @Test + void test18AudioVolume() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(18); + assertThat(outputChannel, is(OutputChannelEnum.AUDIO_VOLUME)); + assertThat(outputChannel.getName(), is("audioVolume")); + } + + @Test + void test19PowerState() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(19); + assertThat(outputChannel, is(OutputChannelEnum.POWER_STATE)); + assertThat(outputChannel.getName(), is("powerState")); + } + + @Test + void test20AirLouverAuto() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(20); + assertThat(outputChannel, is(OutputChannelEnum.AIR_LOUVER_AUTO)); + assertThat(outputChannel.getName(), is("airLouverAuto")); + } + + @Test + void test21AirFlowAuto() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(21); + assertThat(outputChannel, is(OutputChannelEnum.AIR_FLOW_AUTO)); + assertThat(outputChannel.getName(), is("airFlowAuto")); + } + + @Test + void test22WaterTemperature() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(22); + assertThat(outputChannel, is(OutputChannelEnum.WATER_TEMPERATURE)); + assertThat(outputChannel.getName(), is("waterTemperature")); + } + + @Test + void test23WaterFlow() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(23); + assertThat(outputChannel, is(OutputChannelEnum.WATER_FLOW)); + assertThat(outputChannel.getName(), is("waterFlow")); + } + + @Test + void test24PowerLevel() { + OutputChannelEnum outputChannel = OutputChannelEnum.getChannel(24); + assertThat(outputChannel, is(OutputChannelEnum.POWER_LEVEL)); + assertThat(outputChannel.getName(), is("powerLevel")); + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImplTest.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImplTest.java new file mode 100644 index 000000000..b3ea80a65 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/structure/devices/impl/DeviceImplTest.java @@ -0,0 +1,161 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.structure.devices.impl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputModeEnum; +import org.openhab.binding.digitalstrom.internal.lib.util.JsonModel; +import org.openhab.binding.digitalstrom.internal.lib.util.OutputChannel; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * Test class for certain code in {@link DeviceImpl} + * + * @author Rouven Schürch - Initial contribution + * + */ +@ExtendWith(MockitoExtension.class) +@NonNullByDefault +class DeviceImplTest { + + private static final List EMPTY_CHANNEL = new ArrayList<>(); + + private static final List SHADE_ANGLE_CHANNELS = Arrays.asList( + new OutputChannel(OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE), + new OutputChannel(OutputChannelEnum.SHADE_OPENING_ANGLE_INDOOR)); + + private static final List SHADE_POSITION_CHANNELS = Arrays.asList( + new OutputChannel(OutputChannelEnum.SHADE_POSITION_INDOOR), + new OutputChannel(OutputChannelEnum.SHADE_POSITION_OUTSIDE)); + + private static final List NON_SHADE_CHANNEL = Arrays + .asList(new OutputChannel(OutputChannelEnum.BRIGHTNESS)); + + private static final List MIXED_SHADE_CHANNEL = Arrays.asList( + new OutputChannel(OutputChannelEnum.BRIGHTNESS), + new OutputChannel(OutputChannelEnum.SHADE_OPENING_ANGLE_OUTSIDE)); + + @Test + void isBlindSwitchShadeChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.SINGLE_SWITCH, SHADE_ANGLE_CHANNELS); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindSwitchNoShadeChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.SINGLE_SWITCH, NON_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindSwitchMixedShadeChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.SINGLE_SWITCH, MIXED_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConUsNoChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON_US, EMPTY_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConUsNonShadeChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON_US, NON_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConUsShadePositionChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON_US, SHADE_POSITION_CHANNELS); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConUsShadeAngleChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON_US, SHADE_ANGLE_CHANNELS); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(true)); + } + + @Test + void isBlindPositionConUsMixedChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON_US, MIXED_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(true)); + } + + @Test + void isBlindPositionConNoChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON, EMPTY_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConNonShadeChannel() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON, NON_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConShadePositionChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON, SHADE_POSITION_CHANNELS); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(false)); + } + + @Test + void isBlindPositionConShadeAngleChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON, SHADE_ANGLE_CHANNELS); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(true)); + } + + @Test + void isBlindPositionConMixedChannels() { + JsonObject jsonObject = createJsonObject(OutputModeEnum.POSITION_CON, MIXED_SHADE_CHANNEL); + DeviceImpl deviceImpl = new DeviceImpl(jsonObject); + assertThat(deviceImpl.isBlind(), is(true)); + } + + private static JsonObject createJsonObject(OutputModeEnum outputMode, List channels) { + JsonModel model = new JsonModel(outputMode.getMode(), channels); + + Gson gson = new Gson(); + String json = gson.toJson(model); + + return JsonParser.parseString(json).getAsJsonObject(); + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParserTest.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParserTest.java new file mode 100644 index 000000000..57ec1092a --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/DSJsonParserTest.java @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.util; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; + +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +/** + * Test class for {@link DSJsonParser} + * + * @author Rouven Schürch - Initial contribution + * + */ +@NonNullByDefault +class DSJsonParserTest { + + @Test + void testParseSingleOutputchannels() { + JsonObject jsonObject = createJsonObject(Arrays.asList(new OutputChannel(OutputChannelEnum.BRIGHTNESS))); + + List channels = DSJsonParser.getOutputChannels(jsonObject); + assertThat(channels, contains(OutputChannelEnum.BRIGHTNESS)); + } + + @Test + void testParseMultipleOutputchannels() { + JsonObject jsonObject = createJsonObject(Arrays.asList(new OutputChannel(OutputChannelEnum.BRIGHTNESS), + new OutputChannel(OutputChannelEnum.AIR_FLAP_POSITION))); + + List channels = DSJsonParser.getOutputChannels(jsonObject); + assertThat(channels, contains(OutputChannelEnum.BRIGHTNESS, OutputChannelEnum.AIR_FLAP_POSITION)); + } + + @Test + void testParseNoOutputchannels() { + JsonObject jsonObject = createJsonObject(Arrays.asList()); + List channels = DSJsonParser.getOutputChannels(jsonObject); + assertThat(channels, hasSize(0)); + } + + private static JsonObject createJsonObject(List channels) { + JsonModel model = new JsonModel(channels); + + Gson gson = new Gson(); + String json = gson.toJson(model); + + return JsonParser.parseString(json).getAsJsonObject(); + } +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/JsonModel.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/JsonModel.java new file mode 100644 index 000000000..b0a459253 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/JsonModel.java @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.util; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Model used in test cases. + * + * @author Rouven Schürch - Initial contribution + * + */ +@NonNullByDefault +public class JsonModel { + public JsonModel(List outputChannels) { + this(-1, outputChannels); + } + + public JsonModel(int outputMode, List outputChannels) { + this.outputMode = outputMode; + this.outputChannels = new ArrayList<>(); + if (outputChannels != null) { + this.outputChannels = outputChannels; + } + } + + int outputMode; + + List outputChannels; +} diff --git a/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/OutputChannel.java b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/OutputChannel.java new file mode 100644 index 000000000..4b07de504 --- /dev/null +++ b/bundles/org.openhab.binding.digitalstrom/src/test/java/org/openhab/binding/digitalstrom/internal/lib/util/OutputChannel.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.digitalstrom.internal.lib.util; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.constants.OutputChannelEnum; + +/** + * Model used in test cases. + * + * @author Rouven Schürch - Initial contribution + * + */ +@NonNullByDefault +public class OutputChannel { + public OutputChannel(OutputChannelEnum outputChannel) { + super(); + this.channelID = outputChannel.getChannelId(); + this.name = outputChannel.getName(); + this.id = outputChannel.getName(); + this.index = outputChannel.getChannelId(); + } + + int channelID; + String name; + String id; + int index; +}