]> git.basschouten.com Git - openhab-addons.git/commitdiff
[enocean] Added support for Heat Recovery Ventilation devices (#9465) (#9468)
authorDaniel Weber <25605184+fruggy83@users.noreply.github.com>
Thu, 4 Feb 2021 06:18:35 +0000 (07:18 +0100)
committerGitHub <noreply@github.com>
Thu, 4 Feb 2021 06:18:35 +0000 (22:18 -0800)
* [enocean] Added support for Heat Recovery Ventilation devices (#9465)

 * Implemented EEP family D2_50
 * Added new thing type (heatRecoveryVentilation) and channels for heat recovery ventilation units

Fixes #9465

* [enocean] Added support for Heat Recovery Ventilation devices (#9465)

 * code refactoring (JAVA11 improvements)

Fixes #9465

* [enocean] Added support for Heat Recovery Ventilation devices (#9465)

 * Removed unnecessary EEP classes
 * Made final fields static
 * Added @NonNullByDefault to EEP Class

Fixes #9465

* [enocean] Added support for Heat Recovery Ventilation devices (#9465)

 * Removed @NonNullByDefault to not mess up PR with non related changes

Fixes #9465

Signed-off-by: Daniel Weber <uni@fruggy.de>
bundles/org.openhab.binding.enocean/README.md
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/Helper.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_50/D2_50.java [new file with mode: 0644]
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseActuatorHandler.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBridgeHandler.java
bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanClassicDeviceHandler.java
bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/HeatRecoveryVentilation.xml [new file with mode: 0644]
bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml

index 69dc3cb32bc9acd5081ed9de97e21cb15d217dc6..e6ff99b0a1686b2cc2c61a5e3c8b9923a0f1011f 100644 (file)
@@ -90,6 +90,7 @@ Hence if your device supports one of the following EEPs the chances are good tha
 | rollershutter                   | A5-3F/D2-05/A5-38 | 0x7F/00/08 | rollershutter             | Eltako FSB14, NodOn SIN-2-RS-01| Teach-in/Discovery |
 | measurementSwitch               | D2-01       | 0x00-0F,11,12 | generalSwitch(/A/B), instantpower,<br/>totalusage, repeaterMode | NodOn In Wall Switch | Discovery |
 | multiFunctionSmokeDetector      | D2-14/F6-05 | 0x30/02       | smokeDetection, batteryLow   | Insafe+, Afriso ASD | Discovery |
+| heatRecoveryVentilation         | D2-50       | 0x00,01,10,11 | a lot of different state channels | Dimplex DL WE2 | Discovery |
 | classicDevice                   | F6-02       | 0x01-02       | virtualRockerswitchA, virtualRockerswitchB | - | Teach-in |
 
 ยน Not all channels are supported by all devices, it depends which specific EEP type is used by the device, all thing types additionally support `rssi`, `repeatCount` and `lastReceived` channels
@@ -210,6 +211,12 @@ If you change the SenderId of your thing, you have to pair again the thing with
 |                                 | suppressRepeating |                             | true, false |
 | multiFunctionSmokeDetector      | receivingEEPId    |                             | F6_05_02, D2_14_30 |
 |                                 | enoceanId         | | |
+| heatRecoveryVentilation         | senderIdOffset    |                             | 1-127 |
+|                                 | enoceanId         | | |
+|                                 | sendingEEPId      |                             | D2_50_00, D2_50_01,<br/>D2_50_10, D2_50_11 |
+|                                 | receivingEEPId    |                             | D2_50_00, D2_50_01,<br/>D2_50_10, D2_50_11 |
+|                                 | broadcastMessages |                             | true, false |
+|                                 | suppressRepeating |                             | true, false |
 | classicDevice                   | senderIdOffset    |                             | 1-127 |
 |                                 | sendingEEPId      |                             | F6_02_01, F6_02_02 |
 |                                 | broadcastMessages |                             | true, false |
@@ -267,6 +274,29 @@ The channels of a thing are determined automatically based on the chosen EEP.
 | remainingPLT         | Number:Time        | Remaining product life time |
 | hygroComfortIndex    | String             | Hygrothermal Comfort Index |
 | indoorAirAnalysis    | String             | Indoor Air Analysis |
+| ventilationOperationMode | String         | Direct Operation Mode Control |
+| fireplaceSafetyMode  | Switch             | Fireplace Safety Mode |
+| heatExchangerBypassStatus | Contact       | Heat Exchanger Bypass Status |
+| supplyAirFlapStatus  | Contact            | Supply Air Flap Position |
+| exhaustAirFlapStatus | Contact            | Exhaust Air Flap Position |
+| defrostMode          | Switch             | Defrost Mode |
+| coolingProtectionMode | Switch            | Cooling Protection Mode |
+| outdoorAirHeaterStatus | Switch           | Outdoor Air Heater Status |
+| supplyAirHeaterStatus | Switch            | Supply Air Heater Status |
+| drainHeaterStatus    | Switch             | Drain Heater Status |
+| timerOperationMode   | Switch             | Timer Operation Mode |
+| weeklyTimerProgramStatus | Switch         | Weekly Timer Program Status |
+| roomTemperatureControlStatus | Switch     | Room Temperature Control Status |
+| airQualityValue1     | Number:Dimensionless | Air Quality Value in percent |
+| airQualityValue2     | Number:Dimensionless | Air Quality Value in percent |
+| outdoorAirTemperature | Number:Temperature | Outdoor Temperature |
+| supplyAirTemperature | Number:Temperature | Supply Air Temperature |
+| indoorAirTemperature | Number:Temperature | Indoor Temperature |
+| exhaustAirTemperature | Number:Temperature | Exhaust Air Temperature |
+| supplyAirFanAirFlowRate | Number:VolumetricFlowRate | Supply Air Fan Air Flow Rate |
+| exhaustAirFanAirFlowRate | Number:VolumetricFlowRate | Exhaust Air Fan Air Flow Rate |
+| supplyFanSpeed       | Number:Dimensionless | Supply Fan Speed in rpm |
+| exhaustFanSpeed      | Number:Dimensionless | Exhaust Fan Speed |
 | rssi                 | Number                   | Received Signal Strength Indication (dBm) of last received message |
 | repeatCount          | Number                   | Number of repeaters involved in the transmission of the telegram |
 | lastReceived         | DateTime                 | Date and time the last telegram was received |
index b8dc0cca9d7f3072b576f3d10195e47e26ba6acf..4ae4bf2240bcac6ae1601c88a1f8cde39467991b 100644 (file)
  */
 package org.openhab.binding.enocean.internal;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
 import javax.measure.quantity.Angle;
+import javax.measure.quantity.Dimensionless;
 import javax.measure.quantity.ElectricPotential;
 import javax.measure.quantity.Energy;
 import javax.measure.quantity.Illuminance;
@@ -78,13 +75,16 @@ public class EnOceanBindingConstants {
     public static final ThingTypeUID THING_TYPE_MULTFUNCTIONSMOKEDETECTOR = new ThingTypeUID(BINDING_ID,
             "multiFunctionSmokeDetector");
 
-    public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = new HashSet<>(Arrays.asList(
-            THING_TYPE_PUSHBUTTON, THING_TYPE_ROCKERSWITCH, THING_TYPE_CLASSICDEVICE, THING_TYPE_CENTRALCOMMAND,
-            THING_TYPE_ROOMOPERATINGPANEL, THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT,
-            THING_TYPE_MEASUREMENTSWITCH, THING_TYPE_TEMPERATURESENSOR, THING_TYPE_TEMPERATUREHUMIDITYSENSOR,
-            THING_TYPE_GENERICTHING, THING_TYPE_ROLLERSHUTTER, THING_TYPE_OCCUPANCYSENSOR,
-            THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR, THING_TYPE_ENVIRONMENTALSENSOR,
-            THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_THERMOSTAT, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR));
+    public static final ThingTypeUID THING_TYPE_HEATRECOVERYVENTILATION = new ThingTypeUID(BINDING_ID,
+            "heatRecoveryVentilation");
+
+    public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(THING_TYPE_PUSHBUTTON,
+            THING_TYPE_ROCKERSWITCH, THING_TYPE_CLASSICDEVICE, THING_TYPE_CENTRALCOMMAND, THING_TYPE_ROOMOPERATINGPANEL,
+            THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT, THING_TYPE_MEASUREMENTSWITCH, THING_TYPE_TEMPERATURESENSOR,
+            THING_TYPE_TEMPERATUREHUMIDITYSENSOR, THING_TYPE_GENERICTHING, THING_TYPE_ROLLERSHUTTER,
+            THING_TYPE_OCCUPANCYSENSOR, THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR,
+            THING_TYPE_ENVIRONMENTALSENSOR, THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_THERMOSTAT,
+            THING_TYPE_MULTFUNCTIONSMOKEDETECTOR, THING_TYPE_HEATRECOVERYVENTILATION);
 
     // List of all Channel Type Ids, these type ids are also used as channel ids during dynamic creation of channels
     // this makes it a lot easier as we do not have to manage a type id and an id, drawback long channel names
@@ -179,215 +179,356 @@ public class EnOceanBindingConstants {
     public static final String CHANNEL_STATUS_REQUEST_EVENT = "statusRequestEvent";
     public static final String CHANNEL_SEND_COMMAND = "sendCommand";
 
-    public static final Map<String, EnOceanChannelDescription> CHANNELID2CHANNELDESCRIPTION = Collections
-            .unmodifiableMap(new HashMap<String, EnOceanChannelDescription>() {
-                private static final long serialVersionUID = 1L;
-
-                {
-                    put(CHANNEL_GENERAL_SWITCHING, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHING), CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_GENERAL_SWITCHINGA, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHINGA), CoreItemFactory.SWITCH));
-                    put(CHANNEL_GENERAL_SWITCHINGB, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHINGB), CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_DIMMER, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DIMMER),
-                            CoreItemFactory.DIMMER));
-                    put(CHANNEL_ROLLERSHUTTER, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_ROLLERSHUTTER), CoreItemFactory.ROLLERSHUTTER));
-                    put(CHANNEL_ANGLE, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ANGLE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Angle.class.getSimpleName()));
-                    put(CHANNEL_TEMPERATURE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName()));
-                    put(CHANNEL_HUMIDITY, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_HUMIDITY), CoreItemFactory.NUMBER));
-                    put(CHANNEL_FANSPEEDSTAGE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_FANSPEEDSTAGE), CoreItemFactory.STRING));
-                    put(CHANNEL_OCCUPANCY, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_OCCUPANCY), CoreItemFactory.SWITCH));
-                    put(CHANNEL_MOTIONDETECTION, new EnOceanChannelDescription(
-                            DefaultSystemChannelTypeProvider.SYSTEM_MOTION.getUID(), CoreItemFactory.SWITCH));
-                    put(CHANNEL_VIBRATION, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_VIBRATION), CoreItemFactory.SWITCH));
-                    put(CHANNEL_ILLUMINATION, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATION),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName()));
-                    put(CHANNEL_ILLUMINATIONWEST, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONWEST),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName()));
-                    put(CHANNEL_ILLUMINATIONSOUTHNORTH, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONSOUTHNORTH),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName()));
-                    put(CHANNEL_ILLUMINATIONEAST, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONEAST),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName()));
-                    put(CHANNEL_WINDSPEED, new EnOceanChannelDescription(
-                            DefaultSystemChannelTypeProvider.SYSTEM_WIND_SPEED.getUID(),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Speed.class.getSimpleName()));
-                    put(CHANNEL_RAINSTATUS, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_RAINSTATUS), CoreItemFactory.SWITCH));
-                    put(CHANNEL_COUNTER, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_COUNTER),
-                            CoreItemFactory.NUMBER));
-                    put(CHANNEL_CURRENTNUMBER, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_CURRENTNUMBER), CoreItemFactory.NUMBER));
-                    put(CHANNEL_SMOKEDETECTION, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SMOKEDETECTION), CoreItemFactory.SWITCH));
-                    put(CHANNEL_SENSORFAULT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT), CoreItemFactory.SWITCH));
-                    put(CHANNEL_MAINTENANCESTATUS, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT), CoreItemFactory.SWITCH));
-                    put(CHANNEL_SENSORANALYSISHUMIDITYRANGE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT), CoreItemFactory.SWITCH));
-                    put(CHANNEL_SENSORANALYSISTEMPERATURRANGE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT), CoreItemFactory.SWITCH));
-                    put(CHANNEL_TIMESINCELASTMAINTENANCE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TIMESINCELASTMAINTENANCE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Time.class.getSimpleName()));
-                    put(CHANNEL_REMAININGPLT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_REMAININGPLT),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Time.class.getSimpleName()));
-                    put(CHANNEL_HYGROCOMFORTINDEX, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_HYGROCOMFORTINDEX), CoreItemFactory.STRING));
-                    put(CHANNEL_INDOORAIRANALYSIS, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_INDOORAIRANALYSIS), CoreItemFactory.STRING));
-                    put(CHANNEL_SETPOINT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SETPOINT), CoreItemFactory.NUMBER));
-                    put(CHANNEL_CONTACT, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CONTACT),
-                            CoreItemFactory.CONTACT));
-                    put(CHANNEL_WINDOWHANDLESTATE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWHANDLESTATE), CoreItemFactory.STRING));
-                    put(CHANNEL_BATTERY_VOLTAGE,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_BATTERY_VOLTAGE),
-                                    CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
-                                            + ElectricPotential.class.getSimpleName()));
-                    put(CHANNEL_ENERGY_STORAGE,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ENERGY_STORAGE),
-                                    CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
-                                            + ElectricPotential.class.getSimpleName()));
-                    put(CHANNEL_BATTERY_LEVEL,
-                            new EnOceanChannelDescription(
-                                    DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_BATTERY_LEVEL.getUID(),
-                                    CoreItemFactory.NUMBER));
-                    put(CHANNEL_BATTERYLOW,
-                            new EnOceanChannelDescription(
-                                    DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_LOW_BATTERY.getUID(),
-                                    CoreItemFactory.SWITCH));
-                    put(CHANNEL_TEACHINCMD, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TEACHINCMD), CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_PUSHBUTTON,
-                            new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(),
-                                    null, "Push button", false, true));
-                    put(CHANNEL_DOUBLEPRESS,
-                            new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(),
-                                    null, "Double press", false, true));
-                    put(CHANNEL_LONGPRESS,
-                            new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(),
-                                    null, "Long press", false, true));
-
-                    put(CHANNEL_ROCKERSWITCH_CHANNELA,
-                            new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(),
-                                    null, "Rocker Switch - Channel A", false, false));
-                    put(CHANNEL_ROCKERSWITCH_CHANNELB,
-                            new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(),
-                                    null, "Rocker Switch - Channel B", false, false));
-
-                    put(CHANNEL_VIRTUALSWITCHA,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALSWITCHA),
-                                    CoreItemFactory.SWITCH, "", true, false));
-                    put(CHANNEL_VIRTUALROLLERSHUTTERA,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALROLLERSHUTTERA),
-                                    CoreItemFactory.ROLLERSHUTTER, "", true, false));
-                    put(CHANNEL_VIRTUALROCKERSWITCHB,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALROCKERSWITCHB),
-                                    CoreItemFactory.STRING, "Rocker Switch - Channel B", true, false));
-                    put(CHANNEL_ROCKERSWITCHLISTENERSWITCH,
-                            new EnOceanChannelDescription(
-                                    new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCHLISTENERSWITCH),
-                                    CoreItemFactory.SWITCH, "Rocker Switch Listener (Switch)", true, false));
-                    put(CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER, new EnOceanChannelDescription(
+    public static final String CHANNEL_VENTILATIONOPERATIONMODE = "ventilationOperationMode";
+    public static final String CHANNEL_FIREPLACESAFETYMODE = "fireplaceSafetyMode";
+    public static final String CHANNEL_HEATEXCHANGERBYPASSSTATUS = "heatExchangerBypassStatus";
+    public static final String CHANNEL_SUPPLYAIRFLAPSTATUS = "supplyAirFlapStatus";
+    public static final String CHANNEL_EXHAUSTAIRFLAPSTATUS = "exhaustAirFlapStatus";
+    public static final String CHANNEL_DEFROSTMODE = "defrostMode";
+    public static final String CHANNEL_COOLINGPROTECTIONMODE = "coolingProtectionMode";
+    public static final String CHANNEL_OUTDOORAIRHEATERSTATUS = "outdoorAirHeaterStatus";
+    public static final String CHANNEL_SUPPLYAIRHEATERSTATUS = "supplyAirHeaterStatus";
+    public static final String CHANNEL_DRAINHEATERSTATUS = "drainHeaterStatus";
+    public static final String CHANNEL_TIMEROPERATIONMODE = "timerOperationMode";
+    public static final String CHANNEL_WEEKLYTIMERPROGRAMSTATUS = "weeklyTimerProgramStatus";
+    public static final String CHANNEL_ROOMTEMPERATURECONTROLSTATUS = "roomTemperatureControlStatus";
+    public static final String CHANNEL_AIRQUALITYVALUE1 = "airQualityValue1";
+    public static final String CHANNEL_AIRQUALITYVALUE2 = "airQualityValue2";
+    public static final String CHANNEL_OUTDOORAIRTEMPERATURE = "outdoorAirTemperature";
+    public static final String CHANNEL_SUPPLYAIRTEMPERATURE = "supplyAirTemperature";
+    public static final String CHANNEL_INDOORAIRTEMPERATURE = "indoorAirTemperature";
+    public static final String CHANNEL_EXHAUSTAIRTEMPERATURE = "exhaustAirTemperature";
+    public static final String CHANNEL_SUPPLYAIRFANAIRFLOWRATE = "supplyAirFanAirFlowRate";
+    public static final String CHANNEL_EXHAUSTAIRFANAIRFLOWRATE = "exhaustAirFanAirFlowRate";
+    public static final String CHANNEL_SUPPLYFANSPEED = "supplyFanSpeed";
+    public static final String CHANNEL_EXHAUSTFANSPEED = "exhaustFanSpeed";
+
+    public static final Map<String, EnOceanChannelDescription> CHANNELID2CHANNELDESCRIPTION = Map.ofEntries(
+            Map.entry(CHANNEL_GENERAL_SWITCHING,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHING),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_GENERAL_SWITCHINGA,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHINGA),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_GENERAL_SWITCHINGB,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHINGB),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_DIMMER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DIMMER),
+                            CoreItemFactory.DIMMER)),
+            Map.entry(CHANNEL_ROLLERSHUTTER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ROLLERSHUTTER),
+                            CoreItemFactory.ROLLERSHUTTER)),
+            Map.entry(CHANNEL_ANGLE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ANGLE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Angle.class.getSimpleName())),
+            Map.entry(CHANNEL_TEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_HUMIDITY,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_HUMIDITY),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_FANSPEEDSTAGE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_FANSPEEDSTAGE),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_OCCUPANCY,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_OCCUPANCY),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_MOTIONDETECTION,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_MOTION.getUID(),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_VIBRATION,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIBRATION),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_ILLUMINATION,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATION),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName())),
+            Map.entry(CHANNEL_ILLUMINATIONWEST,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONWEST),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName())),
+            Map.entry(CHANNEL_ILLUMINATIONSOUTHNORTH,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONSOUTHNORTH),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName())),
+            Map.entry(CHANNEL_ILLUMINATIONEAST,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ILLUMINATIONEAST),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Illuminance.class.getSimpleName())),
+            Map.entry(CHANNEL_WINDSPEED,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_WIND_SPEED.getUID(),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Speed.class.getSimpleName())),
+            Map.entry(CHANNEL_RAINSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_RAINSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_COUNTER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_COUNTER),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_CURRENTNUMBER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CURRENTNUMBER),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_SMOKEDETECTION,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SMOKEDETECTION),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_SENSORFAULT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_MAINTENANCESTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_SENSORANALYSISHUMIDITYRANGE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_SENSORANALYSISTEMPERATURRANGE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SENSORFAULT),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_TIMESINCELASTMAINTENANCE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TIMESINCELASTMAINTENANCE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Time.class.getSimpleName())),
+            Map.entry(CHANNEL_REMAININGPLT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_REMAININGPLT),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Time.class.getSimpleName())),
+            Map.entry(CHANNEL_HYGROCOMFORTINDEX,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_HYGROCOMFORTINDEX),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_INDOORAIRANALYSIS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_INDOORAIRANALYSIS),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_SETPOINT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SETPOINT),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_CONTACT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CONTACT),
+                            CoreItemFactory.CONTACT)),
+            Map.entry(CHANNEL_WINDOWHANDLESTATE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWHANDLESTATE),
+                            CoreItemFactory.STRING)),
+            Map.entry(
+                    CHANNEL_BATTERY_VOLTAGE,
+                    new EnOceanChannelDescription(
+                            new ChannelTypeUID(BINDING_ID, CHANNEL_BATTERY_VOLTAGE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + ElectricPotential.class.getSimpleName())),
+            Map.entry(CHANNEL_ENERGY_STORAGE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ENERGY_STORAGE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + ElectricPotential.class.getSimpleName())),
+            Map.entry(CHANNEL_BATTERY_LEVEL, new EnOceanChannelDescription(
+                    DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_BATTERY_LEVEL.getUID(), CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_BATTERYLOW,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_CHANNEL_LOW_BATTERY.getUID(),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_TEACHINCMD,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TEACHINCMD),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_PUSHBUTTON,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
+                            "Push button", false, true)),
+            Map.entry(CHANNEL_DOUBLEPRESS,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
+                            "Double press", false, true)),
+            Map.entry(CHANNEL_LONGPRESS,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
+                            "Long press", false, true)),
+
+            Map.entry(CHANNEL_ROCKERSWITCH_CHANNELA,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(), null,
+                            "Rocker Switch - Channel A", false, false)),
+            Map.entry(CHANNEL_ROCKERSWITCH_CHANNELB,
+                    new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(), null,
+                            "Rocker Switch - Channel B", false, false)),
+
+            Map.entry(CHANNEL_VIRTUALSWITCHA,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALSWITCHA),
+                            CoreItemFactory.SWITCH, "", true, false)),
+            Map.entry(CHANNEL_VIRTUALROLLERSHUTTERA,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALROLLERSHUTTERA),
+                            CoreItemFactory.ROLLERSHUTTER, "", true, false)),
+            Map.entry(CHANNEL_VIRTUALROCKERSWITCHB,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALROCKERSWITCHB),
+                            CoreItemFactory.STRING, "Rocker Switch - Channel B", true, false)),
+            Map.entry(CHANNEL_ROCKERSWITCHLISTENERSWITCH,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCHLISTENERSWITCH),
+                            CoreItemFactory.SWITCH, "Rocker Switch Listener (Switch)", true, false)),
+            Map.entry(CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER,
+                    new EnOceanChannelDescription(
                             new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER),
-                            CoreItemFactory.ROLLERSHUTTER, "Rocker Switch Listener (Rollershutter)", true, false));
-
-                    put(CHANNEL_INSTANTPOWER, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_INSTANTPOWER),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Power.class.getSimpleName()));
-                    put(CHANNEL_TOTALUSAGE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TOTALUSAGE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Energy.class.getSimpleName()));
-                    put(CHANNEL_CURRENTFLOW,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CURRENTFLOW),
-                                    CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
-                                            + VolumetricFlowRate.class.getSimpleName()));
-                    put(CHANNEL_CUMULATIVEVALUE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_CUMULATIVEVALUE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Volume.class.getSimpleName()));
-                    put(CHANNEL_AUTOOFF, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_AUTOOFF),
-                            CoreItemFactory.NUMBER));
-                    put(CHANNEL_DELAYRADIOOFF, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_DELAYRADIOOFF), CoreItemFactory.NUMBER));
-                    put(CHANNEL_EXTERNALINTERFACEMODE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_EXTERNALINTERFACEMODE), CoreItemFactory.STRING));
-                    put(CHANNEL_TWOSTATESWITCH, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TWOSTATESWITCH), CoreItemFactory.SWITCH));
-                    put(CHANNEL_ECOMODE, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ECOMODE),
-                            CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_RSSI, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_RSSI),
-                            CoreItemFactory.NUMBER));
-                    put(CHANNEL_REPEATCOUNT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_REPEATCOUNT), CoreItemFactory.NUMBER));
-                    put(CHANNEL_LASTRECEIVED, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_LASTRECEIVED), CoreItemFactory.DATETIME));
-
-                    put(CHANNEL_GENERIC_SWITCH, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_SWITCH), CoreItemFactory.SWITCH));
-                    put(CHANNEL_GENERIC_ROLLERSHUTTER,
-                            new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_ROLLERSHUTTER),
-                                    CoreItemFactory.ROLLERSHUTTER));
-                    put(CHANNEL_GENERIC_DIMMER, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_DIMMER), CoreItemFactory.DIMMER));
-                    put(CHANNEL_GENERIC_NUMBER, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_NUMBER), CoreItemFactory.NUMBER));
-                    put(CHANNEL_GENERIC_STRING, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_STRING), CoreItemFactory.STRING));
-                    put(CHANNEL_GENERIC_COLOR, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_COLOR), CoreItemFactory.COLOR));
-                    put(CHANNEL_GENERIC_TEACHINCMD, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_TEACHINCMD), CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_VALVE_POSITION, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_VALVE_POSITION), CoreItemFactory.NUMBER));
-                    put(CHANNEL_BUTTON_LOCK, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_BUTTON_LOCK), CoreItemFactory.SWITCH));
-                    put(CHANNEL_DISPLAY_ORIENTATION, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_DISPLAY_ORIENTATION), CoreItemFactory.NUMBER));
-                    put(CHANNEL_TEMPERATURE_SETPOINT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE_SETPOINT),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName()));
-                    put(CHANNEL_FEED_TEMPERATURE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_FEED_TEMPERATURE),
-                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName()));
-                    put(CHANNEL_MEASUREMENT_CONTROL, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_MEASUREMENT_CONTROL), CoreItemFactory.SWITCH));
-                    put(CHANNEL_FAILURE_CODE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_FAILURE_CODE), CoreItemFactory.NUMBER));
-                    put(CHANNEL_WAKEUPCYCLE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_WAKEUPCYCLE), CoreItemFactory.NUMBER));
-                    put(CHANNEL_SERVICECOMMAND, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SERVICECOMMAND), CoreItemFactory.NUMBER));
-
-                    put(CHANNEL_STATUS_REQUEST_EVENT, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_STATUS_REQUEST_EVENT), null, "", false, true));
-                    put(CHANNEL_SEND_COMMAND, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_SEND_COMMAND), CoreItemFactory.SWITCH));
-
-                    put(CHANNEL_REPEATERMODE, new EnOceanChannelDescription(
-                            new ChannelTypeUID(BINDING_ID, CHANNEL_REPEATERMODE), CoreItemFactory.STRING));
-                }
-            });
+                            CoreItemFactory.ROLLERSHUTTER, "Rocker Switch Listener (Rollershutter)", true, false)),
+
+            Map.entry(CHANNEL_INSTANTPOWER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_INSTANTPOWER),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Power.class.getSimpleName())),
+            Map.entry(CHANNEL_TOTALUSAGE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TOTALUSAGE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Energy.class.getSimpleName())),
+            Map.entry(CHANNEL_CURRENTFLOW,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CURRENTFLOW),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + VolumetricFlowRate.class.getSimpleName())),
+            Map.entry(CHANNEL_CUMULATIVEVALUE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_CUMULATIVEVALUE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Volume.class.getSimpleName())),
+            Map.entry(CHANNEL_AUTOOFF,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_AUTOOFF),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_DELAYRADIOOFF,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DELAYRADIOOFF),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_EXTERNALINTERFACEMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_EXTERNALINTERFACEMODE),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_TWOSTATESWITCH,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TWOSTATESWITCH),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_ECOMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ECOMODE),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_RSSI,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_RSSI),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_REPEATCOUNT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_REPEATCOUNT),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_LASTRECEIVED,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_LASTRECEIVED),
+                            CoreItemFactory.DATETIME)),
+
+            Map.entry(CHANNEL_GENERIC_SWITCH,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_SWITCH),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_GENERIC_ROLLERSHUTTER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_ROLLERSHUTTER),
+                            CoreItemFactory.ROLLERSHUTTER)),
+            Map.entry(CHANNEL_GENERIC_DIMMER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_DIMMER),
+                            CoreItemFactory.DIMMER)),
+            Map.entry(CHANNEL_GENERIC_NUMBER,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_NUMBER),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_GENERIC_STRING,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_STRING),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_GENERIC_COLOR,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_COLOR),
+                            CoreItemFactory.COLOR)),
+            Map.entry(CHANNEL_GENERIC_TEACHINCMD,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERIC_TEACHINCMD),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_VALVE_POSITION,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VALVE_POSITION),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_BUTTON_LOCK,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_BUTTON_LOCK),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_DISPLAY_ORIENTATION,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DISPLAY_ORIENTATION),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_TEMPERATURE_SETPOINT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TEMPERATURE_SETPOINT),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_FEED_TEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_FEED_TEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_MEASUREMENT_CONTROL,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_MEASUREMENT_CONTROL),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_FAILURE_CODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_FAILURE_CODE),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_WAKEUPCYCLE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WAKEUPCYCLE),
+                            CoreItemFactory.NUMBER)),
+            Map.entry(CHANNEL_SERVICECOMMAND,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SERVICECOMMAND),
+                            CoreItemFactory.NUMBER)),
+
+            Map.entry(CHANNEL_STATUS_REQUEST_EVENT,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_STATUS_REQUEST_EVENT), null,
+                            "", false, true)),
+            Map.entry(CHANNEL_SEND_COMMAND,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SEND_COMMAND),
+                            CoreItemFactory.SWITCH)),
+
+            Map.entry(CHANNEL_VENTILATIONOPERATIONMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VENTILATIONOPERATIONMODE),
+                            CoreItemFactory.STRING)),
+            Map.entry(CHANNEL_FIREPLACESAFETYMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_FIREPLACESAFETYMODE),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_HEATEXCHANGERBYPASSSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_HEATEXCHANGERBYPASSSTATUS),
+                            CoreItemFactory.CONTACT)),
+            Map.entry(CHANNEL_SUPPLYAIRFLAPSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SUPPLYAIRFLAPSTATUS),
+                            CoreItemFactory.CONTACT)),
+            Map.entry(CHANNEL_EXHAUSTAIRFLAPSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_EXHAUSTAIRFLAPSTATUS),
+                            CoreItemFactory.CONTACT)),
+            Map.entry(CHANNEL_DEFROSTMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DEFROSTMODE),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_COOLINGPROTECTIONMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_COOLINGPROTECTIONMODE),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_OUTDOORAIRHEATERSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_OUTDOORAIRHEATERSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_SUPPLYAIRHEATERSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SUPPLYAIRHEATERSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_DRAINHEATERSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_DRAINHEATERSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_TIMEROPERATIONMODE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_TIMEROPERATIONMODE),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_WEEKLYTIMERPROGRAMSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WEEKLYTIMERPROGRAMSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_ROOMTEMPERATURECONTROLSTATUS,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_ROOMTEMPERATURECONTROLSTATUS),
+                            CoreItemFactory.SWITCH)),
+            Map.entry(CHANNEL_AIRQUALITYVALUE1,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_AIRQUALITYVALUE1),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + Dimensionless.class.getSimpleName())),
+            Map.entry(CHANNEL_AIRQUALITYVALUE2,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_AIRQUALITYVALUE2),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + Dimensionless.class.getSimpleName())),
+            Map.entry(CHANNEL_OUTDOORAIRTEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_OUTDOORAIRTEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_SUPPLYAIRTEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SUPPLYAIRTEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_INDOORAIRTEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_INDOORAIRTEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_EXHAUSTAIRTEMPERATURE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_EXHAUSTAIRTEMPERATURE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR + Temperature.class.getSimpleName())),
+            Map.entry(CHANNEL_SUPPLYAIRFANAIRFLOWRATE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SUPPLYAIRFANAIRFLOWRATE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + VolumetricFlowRate.class.getSimpleName())),
+            Map.entry(CHANNEL_EXHAUSTAIRFANAIRFLOWRATE,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_EXHAUSTAIRFANAIRFLOWRATE),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + VolumetricFlowRate.class.getSimpleName())),
+            Map.entry(CHANNEL_SUPPLYFANSPEED,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SUPPLYFANSPEED),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + Dimensionless.class.getSimpleName())),
+            Map.entry(CHANNEL_EXHAUSTFANSPEED,
+                    new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_EXHAUSTFANSPEED),
+                            CoreItemFactory.NUMBER + ItemUtil.EXTENSION_SEPARATOR
+                                    + Dimensionless.class.getSimpleName())),
+
+            Map.entry(CHANNEL_REPEATERMODE, new EnOceanChannelDescription(
+                    new ChannelTypeUID(BINDING_ID, CHANNEL_REPEATERMODE), CoreItemFactory.STRING)));
 
     // List of all repeater mode states
     public static final String REPEATERMODE_OFF = "OFF";
index 65822bc3e6a960eaa25fb6a6f6309c0473d0a5a5..511d81a5dd3182659c4d058880d2e375ec051db9 100644 (file)
@@ -42,4 +42,12 @@ public class Helper {
         }
         return result;
     }
+
+    public static int tryParseInt(String value, int defaultValue) {
+        try {
+            return Integer.parseInt(value);
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
 }
diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_50/D2_50.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/D2_50/D2_50.java
new file mode 100644 (file)
index 0000000..ee12d41
--- /dev/null
@@ -0,0 +1,184 @@
+/**
+ * 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.enocean.internal.eep.D2_50;
+
+import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
+
+import java.util.function.Function;
+
+import org.openhab.binding.enocean.internal.Helper;
+import org.openhab.binding.enocean.internal.eep.Base._VLDMessage;
+import org.openhab.binding.enocean.internal.messages.ERP1Message;
+import org.openhab.core.config.core.Configuration;
+import org.openhab.core.config.discovery.DiscoveryResultBuilder;
+import org.openhab.core.library.types.DecimalType;
+import org.openhab.core.library.types.OnOffType;
+import org.openhab.core.library.types.OpenClosedType;
+import org.openhab.core.library.types.QuantityType;
+import org.openhab.core.library.types.StringType;
+import org.openhab.core.library.unit.SIUnits;
+import org.openhab.core.library.unit.Units;
+import org.openhab.core.types.Command;
+import org.openhab.core.types.RefreshType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+
+/**
+ *
+ * @author Daniel Weber - Initial contribution
+ */
+public class D2_50 extends _VLDMessage {
+
+    protected static final byte mtMask = (byte) 0xf0;
+    protected static final byte MT_REMOTE_TRANSMISSION_REQUEST = 0x00;
+    protected static final byte MT_CONTROL = 0x20;
+    protected static final byte MT_BASIC_STATUS = 0x40;
+    protected static final byte MT_EXTENDED_STATUS = 0x60; // not yet implemented
+
+    protected static final byte rmtMask = (byte) 0x0f;
+    protected static final byte RMT_BASIC_STATUS = 0x00;
+    protected static final byte RMT_EXTENDED_STATUS = 0x01; // not yet implemented
+
+    protected static final byte DOMC_NOACTION = 0x0f;
+    protected static final byte CONTROL_NOACTION = 0;
+    protected static final byte TMOC_NOACTION = 127;
+    protected static final byte TMOC_ACTIVATE = (byte) 0xff;
+    protected static final byte THRESHOLD_NOACTION = 127;
+
+    public D2_50() {
+        super();
+    }
+
+    public D2_50(ERP1Message packet) {
+        super(packet);
+    }
+
+    protected byte getMessageType(byte b) {
+        return (byte) (b & mtMask);
+    }
+
+    @Override
+    public void addConfigPropertiesTo(DiscoveryResultBuilder discoveredThingResultBuilder) {
+        discoveredThingResultBuilder.withProperty(PARAMETER_SENDINGEEPID, getEEPType().getId())
+                .withProperty(PARAMETER_RECEIVINGEEPID, getEEPType().getId());
+    }
+
+    @Override
+    protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command,
+            Function<String, State> getCurrentStateFunc, Configuration config) {
+
+        // we need to send just a single message to refresh all channel states, hence just send refresh for OM
+        if (command == RefreshType.REFRESH && CHANNEL_VENTILATIONOPERATIONMODE.equals(channelId)) {
+            setData((byte) (MT_REMOTE_TRANSMISSION_REQUEST + RMT_BASIC_STATUS));
+        } else {
+            switch (channelId) {
+                case CHANNEL_VENTILATIONOPERATIONMODE:
+                    if (command instanceof StringType) {
+                        byte value = (byte) (Helper.tryParseInt(((StringType) command).toString(), 15) & 0x0f);
+                        setData((byte) (MT_CONTROL + value), CONTROL_NOACTION, TMOC_NOACTION, THRESHOLD_NOACTION,
+                                THRESHOLD_NOACTION, CONTROL_NOACTION);
+                    }
+                    break;
+                case CHANNEL_TIMEROPERATIONMODE:
+                    if (command instanceof OnOffType) {
+                        byte value = (OnOffType) command == OnOffType.ON ? TMOC_ACTIVATE : TMOC_NOACTION;
+                        setData((byte) (MT_CONTROL + DOMC_NOACTION), CONTROL_NOACTION, value, THRESHOLD_NOACTION,
+                                THRESHOLD_NOACTION, CONTROL_NOACTION);
+                    }
+                    break;
+            }
+        }
+    }
+
+    @Override
+    protected State convertToStateImpl(String channelId, String channelTypeId,
+            Function<String, State> getCurrentStateFunc, Configuration config) {
+
+        if (getMessageType(bytes[0]) != MT_BASIC_STATUS) {
+            return UnDefType.UNDEF;
+        }
+
+        switch (channelId) {
+            case CHANNEL_VENTILATIONOPERATIONMODE:
+                return new StringType(String.valueOf(bytes[0] & 0x0f));
+            case CHANNEL_FIREPLACESAFETYMODE:
+                return OnOffType.from(getBit(bytes[1], 3));
+            case CHANNEL_HEATEXCHANGERBYPASSSTATUS:
+                return getBit(bytes[1], 2) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+            case CHANNEL_SUPPLYAIRFLAPSTATUS:
+                return getBit(bytes[1], 1) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+            case CHANNEL_EXHAUSTAIRFLAPSTATUS:
+                return getBit(bytes[1], 0) ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
+            case CHANNEL_DEFROSTMODE:
+                return OnOffType.from(getBit(bytes[2], 7));
+            case CHANNEL_COOLINGPROTECTIONMODE:
+                return OnOffType.from(getBit(bytes[2], 6));
+            case CHANNEL_OUTDOORAIRHEATERSTATUS:
+                return OnOffType.from(getBit(bytes[2], 5));
+            case CHANNEL_SUPPLYAIRHEATERSTATUS:
+                return OnOffType.from(getBit(bytes[2], 4));
+            case CHANNEL_DRAINHEATERSTATUS:
+                return OnOffType.from(getBit(bytes[2], 3));
+            case CHANNEL_TIMEROPERATIONMODE:
+                return OnOffType.from(getBit(bytes[2], 2));
+            case CHANNEL_MAINTENANCESTATUS:
+                return OnOffType.from(getBit(bytes[2], 1));
+            case CHANNEL_WEEKLYTIMERPROGRAMSTATUS:
+                return OnOffType.from(getBit(bytes[2], 0));
+            case CHANNEL_ROOMTEMPERATURECONTROLSTATUS:
+                return OnOffType.from(getBit(bytes[3], 7));
+            case CHANNEL_AIRQUALITYVALUE1:
+                return new QuantityType<>((bytes[3] & 0x7f), Units.PERCENT);
+            case CHANNEL_AIRQUALITYVALUE2:
+                return new QuantityType<>((bytes[4] & 0x7f), Units.PERCENT);
+            case CHANNEL_OUTDOORAIRTEMPERATURE:
+                return new QuantityType<>(-63 + (bytes[5] >>> 1), SIUnits.CELSIUS);
+            case CHANNEL_SUPPLYAIRTEMPERATURE:
+                return new QuantityType<>(-63 + (bytes[6] >>> 2) + ((bytes[5] & 1) << 6), SIUnits.CELSIUS);
+            case CHANNEL_INDOORAIRTEMPERATURE:
+                return new QuantityType<>(-63 + (bytes[7] >>> 3) + ((bytes[6] & 0b11) << 5), SIUnits.CELSIUS);
+            case CHANNEL_EXHAUSTAIRTEMPERATURE:
+                return new QuantityType<>(-63 + (bytes[8] >>> 4) + ((bytes[7] & 0b111) << 4), SIUnits.CELSIUS);
+            case CHANNEL_SUPPLYAIRFANAIRFLOWRATE:
+                return new QuantityType<>((bytes[9] >>> 2) + ((bytes[8] & 0b1111) << 6), Units.CUBICMETRE_PER_MINUTE);
+            case CHANNEL_EXHAUSTAIRFANAIRFLOWRATE:
+                return new QuantityType<>((bytes[10] & 0xff) + ((bytes[9] & 0b11) << 8), Units.CUBICMETRE_PER_MINUTE);
+            case CHANNEL_SUPPLYFANSPEED:
+                return new DecimalType((bytes[12] >>> 4) + (bytes[11] << 4));
+            case CHANNEL_EXHAUSTFANSPEED:
+                return new DecimalType((bytes[13] & 0xff) + ((bytes[12] & 0b1111) << 8));
+        }
+
+        return UnDefType.UNDEF;
+    }
+
+    @Override
+    protected boolean validateData(byte[] bytes) {
+        if (bytes.length == 0) {
+            return false;
+        }
+
+        switch (getMessageType(bytes[0])) {
+            case MT_REMOTE_TRANSMISSION_REQUEST:
+                return bytes.length == 1;
+            case MT_CONTROL:
+                return bytes.length == 6;
+            case MT_BASIC_STATUS:
+                return bytes.length == 14;
+            case MT_EXTENDED_STATUS: // MT_EXTENDED_STATUS is not yet supported, however return true to avoid Exceptions
+                return true;
+            default:
+                return false;
+        }
+    }
+}
index 562bf8582dbad71d9ecec886bb923052006b740d..451c853303fddc3eb9e282ac869a8e6ff51e3bc2 100644 (file)
@@ -136,6 +136,7 @@ import org.openhab.binding.enocean.internal.eep.D2_01.D2_01_12_NodON;
 import org.openhab.binding.enocean.internal.eep.D2_03.D2_03_0A;
 import org.openhab.binding.enocean.internal.eep.D2_05.D2_05_00;
 import org.openhab.binding.enocean.internal.eep.D2_14.D2_14_30;
+import org.openhab.binding.enocean.internal.eep.D2_50.D2_50;
 import org.openhab.binding.enocean.internal.eep.D5_00.D5_00_01;
 import org.openhab.binding.enocean.internal.eep.F6_01.F6_01_01;
 import org.openhab.binding.enocean.internal.eep.F6_02.F6_02_01;
@@ -457,7 +458,43 @@ public enum EEPType {
     MultiFunctionSensor_30(RORG.VLD, 0x14, 0x30, false, D2_14_30.class, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR,
             CHANNEL_SMOKEDETECTION, CHANNEL_SENSORFAULT, CHANNEL_TIMESINCELASTMAINTENANCE, CHANNEL_BATTERY_LEVEL,
             CHANNEL_REMAININGPLT, CHANNEL_TEMPERATURE, CHANNEL_HUMIDITY, CHANNEL_HYGROCOMFORTINDEX,
-            CHANNEL_INDOORAIRANALYSIS);
+            CHANNEL_INDOORAIRANALYSIS),
+
+    HeatRecoveryVentilation_00(RORG.VLD, 0x50, 0x00, false, D2_50.class, THING_TYPE_HEATRECOVERYVENTILATION,
+            CHANNEL_VENTILATIONOPERATIONMODE, CHANNEL_SUPPLYAIRFLAPSTATUS, CHANNEL_WEEKLYTIMERPROGRAMSTATUS,
+            CHANNEL_EXHAUSTAIRFLAPSTATUS, CHANNEL_DEFROSTMODE, CHANNEL_COOLINGPROTECTIONMODE,
+            CHANNEL_OUTDOORAIRHEATERSTATUS, CHANNEL_SUPPLYAIRHEATERSTATUS, CHANNEL_DRAINHEATERSTATUS,
+            CHANNEL_TIMEROPERATIONMODE, CHANNEL_MAINTENANCESTATUS, CHANNEL_ROOMTEMPERATURECONTROLSTATUS,
+            CHANNEL_AIRQUALITYVALUE1, CHANNEL_AIRQUALITYVALUE2, CHANNEL_OUTDOORAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRTEMPERATURE, CHANNEL_INDOORAIRTEMPERATURE, CHANNEL_EXHAUSTAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRFANAIRFLOWRATE, CHANNEL_EXHAUSTAIRFANAIRFLOWRATE, CHANNEL_SUPPLYFANSPEED,
+            CHANNEL_EXHAUSTFANSPEED),
+    HeatRecoveryVentilation_01(RORG.VLD, 0x50, 0x01, false, D2_50.class, THING_TYPE_HEATRECOVERYVENTILATION,
+            CHANNEL_VENTILATIONOPERATIONMODE, CHANNEL_SUPPLYAIRFLAPSTATUS, CHANNEL_WEEKLYTIMERPROGRAMSTATUS,
+            CHANNEL_EXHAUSTAIRFLAPSTATUS, CHANNEL_DEFROSTMODE, CHANNEL_COOLINGPROTECTIONMODE,
+            CHANNEL_OUTDOORAIRHEATERSTATUS, CHANNEL_SUPPLYAIRHEATERSTATUS, CHANNEL_DRAINHEATERSTATUS,
+            CHANNEL_TIMEROPERATIONMODE, CHANNEL_MAINTENANCESTATUS, CHANNEL_ROOMTEMPERATURECONTROLSTATUS,
+            CHANNEL_AIRQUALITYVALUE1, CHANNEL_AIRQUALITYVALUE2, CHANNEL_OUTDOORAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRTEMPERATURE, CHANNEL_INDOORAIRTEMPERATURE, CHANNEL_EXHAUSTAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRFANAIRFLOWRATE, CHANNEL_EXHAUSTAIRFANAIRFLOWRATE, CHANNEL_SUPPLYFANSPEED,
+            CHANNEL_EXHAUSTFANSPEED),
+    HeatRecoveryVentilation_10(RORG.VLD, 0x50, 0x10, false, D2_50.class, THING_TYPE_HEATRECOVERYVENTILATION,
+            CHANNEL_VENTILATIONOPERATIONMODE, CHANNEL_DEFROSTMODE, CHANNEL_COOLINGPROTECTIONMODE,
+            CHANNEL_OUTDOORAIRHEATERSTATUS, CHANNEL_SUPPLYAIRHEATERSTATUS, CHANNEL_DRAINHEATERSTATUS,
+            CHANNEL_TIMEROPERATIONMODE, CHANNEL_MAINTENANCESTATUS, CHANNEL_ROOMTEMPERATURECONTROLSTATUS,
+            CHANNEL_AIRQUALITYVALUE1, CHANNEL_AIRQUALITYVALUE2, CHANNEL_OUTDOORAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRTEMPERATURE, CHANNEL_INDOORAIRTEMPERATURE, CHANNEL_EXHAUSTAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRFANAIRFLOWRATE, CHANNEL_EXHAUSTAIRFANAIRFLOWRATE, CHANNEL_SUPPLYFANSPEED,
+            CHANNEL_EXHAUSTFANSPEED, CHANNEL_WEEKLYTIMERPROGRAMSTATUS),
+    HeatRecoveryVentilation_11(RORG.VLD, 0x50, 0x11, false, D2_50.class, THING_TYPE_HEATRECOVERYVENTILATION,
+            CHANNEL_VENTILATIONOPERATIONMODE, CHANNEL_FIREPLACESAFETYMODE, CHANNEL_HEATEXCHANGERBYPASSSTATUS,
+            CHANNEL_DEFROSTMODE, CHANNEL_COOLINGPROTECTIONMODE, CHANNEL_OUTDOORAIRHEATERSTATUS,
+            CHANNEL_WEEKLYTIMERPROGRAMSTATUS, CHANNEL_SUPPLYAIRHEATERSTATUS, CHANNEL_DRAINHEATERSTATUS,
+            CHANNEL_TIMEROPERATIONMODE, CHANNEL_MAINTENANCESTATUS, CHANNEL_ROOMTEMPERATURECONTROLSTATUS,
+            CHANNEL_AIRQUALITYVALUE1, CHANNEL_AIRQUALITYVALUE2, CHANNEL_OUTDOORAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRTEMPERATURE, CHANNEL_INDOORAIRTEMPERATURE, CHANNEL_EXHAUSTAIRTEMPERATURE,
+            CHANNEL_SUPPLYAIRFANAIRFLOWRATE, CHANNEL_EXHAUSTAIRFANAIRFLOWRATE, CHANNEL_SUPPLYFANSPEED,
+            CHANNEL_EXHAUSTFANSPEED);
 
     private RORG rorg;
     private int func;
index 970947763fd74fef4ab56c17fe494b4a0bcd82e0..590769153791d619303f73610ff121a0db5fef4e 100644 (file)
@@ -14,10 +14,8 @@ package org.openhab.binding.enocean.internal.handler;
 
 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
 
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
@@ -50,8 +48,9 @@ import org.openhab.core.util.HexUtils;
 public class EnOceanBaseActuatorHandler extends EnOceanBaseSensorHandler {
 
     // List of thing types which support sending of eep messages
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_CENTRALCOMMAND,
-            THING_TYPE_MEASUREMENTSWITCH, THING_TYPE_GENERICTHING, THING_TYPE_ROLLERSHUTTER, THING_TYPE_THERMOSTAT));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_CENTRALCOMMAND,
+            THING_TYPE_MEASUREMENTSWITCH, THING_TYPE_GENERICTHING, THING_TYPE_ROLLERSHUTTER, THING_TYPE_THERMOSTAT,
+            THING_TYPE_HEATRECOVERYVENTILATION);
 
     protected byte[] senderId; // base id of bridge + senderIdOffset, used for sending msg
     protected byte[] destinationId; // in case of broadcast FFFFFFFF otherwise the enocean id of the device
index c85aa460b32cf6d30e45ef61f706f5aabd1f90fc..d533c1e558c4abd491e9c3f2032349e58bbc33bb 100644 (file)
@@ -14,11 +14,9 @@ package org.openhab.binding.enocean.internal.handler;
 
 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
 
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Set;
 import java.util.function.Predicate;
@@ -51,12 +49,11 @@ import org.openhab.core.util.HexUtils;
 public class EnOceanBaseSensorHandler extends EnOceanBaseThingHandler implements PacketListener {
 
     // List of all thing types which support receiving of eep messages
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
-            Arrays.asList(THING_TYPE_ROOMOPERATINGPANEL, THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT,
-                    THING_TYPE_TEMPERATURESENSOR, THING_TYPE_TEMPERATUREHUMIDITYSENSOR, THING_TYPE_ROCKERSWITCH,
-                    THING_TYPE_OCCUPANCYSENSOR, THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR,
-                    THING_TYPE_PUSHBUTTON, THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_ENVIRONMENTALSENSOR,
-                    THING_TYPE_MULTFUNCTIONSMOKEDETECTOR));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_ROOMOPERATINGPANEL,
+            THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT, THING_TYPE_TEMPERATURESENSOR,
+            THING_TYPE_TEMPERATUREHUMIDITYSENSOR, THING_TYPE_ROCKERSWITCH, THING_TYPE_OCCUPANCYSENSOR,
+            THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR, THING_TYPE_PUSHBUTTON,
+            THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_ENVIRONMENTALSENSOR, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR);
 
     protected final Hashtable<RORG, EEPType> receivingEEPTypes = new Hashtable<>();
 
index 9fc1c5eee4dca8a68d2f9fae3bb3dc511a354daf..c888f6a60be2d0ad2a7c93f4441b929ded7f64ce 100644 (file)
@@ -16,9 +16,7 @@ import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
 
 import java.io.IOException;
 import java.math.BigDecimal;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.Set;
 import java.util.concurrent.ScheduledFuture;
@@ -70,7 +68,7 @@ public class EnOceanBridgeHandler extends ConfigStatusBridgeHandler implements T
 
     private Logger logger = LoggerFactory.getLogger(EnOceanBridgeHandler.class);
 
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(Arrays.asList(THING_TYPE_BRIDGE));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_BRIDGE);
 
     private EnOceanTransceiver transceiver; // holds connection to serial/tcp port and sends/receives messages
     private ScheduledFuture<?> connectorTask; // is used for reconnection if something goes wrong
index 3e52c257e90d74739cc4b7bbbcbf5adbf686542a..412cd9ad8d8fec82e3213d77c49de342ab407ae0 100644 (file)
@@ -14,8 +14,6 @@ package org.openhab.binding.enocean.internal.handler;
 
 import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
 
-import java.util.Arrays;
-import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
@@ -56,8 +54,7 @@ import org.openhab.core.util.HexUtils;
 public class EnOceanClassicDeviceHandler extends EnOceanBaseActuatorHandler {
 
     // List of thing types which support sending of eep messages
-    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = new HashSet<>(
-            Arrays.asList(THING_TYPE_CLASSICDEVICE));
+    public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES = Set.of(THING_TYPE_CLASSICDEVICE);
 
     private StringType lastTriggerEvent = StringType.valueOf(CommonTriggerEvents.DIR1_PRESSED);
     ScheduledFuture<?> releaseFuture = null;
diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/HeatRecoveryVentilation.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/HeatRecoveryVentilation.xml
new file mode 100644 (file)
index 0000000..cd58af2
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<thing:thing-descriptions bindingId="enocean"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
+       xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
+
+       <thing-type id="heatRecoveryVentilation">
+               <supported-bridge-type-refs>
+                       <bridge-type-ref id="bridge"/>
+               </supported-bridge-type-refs>
+
+               <label>Heat Recovery Ventilation</label>
+               <description>Sensor and actuator to control heat recovery ventilation units (EEP: D2-50)</description>
+
+               <config-description>
+                       <parameter name="enoceanId" type="text">
+                               <label>EnOceanId</label>
+                               <description>EnOceanId of device this thing belongs to</description>
+                               <required>true</required>
+                       </parameter>
+                       <parameter name="senderIdOffset" type="integer">
+                               <label>Sender Id</label>
+                               <description>Id is used to generate the EnOcean Id (Int between [1-127]). If not specified the next free Id will be
+                                       determined by bridge</description>
+                               <required>true</required>
+                       </parameter>
+                       <parameter name="sendingEEPId" type="text">
+                               <label>EEP for Sending Commands</label>
+                               <options>
+                                       <option value="D2_50_00">D2-50-00 Single Room Ventilation Unit</option>
+                                       <option value="D2_50_01">D2-50-01 Single Room Ventilation Unit With Pre-Heater</option>
+                                       <option value="D2_50_10">D2-50-10 Multi Room Ventilation Unit Without Bypass</option>
+                                       <option value="D2_50_11">D2-50-11 Multi Room Ventilation Unit With Bypass</option>
+                               </options>
+                               <limitToOptions>true</limitToOptions>
+                               <required>true</required>
+                       </parameter>
+                       <parameter name="broadcastMessages" type="boolean">
+                               <label>Send Broadcast Messages</label>
+                               <default>false</default>
+                       </parameter>
+                       <parameter name="receivingEEPId" type="text">
+                               <label>EEP</label>
+                               <description>EEP which is used by Ventilation Unit</description>
+                               <options>
+                                       <option value="D2_50_00">D2-50-00 Single Room Ventilation Unit</option>
+                                       <option value="D2_50_01">D2-50-01 Single Room Ventilation Unit With Pre-Heater</option>
+                                       <option value="D2_50_10">D2-50-10 Multi Room Ventilation Unit Without Bypass</option>
+                                       <option value="D2_50_11">D2-50-11 Multi Room Ventilation Unit With Bypass</option>
+                               </options>
+                               <limitToOptions>true</limitToOptions>
+                               <required>true</required>
+                       </parameter>
+                       <parameter name="suppressRepeating" type="boolean">
+                               <label>Suppress Repeating of Messages</label>
+                               <default>false</default>
+                       </parameter>
+               </config-description>
+
+       </thing-type>
+
+</thing:thing-descriptions>
index 9550e0d5e6ad30ec3e59a019be802a179d863eaf..9469d48b8c9af9207e3a122bd503ef3bd62b8c88 100644 (file)
                </state>
        </channel-type>
 
+       <channel-type id="ventilationOperationMode">
+               <item-type>String</item-type>
+               <label>Direct Operation Mode Control</label>
+               <description>Sets the ventilation mode/level.</description>
+               <state>
+                       <options>
+                               <option value="0">Off</option>
+                               <option value="1">Level 1</option>
+                               <option value="2">Level 2</option>
+                               <option value="3">Level 3</option>
+                               <option value="4">Level 4</option>
+                               <option value="5">Reserved</option>
+                               <option value="6">Reserved</option>
+                               <option value="7">Reserved</option>
+                               <option value="8">Reserved</option>
+                               <option value="9">Reserved</option>
+                               <option value="10">Reserved</option>
+                               <option value="11">Automatic</option>
+                               <option value="12">Automatic on demand</option>
+                               <option value="13">Supply air only</option>
+                               <option value="14">Exhaust air only</option>
+                               <option value="15">Reserved</option>
+                       </options>
+               </state>
+       </channel-type>
+
+       <channel-type id="fireplaceSafetyMode">
+               <item-type>Switch</item-type>
+               <label>Fireplace Safety Mode</label>
+               <description>Indicates if device is running in fireplace safety mode</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="heatExchangerBypassStatus">
+               <item-type>Contact</item-type>
+               <label>Heat Exchanger Bypass Status</label>
+               <description>Indicates if heat exchanger bypass is open (heat recovery inactive) or closed (heat recovery active)</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="supplyAirFlapStatus">
+               <item-type>Contact</item-type>
+               <label>Supply Air Flap Position</label>
+               <description>Indicates if supply air flap is open or closed</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="exhaustAirFlapStatus">
+               <item-type>Contact</item-type>
+               <label>Exhaust Air Flap Position</label>
+               <description>Indicates if exhaust air flap is open or closed</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="defrostMode">
+               <item-type>Switch</item-type>
+               <label>Defrost Mode</label>
+               <description>Indicates if defrosting of heat exchanger is active or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="coolingProtectionMode">
+               <item-type>Switch</item-type>
+               <label>Cooling Protection Mode</label>
+               <description>Indicates if device is running in cooling protection mode</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="outdoorAirHeaterStatus">
+               <item-type>Switch</item-type>
+               <label>Outdoor Air Heater Status</label>
+               <description>Indicates if outdoor air heater is active or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="supplyAirHeaterStatus">
+               <item-type>Switch</item-type>
+               <label>Supply Air Heater Status</label>
+               <description>Indicates if supply air heater is active or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="drainHeaterStatus">
+               <item-type>Switch</item-type>
+               <label>Drain Heater Status</label>
+               <description>Indicates if drain heater is active or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="timerOperationMode">
+               <item-type>Switch</item-type>
+               <label>Timer Operation Mode</label>
+               <description>Indicates if timer operation mode is active or not</description>
+       </channel-type>
+
+       <channel-type id="weeklyTimerProgramStatus">
+               <item-type>Switch</item-type>
+               <label>Weekly Timer Program Status</label>
+               <description>Indicates if device is running according to configured program or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="roomTemperatureControlStatus">
+               <item-type>Switch</item-type>
+               <label>Room Temperature Control Status</label>
+               <description>Indicates if room temperature control is active or not</description>
+               <state readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="airQualityValue1">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Air Quality Value</label>
+               <description>Air quality value of first sensor in percentages</description>
+               <state min="0" max="100" pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="airQualityValue2">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Air Quality Value</label>
+               <description>Air quality value of second sensor in percentages</description>
+               <state min="0" max="100" pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="outdoorAirTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Outdoor Temperature</label>
+               <description>Current outdoor air temperature in degree Celsius</description>
+               <category>Temperature</category>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="supplyAirTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Supply Air Temperature</label>
+               <description>Current supply air temperature in degree Celsius</description>
+               <category>Temperature</category>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="indoorAirTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Indoor Temperature</label>
+               <description>Current indoor air temperature in degree Celsius</description>
+               <category>Temperature</category>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="exhaustAirTemperature">
+               <item-type>Number:Temperature</item-type>
+               <label>Exhaust Air Temperature</label>
+               <description>Current exhaust air temperature in degree Celsius</description>
+               <category>Temperature</category>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="supplyAirFanAirFlowRate">
+               <item-type>Number:VolumetricFlowRate</item-type>
+               <label>Supply Air Fan Air Flow Rate</label>
+               <description>Current supply air fan air flow rate</description>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="exhaustAirFanAirFlowRate">
+               <item-type>Number:VolumetricFlowRate</item-type>
+               <label>Exhaust Air Fan Air Flow Rate</label>
+               <description>Current exhaust air fan air flow rate</description>
+               <state pattern="%.1f %unit%" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="supplyFanSpeed">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Supply Fan Speed</label>
+               <description>Supply fan speed in revolutions per minutes</description>
+               <state min="0" max="100" pattern="%.1f rpm" readOnly="true"/>
+       </channel-type>
+
+       <channel-type id="exhaustFanSpeed">
+               <item-type>Number:Dimensionless</item-type>
+               <label>Exhaust Fan Speed</label>
+               <description>Exhaust fan speed in revolutions per minutes</description>
+               <state min="0" max="100" pattern="%.1f rpm" readOnly="true"/>
+       </channel-type>
+
 </thing:thing-descriptions>