From 47b89f5235fc122596096aee0be0e1cb26b7d1b8 Mon Sep 17 00:00:00 2001 From: Dietmar Franzen Date: Sat, 29 May 2021 12:15:37 +0200 Subject: [PATCH 1/6] [enocean] Add second action for two rocker switches (Fixes #9750) Signed-off-by: Dietmar Franzen --- .../enocean/internal/eep/F6_02/F6_02_01.java | 33 +++++++++++++++++++ .../enocean/internal/eep/F6_02/F6_02_02.java | 33 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java index 8152c5e90a30a..9231a58692c81 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java @@ -40,6 +40,7 @@ public class F6_02_01 extends _RPSMessage { final byte BI = 2; final byte B0 = 3; final byte PRESSED = 16; + final byte PRESSED_SEC = 1; int secondByte = -1; int secondStatus = -1; @@ -66,6 +67,12 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri } else if ((bytes[0] >>> 5) == dir2) { return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED : CommonTriggerEvents.DIR2_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED + : CommonTriggerEvents.DIR1_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED + : CommonTriggerEvents.DIR2_RELEASED; } } else if (t21 && !nu) { if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { @@ -127,6 +134,16 @@ protected State convertToStateImpl(String channelId, String channelTypeId, return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF : UpDownType.DOWN; } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } } break; case ToggleDir1: @@ -138,6 +155,14 @@ protected State convertToStateImpl(String channelId, String channelTypeId, : (currentState == UnDefType.UNDEF ? UpDownType.UP : inverse((UpDownType) currentState)); } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } break; case ToggleDir2: @@ -149,6 +174,14 @@ protected State convertToStateImpl(String channelId, String channelTypeId, : (currentState == UnDefType.UNDEF ? UpDownType.UP : inverse((UpDownType) currentState)); } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } break; default: diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java index 76e169785171a..7ae7bcbafe444 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java @@ -40,6 +40,7 @@ public class F6_02_02 extends _RPSMessage { final byte BI = 2; final byte B0 = 3; final byte PRESSED = 16; + final byte PRESSED_SEC = 1; public F6_02_02() { super(); @@ -63,6 +64,12 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri } else if ((bytes[0] >>> 5) == dir2) { return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED : CommonTriggerEvents.DIR2_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED + : CommonTriggerEvents.DIR1_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED + : CommonTriggerEvents.DIR2_RELEASED; } } else if (t21 && !nu) { if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { @@ -124,6 +131,16 @@ protected State convertToStateImpl(String channelId, String channelTypeId, return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF : UpDownType.DOWN; } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } } break; case ToggleDir1: @@ -135,6 +152,14 @@ protected State convertToStateImpl(String channelId, String channelTypeId, : (currentState == UnDefType.UNDEF ? UpDownType.UP : inverse((UpDownType) currentState)); } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } break; case ToggleDir2: @@ -146,6 +171,14 @@ protected State convertToStateImpl(String channelId, String channelTypeId, : (currentState == UnDefType.UNDEF ? UpDownType.UP : inverse((UpDownType) currentState)); } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } break; default: From d951f9503b1884df71db1ca14452f2f7b8371ef0 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 3 Sep 2021 10:19:11 +0200 Subject: [PATCH 2/6] [enocean] Add second action for two rocker switches (Fixes #9750) * Added two new channels: * secondActionPressed: Indicates if second action of rocker switch is pressed too * rockerSwitchAction: emits the combined rocker switch actions "ChannelADir|ChannelBDir", extensible channel, filter for each channel * Added two new profiles for channel rockerSwitchAction: * rockerswitchaction-toggle-switch * rockerswitchaction-toggle-player * EnOceanSensorHandler can now handle extensible channels too * EEP F6-02 refactoring Signed-off-by: Daniel Weber --- bundles/org.openhab.binding.enocean/README.md | 6 +- .../internal/EnOceanBindingConstants.java | 12 ++ ...nOceanChannelRockerSwitchActionConfig.java | 28 +++ .../binding/enocean/internal/eep/EEPType.java | 11 +- .../enocean/internal/eep/F6_02/F6_02.java | 119 +++++++++++ .../enocean/internal/eep/F6_02/F6_02_01.java | 200 ++++++++---------- .../enocean/internal/eep/F6_02/F6_02_02.java | 191 ++++++++--------- .../handler/EnOceanBaseSensorHandler.java | 3 +- .../profiles/EnOceanProfileFactory.java | 109 ++++++++++ .../internal/profiles/EnOceanProfiles.java | 45 ++++ ...RockerSwitchActionTogglePlayerProfile.java | 60 ++++++ ...RockerSwitchActionToggleSwitchProfile.java | 59 ++++++ .../resources/OH-INF/thing/RockerSwitch.xml | 5 +- .../main/resources/OH-INF/thing/channels.xml | 48 +++++ 14 files changed, 679 insertions(+), 217 deletions(-) create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfiles.java create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java diff --git a/bundles/org.openhab.binding.enocean/README.md b/bundles/org.openhab.binding.enocean/README.md index a32ab02b157b4..d60b0fa640f8a 100644 --- a/bundles/org.openhab.binding.enocean/README.md +++ b/bundles/org.openhab.binding.enocean/README.md @@ -75,7 +75,7 @@ Hence if your device supports one of the following EEPs the chances are good tha |---------------------------------|-------------|---------------|------------------------------|--------------------------------|-----------| | bridge | - | - | repeaterMode, setBaseId | USB300, EnOceanPi | - | | pushButton | F6-01/D2-03 | 0x01/0x0A | pushButton, doublePress,
longPress, batteryLevel | NodOn soft button | Manually/Discovery | -| rockerSwitch | F6-02 | 0x01-02 | rockerswitchA, rockerswitchB | Eltako FT55 | Discovery | +| rockerSwitch | F6-02 | 0x01-02 | rockerswitchA, rockerswitchB,
secondActionPressed, rockerSwitchAction | Eltako FT55 | Discovery | | mechanicalHandle | F6-10 | 0x00-01 | windowHandleState, contact | Hoppe SecuSignal handles, Eltako TF-FGB | Discovery | | contact | D5-00 | 0x01 | contact | Eltako FTK(E) & TF-FKB | Discovery | | temperatureSensor | A5-02 | 0x01-30 | temperature | Thermokon SR65 | Discovery | @@ -254,6 +254,8 @@ The channels of a thing are determined automatically based on the chosen EEP. | doublePress | Trigger | Channel type system:rawbutton, emits PRESSED | | longPress | Trigger | Channel type system:rawbutton, emits PRESSED and RELEASED events | | rockerswitchA/B | Trigger | Channel type system:rawrocker, emits DIR1_PRESSED, DIR1_RELEASED, DIR2_PRESSED, DIR2_RELEASED events | +| secondActionPressed | Switch | Indicates if second action of rocker switch is pressed too | +| rockerSwitchAction | Trigger | Emits combined rocker switch actions for channel A and B and RELEASED events | | windowHandleState | String | Textual representation of handle position (OPEN, CLOSED, TILTED) | | contact | Contact | State OPEN/CLOSED (tilted handle => OPEN) | | temperature | Number:Temperature | Temperature in degree Celsius | @@ -336,6 +338,8 @@ Some channels can be configured with parameters. | totalusage | validateValue | Filter out increases more than 10.0 kWh and decreases less than 1.0 kWh | true / false | | | tariff | Tariff info or measurement channel to listen to | 0-15 | | contact | inverted | Swap OPEN / CLOSED. Set True for Eltako FPE-2. | true / false. Defaults to false. | +| rockerSwitchAction | channelAFilter | Defines for which channel A events this trigger should fire | *: Any Direction, DIR1, DIR2, -:No Direction. Defaults to * | +| rockerSwitchAction | channelBFilter | Defines for which channel B events this trigger should fire | *: Any Direction, DIR1, DIR2, -:No Direction. Defaults to * | Possible declaration in Thing DSL: diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java index c6b3814c5edbc..d104020d84afb 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java @@ -129,6 +129,10 @@ public class EnOceanBindingConstants { public static final String CHANNEL_ROCKERSWITCH_CHANNELA = "rockerswitchA"; public static final String CHANNEL_ROCKERSWITCH_CHANNELB = "rockerswitchB"; + public static final String CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED = "secondActionPressed"; + public static final String CHANNEL_ROCKERSWITCH_ACTION = "rockerSwitchAction"; + public static final ChannelTypeUID CHANNELTYPE_ROCKERSWITCH_ACTION_UID = new ChannelTypeUID(BINDING_ID, + CHANNEL_ROCKERSWITCH_ACTION); public static final String CHANNEL_VIRTUALSWITCHA = "virtualSwitchA"; public static final String CHANNEL_VIRTUALROLLERSHUTTERA = "virtualRollershutterA"; @@ -203,6 +207,7 @@ public class EnOceanBindingConstants { public static final String CHANNEL_SUPPLYFANSPEED = "supplyFanSpeed"; public static final String CHANNEL_EXHAUSTFANSPEED = "exhaustFanSpeed"; + public static final Map CHANNELID2CHANNELDESCRIPTION = Map.ofEntries( Map.entry(CHANNEL_GENERAL_SWITCHING, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHING), @@ -338,6 +343,13 @@ public class EnOceanBindingConstants { Map.entry(CHANNEL_ROCKERSWITCH_CHANNELB, new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(), null, "Rocker Switch - Channel B", false, false)), + Map.entry(CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, + new EnOceanChannelDescription( + new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED), + CoreItemFactory.SWITCH, "Second Action Pressed", false, false)), + Map.entry(CHANNEL_ROCKERSWITCH_ACTION, + new EnOceanChannelDescription(CHANNELTYPE_ROCKERSWITCH_ACTION_UID, null, "Rocker Switch Action", + false, false)), Map.entry(CHANNEL_VIRTUALSWITCHA, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VIRTUALSWITCHA), diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java new file mode 100644 index 0000000000000..d39ea16ddf584 --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java @@ -0,0 +1,28 @@ +/** + * 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.config; + +/** + * + * @author Daniel Weber - Initial contribution + */ +public class EnOceanChannelRockerSwitchActionConfig { + + public String channelAFilter; + public String channelBFilter; + + public EnOceanChannelRockerSwitchActionConfig() { + channelAFilter = "*"; + channelBFilter = "*"; + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java index 26c461ae8257c..50b6c36c06af1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java @@ -177,12 +177,15 @@ public enum EEPType { CHANNEL_DOUBLEPRESS, CHANNEL_LONGPRESS, CHANNEL_BATTERY_LEVEL), RockerSwitch2RockerStyle1(RORG.RPS, 0x02, 0x01, false, F6_02_01.class, THING_TYPE_ROCKERSWITCH, - CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_VIRTUALSWITCHA, - CHANNEL_VIRTUALROLLERSHUTTERA, CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, + CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, + CHANNEL_ROCKERSWITCH_ACTION, CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, + CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), + RockerSwitch2RockerStyle2(RORG.RPS, 0x02, 0x02, false, F6_02_02.class, THING_TYPE_ROCKERSWITCH, - CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_VIRTUALSWITCHA, - CHANNEL_VIRTUALROLLERSHUTTERA, CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, + CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, + CHANNEL_ROCKERSWITCH_ACTION, CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, + CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), MechanicalHandle00(RORG.RPS, 0x10, 0x00, false, F6_10_00.class, THING_TYPE_MECHANICALHANDLE, diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java new file mode 100644 index 0000000000000..a5834c915cd17 --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java @@ -0,0 +1,119 @@ +/** + * 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.F6_02; + +import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchActionConfig; +import org.openhab.binding.enocean.internal.eep.Base._RPSMessage; +import org.openhab.binding.enocean.internal.messages.ERP1Message; +import org.openhab.core.config.core.Configuration; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.UpDownType; +import org.openhab.core.thing.CommonTriggerEvents; +import org.openhab.core.types.State; + +/** + * + * @author Daniel Weber - Initial contribution + */ +public abstract class F6_02 extends _RPSMessage { + + final byte AI = 0; + final byte A0 = 1; + final byte BI = 2; + final byte B0 = 3; + final byte PRESSED = 16; + final byte PRESSED_SEC = 1; + + final String DIR1 = "DIR1"; + final String DIR2 = "DIR2"; + final String ANYDIR = "*"; + final String NODIR = "-"; + + int secondByte = -1; + int secondStatus = -1; + + public F6_02() { + super(); + } + + public F6_02(ERP1Message packet) { + super(packet); + } + + private String getChannelADir() { + if ((bytes[0] >>> 5) == A0 && (bytes[0] & PRESSED) != 0) { + return DIR1; + } else if ((bytes[0] >>> 5) == AI && (bytes[0] & PRESSED) != 0) { + return DIR2; + } else { + return NODIR; + } + } + + private String getChannelBDir() { + if ((bytes[0] >>> 5) == B0 && (bytes[0] & PRESSED) != 0) { + return DIR1; + } else if ((bytes[0] >>> 5) == BI && (bytes[0] & PRESSED) != 0) { + return DIR2; + } else if (((bytes[0] & 0xf) >>> 1) == B0 && (bytes[0] & PRESSED_SEC) != 0) { + return DIR1; + } else if (((bytes[0] & 0xf) >>> 1) == BI && (bytes[0] & PRESSED_SEC) != 0) { + return DIR2; + } else { + return NODIR; + } + } + + protected String getRockerSwitchAction(Configuration config) { + EnOceanChannelRockerSwitchActionConfig conf = config.as(EnOceanChannelRockerSwitchActionConfig.class); + String dirA = getChannelADir(); + String dirB = getChannelBDir(); + + if (!(conf.channelAFilter.equals(ANYDIR) || conf.channelAFilter.equals(dirA))) { + return null; + } else if (!(conf.channelBFilter.equals(ANYDIR) || conf.channelBFilter.equals(dirB))) { + return null; + } else { + return dirA + "|" + dirB; + } + } + + protected String getChannelEvent(byte dir1, byte dir2) { + if ((bytes[0] >>> 5) == dir1) { + return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR1_PRESSED : CommonTriggerEvents.DIR1_RELEASED; + } else if ((bytes[0] >>> 5) == dir2) { + return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED : CommonTriggerEvents.DIR2_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED + : CommonTriggerEvents.DIR1_RELEASED; + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED + : CommonTriggerEvents.DIR2_RELEASED; + } else { + return null; + } + } + + protected State inverse(OnOffType currentState) { + return currentState == OnOffType.ON ? OnOffType.OFF : OnOffType.ON; + } + + protected State inverse(UpDownType currentState) { + return currentState == UpDownType.UP ? UpDownType.DOWN : UpDownType.UP; + } + + @Override + protected boolean validateData(byte[] bytes) { + return super.validateData(bytes) && !getBit(bytes[0], 7); + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java index 9231a58692c81..afcbfa70005d1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java @@ -33,17 +33,7 @@ * * @author Daniel Weber - Initial contribution */ -public class F6_02_01 extends _RPSMessage { - - final byte AI = 0; - final byte A0 = 1; - final byte BI = 2; - final byte B0 = 3; - final byte PRESSED = 16; - final byte PRESSED_SEC = 1; - - int secondByte = -1; - int secondStatus = -1; +public class F6_02_01 extends F6_02 { public F6_02_01() { super(); @@ -58,27 +48,23 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri Configuration config) { if (t21 && nu) { - byte dir1 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? A0 : B0; - byte dir2 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? AI : BI; - - if ((bytes[0] >>> 5) == dir1) { - return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR1_PRESSED - : CommonTriggerEvents.DIR1_RELEASED; - } else if ((bytes[0] >>> 5) == dir2) { - return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED - : CommonTriggerEvents.DIR2_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED - : CommonTriggerEvents.DIR1_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED - : CommonTriggerEvents.DIR2_RELEASED; + if (CHANNEL_ROCKERSWITCH_ACTION.equals(channelTypeId)) { + return getRockerSwitchAction(config); + } else { + byte dir1 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? A0 : B0; + byte dir2 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? AI : BI; + + return getChannelEvent(dir1, dir2); } } else if (t21 && !nu) { - if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { - return CommonTriggerEvents.DIR1_RELEASED; - } else if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR2_PRESSED)) { - return CommonTriggerEvents.DIR2_RELEASED; + if (CHANNEL_ROCKERSWITCH_ACTION.equals(channelTypeId)) { + return CommonTriggerEvents.RELEASED; + } else { + if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { + return CommonTriggerEvents.DIR1_RELEASED; + } else if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR2_PRESSED)) { + return CommonTriggerEvents.DIR2_RELEASED; + } } } @@ -117,94 +103,90 @@ protected State convertToStateImpl(String channelId, String channelTypeId, // appropriate item update State currentState = getCurrentStateFunc.apply(channelId); if (t21 && nu) { - EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); - byte dir1 = c.getChannel() == Channel.ChannelA ? A0 : B0; - byte dir2 = c.getChannel() == Channel.ChannelA ? AI : BI; - - // We are just listening on the pressed event here - switch (c.getSwitchMode()) { - case RockerSwitch: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; + if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { + return ((bytes[0] & PRESSED_SEC) != 0) ? OnOffType.ON : OnOffType.OFF; + } else { + EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); + byte dir1 = c.getChannel() == Channel.ChannelA ? A0 : B0; + byte dir2 = c.getChannel() == Channel.ChannelA ? AI : BI; + + // We are just listening on the pressed event here + switch (c.getSwitchMode()) { + case RockerSwitch: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; + break; + case ToggleDir1: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } - } - break; - case ToggleDir1: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); + break; + case ToggleDir2: + if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - case ToggleDir2: - if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - default: - break; + break; + default: + break; + } + } + } else if (t21 && !nu) { + // always unset SecondActionPressed if any rocker switch action is released + if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { + return OnOffType.OFF; } } return UnDefType.UNDEF; } - private State inverse(OnOffType currentState) { - return currentState == OnOffType.ON ? OnOffType.OFF : OnOffType.ON; - } - - private State inverse(UpDownType currentState) { - return currentState == UpDownType.UP ? UpDownType.DOWN : UpDownType.UP; - } - - @Override - protected boolean validateData(byte[] bytes) { - return super.validateData(bytes) && !getBit(bytes[0], 7); - } - @Override public boolean isValidForTeachIn() { if (t21) { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java index 7ae7bcbafe444..a5e61f775441f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java @@ -33,14 +33,7 @@ * * @author Daniel Weber - Initial contribution */ -public class F6_02_02 extends _RPSMessage { - - final byte AI = 0; - final byte A0 = 1; - final byte BI = 2; - final byte B0 = 3; - final byte PRESSED = 16; - final byte PRESSED_SEC = 1; +public class F6_02_02 extends F6_02 { public F6_02_02() { super(); @@ -55,27 +48,22 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri Configuration config) { if (t21 && nu) { - byte dir1 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? AI : BI; - byte dir2 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? A0 : B0; - - if ((bytes[0] >>> 5) == dir1) { - return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR1_PRESSED - : CommonTriggerEvents.DIR1_RELEASED; - } else if ((bytes[0] >>> 5) == dir2) { - return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED - : CommonTriggerEvents.DIR2_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED - : CommonTriggerEvents.DIR1_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED - : CommonTriggerEvents.DIR2_RELEASED; + if (CHANNEL_ROCKERSWITCH_ACTION.equals(channelTypeId)) { + return getRockerSwitchAction(config); + } else { + byte dir1 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? AI : BI; + byte dir2 = channelId.equals(CHANNEL_ROCKERSWITCH_CHANNELA) ? A0 : B0; + return getChannelEvent(dir1, dir2); } } else if (t21 && !nu) { - if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { - return CommonTriggerEvents.DIR1_RELEASED; - } else if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR2_PRESSED)) { - return CommonTriggerEvents.DIR2_RELEASED; + if (CHANNEL_ROCKERSWITCH_ACTION.equals(channelTypeId)) { + return CommonTriggerEvents.RELEASED; + } else { + if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR1_PRESSED)) { + return CommonTriggerEvents.DIR1_RELEASED; + } else if (lastEvent != null && lastEvent.equals(CommonTriggerEvents.DIR2_PRESSED)) { + return CommonTriggerEvents.DIR2_RELEASED; + } } } @@ -114,89 +102,90 @@ protected State convertToStateImpl(String channelId, String channelTypeId, // appropriate item update State currentState = getCurrentStateFunc.apply(channelId); if (t21 && nu) { - EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); - byte dir1 = c.getChannel() == Channel.ChannelA ? AI : BI; - byte dir2 = c.getChannel() == Channel.ChannelA ? A0 : B0; - - // We are just listening on the pressed event here - switch (c.getSwitchMode()) { - case RockerSwitch: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } - break; - case ToggleDir1: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); + if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { + return ((bytes[0] & PRESSED_SEC) != 0) ? OnOffType.ON : OnOffType.OFF; + } else { + EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); + byte dir1 = c.getChannel() == Channel.ChannelA ? AI : BI; + byte dir2 = c.getChannel() == Channel.ChannelA ? A0 : B0; + + // We are just listening on the pressed event here + switch (c.getSwitchMode()) { + case RockerSwitch: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON + : UpDownType.UP; + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } } - } - break; - case ToggleDir2: - if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); + break; + case ToggleDir1: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); + break; + case ToggleDir2: + if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON + : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } } - } - break; - default: - break; + break; + default: + break; + } + } + } else if (t21 && !nu) { + // always unset SecondActionPressed if any rocker switch action is released + if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { + return OnOffType.OFF; } } return UnDefType.UNDEF; } - private State inverse(OnOffType currentState) { - return currentState == OnOffType.ON ? OnOffType.OFF : OnOffType.ON; - } - - private State inverse(UpDownType currentState) { - return currentState == UpDownType.UP ? UpDownType.DOWN : UpDownType.UP; - } - @Override public boolean isValidForTeachIn() { return false; // Never treat a message as F6-02-02, let user decide which orientation of rocker switch is used diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java index 736b37be23671..75a2e615900eb 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/handler/EnOceanBaseSensorHandler.java @@ -128,7 +128,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { protected Predicate channelFilter(EEPType eepType, byte[] senderId) { return c -> { - boolean result = eepType.GetSupportedChannels().containsKey(c.getUID().getId()); + + boolean result = eepType.isChannelSupported(c); return (isLinked(c.getUID()) || c.getKind() == ChannelKind.TRIGGER) && result; }; } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java new file mode 100644 index 0000000000000..3afc467a9660d --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java @@ -0,0 +1,109 @@ +/** + * 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.profiles; + +import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; +import static org.openhab.binding.enocean.internal.profiles.EnOceanProfiles.*; + +import java.util.Collection; +import java.util.Collections; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.library.CoreItemFactory; +import org.openhab.core.thing.Channel; +import org.openhab.core.thing.profiles.Profile; +import org.openhab.core.thing.profiles.ProfileAdvisor; +import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileContext; +import org.openhab.core.thing.profiles.ProfileFactory; +import org.openhab.core.thing.profiles.ProfileType; +import org.openhab.core.thing.profiles.ProfileTypeProvider; +import org.openhab.core.thing.profiles.ProfileTypeUID; +import org.openhab.core.thing.type.ChannelType; +import org.openhab.core.thing.type.ChannelTypeRegistry; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; + +/** + * The {@link EnOceanProfileFactory} class creates EnOceanProfiles + * + * @author Daniel Weber - Initial contribution + */ +@Component +@NonNullByDefault +public class EnOceanProfileFactory implements ProfileFactory, ProfileAdvisor, ProfileTypeProvider { + + private static final Set SUPPORTED_PROFILE_TYPES = Set.of(ROCKERSWITCHACTION_TOGGLE_SWITCH_TYPE, + ROCKERSWITCHACTION_TOGGLE_PLAYER_TYPE); + + private static final Set SUPPORTED_PROFILE_TYPE_UIDS = Set.of(ROCKERSWITCHACTION_TOGGLE_SWITCH, + ROCKERSWITCHACTION_TOGGLE_PLAYER); + + private final ChannelTypeRegistry channelTypeRegistry; + + @Activate + public EnOceanProfileFactory(final @Reference ChannelTypeRegistry channelTypeRegistry) { + this.channelTypeRegistry = channelTypeRegistry; + } + + @Override + public Collection getProfileTypes(@Nullable Locale locale) { + return Collections.unmodifiableList(SUPPORTED_PROFILE_TYPES.stream().collect(Collectors.toList())); + } + + @Override + public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(Channel channel, @Nullable String itemType) { + ChannelType channelType = channelTypeRegistry.getChannelType(channel.getChannelTypeUID()); + if (channelType == null) { + return null; + } + + return getSuggestedProfileTypeUID(channelType, itemType); + } + + @Override + public @Nullable ProfileTypeUID getSuggestedProfileTypeUID(ChannelType channelType, @Nullable String itemType) { + + if (CHANNELTYPE_ROCKERSWITCH_ACTION_UID.equals(channelType.getUID())) { + if (CoreItemFactory.PLAYER.equalsIgnoreCase(itemType)) { + return ROCKERSWITCHACTION_TOGGLE_PLAYER; + } else if (CoreItemFactory.SWITCH.equalsIgnoreCase(itemType)) { + return ROCKERSWITCHACTION_TOGGLE_SWITCH; + } + } + + return null; + } + + @Override + public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, + ProfileContext profileContext) { + if (ROCKERSWITCHACTION_TOGGLE_PLAYER.equals(profileTypeUID)) { + return new RockerSwitchActionTogglePlayerProfile(callback); + } else if (ROCKERSWITCHACTION_TOGGLE_SWITCH.equals(profileTypeUID)) { + return new RockerSwitchActionToggleSwitchProfile(callback); + } else { + return null; + } + } + + @Override + public Collection getSupportedProfileTypeUIDs() { + return Collections.unmodifiableList(SUPPORTED_PROFILE_TYPE_UIDS.stream().collect(Collectors.toList())); + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfiles.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfiles.java new file mode 100644 index 0000000000000..ad5288ea4cd76 --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfiles.java @@ -0,0 +1,45 @@ +/** + * 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.profiles; + +import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.library.CoreItemFactory; +import org.openhab.core.thing.profiles.ProfileType; +import org.openhab.core.thing.profiles.ProfileTypeBuilder; +import org.openhab.core.thing.profiles.ProfileTypeUID; + +/** + * The {@link EnOceanProfiles} class defines profile constants + * + * @author Daniel Weber - Initial contribution + */ +@NonNullByDefault +public class EnOceanProfiles { + public static final ProfileTypeUID ROCKERSWITCHACTION_TOGGLE_SWITCH = new ProfileTypeUID(BINDING_ID, + "rockerswitchaction-toggle-switch"); + + public static final ProfileTypeUID ROCKERSWITCHACTION_TOGGLE_PLAYER = new ProfileTypeUID(BINDING_ID, + "rockerswitchaction-toggle-player"); + + static final ProfileType ROCKERSWITCHACTION_TOGGLE_SWITCH_TYPE = ProfileTypeBuilder + .newTrigger(ROCKERSWITCHACTION_TOGGLE_SWITCH, "Rocker Switch Action Toggle Switch") + .withSupportedItemTypes(CoreItemFactory.SWITCH) + .withSupportedChannelTypeUIDs(CHANNELTYPE_ROCKERSWITCH_ACTION_UID).build(); + + static final ProfileType ROCKERSWITCHACTION_TOGGLE_PLAYER_TYPE = ProfileTypeBuilder + .newTrigger(ROCKERSWITCHACTION_TOGGLE_PLAYER, "Rocker Switch Action Toggle Player") + .withSupportedItemTypes(CoreItemFactory.PLAYER) + .withSupportedChannelTypeUIDs(CHANNELTYPE_ROCKERSWITCH_ACTION_UID).build(); +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java new file mode 100644 index 0000000000000..d0f7386c1982e --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java @@ -0,0 +1,60 @@ +/** + * 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.profiles; + +import static org.openhab.binding.enocean.internal.profiles.EnOceanProfiles.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.library.types.PlayPauseType; +import org.openhab.core.thing.CommonTriggerEvents; +import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileTypeUID; +import org.openhab.core.thing.profiles.TriggerProfile; +import org.openhab.core.types.State; + +/** + * @author Daniel Weber - Initial contribution + */ +@NonNullByDefault +public class RockerSwitchActionTogglePlayerProfile implements TriggerProfile { + + private final ProfileCallback callback; + + private @Nullable State previousState; + + public RockerSwitchActionTogglePlayerProfile(ProfileCallback callback) { + this.callback = callback; + } + + @Override + public ProfileTypeUID getProfileTypeUID() { + return ROCKERSWITCHACTION_TOGGLE_PLAYER; + } + + @Override + public void onStateUpdateFromItem(State state) { + previousState = state.as(PlayPauseType.class); + } + + @Override + public void onTriggerFromHandler(String event) { + // Ignore released event + if (!CommonTriggerEvents.RELEASED.equals(event)) { + PlayPauseType newState = PlayPauseType.PLAY.equals(previousState) ? PlayPauseType.PAUSE + : PlayPauseType.PLAY; + callback.sendCommand(newState); + previousState = newState; + } + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java new file mode 100644 index 0000000000000..2a65f4db372f7 --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java @@ -0,0 +1,59 @@ +/** + * 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.profiles; + +import static org.openhab.binding.enocean.internal.profiles.EnOceanProfiles.*; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.library.types.OnOffType; +import org.openhab.core.thing.CommonTriggerEvents; +import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileTypeUID; +import org.openhab.core.thing.profiles.TriggerProfile; +import org.openhab.core.types.State; + +/** + * @author Daniel Weber - Initial contribution + */ +@NonNullByDefault +public class RockerSwitchActionToggleSwitchProfile implements TriggerProfile { + + private final ProfileCallback callback; + + private @Nullable State previousState; + + public RockerSwitchActionToggleSwitchProfile(ProfileCallback callback) { + this.callback = callback; + } + + @Override + public ProfileTypeUID getProfileTypeUID() { + return ROCKERSWITCHACTION_TOGGLE_SWITCH; + } + + @Override + public void onStateUpdateFromItem(State state) { + previousState = state.as(OnOffType.class); + } + + @Override + public void onTriggerFromHandler(String event) { + // Ignore released event + if (!CommonTriggerEvents.RELEASED.equals(event)) { + OnOffType newState = OnOffType.ON.equals(previousState) ? OnOffType.OFF : OnOffType.ON; + callback.sendCommand(newState); + previousState = newState; + } + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml index c8652487d8b16..dda3fc9edb886 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @@ -20,6 +20,9 @@ + + + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml index 941eb0d76487a..2c97c83d9afca 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml @@ -752,4 +752,52 @@ + + Switch + + Indicates if second action of rocker switch is pressed. + + + + + trigger + + Is triggered when a certain combination of rockers is pressed or released. + + + + + + + + + + + + + + + + + * + + + + + + + + + + * + + + + + + + + + + From 5af46499fd0bb47a89a2980b25e5893c6b37026c Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Fri, 3 Sep 2021 14:44:17 +0200 Subject: [PATCH 3/6] [enocean] Fixed spotless errors (Fixes #9750) Signed-off-by: Daniel Weber --- .../binding/enocean/internal/EnOceanBindingConstants.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java index d104020d84afb..e3bf87b7b084b 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java @@ -207,7 +207,6 @@ public class EnOceanBindingConstants { public static final String CHANNEL_SUPPLYFANSPEED = "supplyFanSpeed"; public static final String CHANNEL_EXHAUSTFANSPEED = "exhaustFanSpeed"; - public static final Map CHANNELID2CHANNELDESCRIPTION = Map.ofEntries( Map.entry(CHANNEL_GENERAL_SWITCHING, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_GENERAL_SWITCHING), @@ -298,8 +297,7 @@ public class EnOceanBindingConstants { Map.entry(CHANNEL_INDOORAIRANALYSIS, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_INDOORAIRANALYSIS), CoreItemFactory.STRING)), - Map.entry( - CHANNEL_SETPOINT, + Map.entry(CHANNEL_SETPOINT, new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_SETPOINT), CoreItemFactory.NUMBER)), Map.entry(CHANNEL_CONTACT, From 5d662d07029d7809063d80b2855ea0411ce499d8 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Sun, 10 Oct 2021 15:47:44 +0200 Subject: [PATCH 4/6] [enocean] Add second action for two rocker switches (Fixes #9750) * Channels "rockerswitchA" and "rockerswitchB" do not longer react if second action is pressed * Added new parameter "handleSecondAction" to channel "rockerswitchListenerSwitch" and "rockerswitchListenerRollershutter" to define if classicDevice should react if second action is pressed too * Added documentation * EEP F6-02 refactoring Signed-off-by: Daniel Weber --- bundles/org.openhab.binding.enocean/README.md | 4 +- .../internal/EnOceanBindingConstants.java | 5 - ...nOceanChannelRockerSwitchActionConfig.java | 1 + ...ceanChannelRockerSwitchListenerConfig.java | 2 + .../binding/enocean/internal/eep/EEPType.java | 14 ++- .../enocean/internal/eep/F6_02/F6_02.java | 86 ++++++++++++++--- .../enocean/internal/eep/F6_02/F6_02_01.java | 92 ++----------------- .../enocean/internal/eep/F6_02/F6_02_02.java | 90 ++---------------- ...RockerSwitchActionTogglePlayerProfile.java | 2 + ...RockerSwitchActionToggleSwitchProfile.java | 2 + .../main/resources/OH-INF/config/config.xml | 5 + 11 files changed, 111 insertions(+), 192 deletions(-) diff --git a/bundles/org.openhab.binding.enocean/README.md b/bundles/org.openhab.binding.enocean/README.md index d60b0fa640f8a..257bb8eb77bcb 100644 --- a/bundles/org.openhab.binding.enocean/README.md +++ b/bundles/org.openhab.binding.enocean/README.md @@ -100,6 +100,9 @@ Hence if your device supports one of the following EEPs the chances are good tha Furthermore following supporting EEP family is available too: A5-11, types 0x03 (rollershutter position status), 0x04 (extended light status) and D0-06 (battery level indication). A `rockerSwitch` is used to receive messages from a physical EnOcean Rocker Switch. +Channel `rockerswitchA` and `rockerswitchA` just react if corresponding rocker switch channel is pressed as single action. +These channels do not emit an event if ChannelA and ChannelB are pressed simultaneously. +To handle simultaneously pressed channels you have to use the `rockerSwitchAction` channel and configure it accordingly. A `classicDevice` is used for older EnOcean devices which react only on rocker switch messages (like Opus GN-A-R12V-SR-4). As these devices do not send their current status, you have to add additional listener channels for each physical Rocker Switch to your thing. In this way you can still sync your item status with the physical status of your device whenever it gets modified by a physical rocker switch. @@ -254,7 +257,6 @@ The channels of a thing are determined automatically based on the chosen EEP. | doublePress | Trigger | Channel type system:rawbutton, emits PRESSED | | longPress | Trigger | Channel type system:rawbutton, emits PRESSED and RELEASED events | | rockerswitchA/B | Trigger | Channel type system:rawrocker, emits DIR1_PRESSED, DIR1_RELEASED, DIR2_PRESSED, DIR2_RELEASED events | -| secondActionPressed | Switch | Indicates if second action of rocker switch is pressed too | | rockerSwitchAction | Trigger | Emits combined rocker switch actions for channel A and B and RELEASED events | | windowHandleState | String | Textual representation of handle position (OPEN, CLOSED, TILTED) | | contact | Contact | State OPEN/CLOSED (tilted handle => OPEN) | diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java index e3bf87b7b084b..c449057a084f1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/EnOceanBindingConstants.java @@ -129,7 +129,6 @@ public class EnOceanBindingConstants { public static final String CHANNEL_ROCKERSWITCH_CHANNELA = "rockerswitchA"; public static final String CHANNEL_ROCKERSWITCH_CHANNELB = "rockerswitchB"; - public static final String CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED = "secondActionPressed"; public static final String CHANNEL_ROCKERSWITCH_ACTION = "rockerSwitchAction"; public static final ChannelTypeUID CHANNELTYPE_ROCKERSWITCH_ACTION_UID = new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCH_ACTION); @@ -341,10 +340,6 @@ public class EnOceanBindingConstants { Map.entry(CHANNEL_ROCKERSWITCH_CHANNELB, new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWROCKER.getUID(), null, "Rocker Switch - Channel B", false, false)), - Map.entry(CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, - new EnOceanChannelDescription( - new ChannelTypeUID(BINDING_ID, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED), - CoreItemFactory.SWITCH, "Second Action Pressed", false, false)), Map.entry(CHANNEL_ROCKERSWITCH_ACTION, new EnOceanChannelDescription(CHANNELTYPE_ROCKERSWITCH_ACTION_UID, null, "Rocker Switch Action", false, false)), diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java index d39ea16ddf584..d5bad6edf4520 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java @@ -15,6 +15,7 @@ /** * * @author Daniel Weber - Initial contribution + * This config class is used for channel rockerSwitchAction to define in which case it triggers. */ public class EnOceanChannelRockerSwitchActionConfig { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchListenerConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchListenerConfig.java index 0212060b04157..8e2047ff427a8 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchListenerConfig.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchListenerConfig.java @@ -19,9 +19,11 @@ public class EnOceanChannelRockerSwitchListenerConfig extends EnOceanChannelRockerSwitchConfigBase { public String enoceanId; + public boolean handleSecondAction; public EnOceanChannelRockerSwitchListenerConfig() { super(); enoceanId = null; + handleSecondAction = false; } } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java index 50b6c36c06af1..359c1b0e822ed 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/EEPType.java @@ -177,16 +177,14 @@ public enum EEPType { CHANNEL_DOUBLEPRESS, CHANNEL_LONGPRESS, CHANNEL_BATTERY_LEVEL), RockerSwitch2RockerStyle1(RORG.RPS, 0x02, 0x01, false, F6_02_01.class, THING_TYPE_ROCKERSWITCH, - CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, - CHANNEL_ROCKERSWITCH_ACTION, CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, - CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, - CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), + CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_ACTION, + CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, CHANNEL_VIRTUALROCKERSWITCHB, + CHANNEL_ROCKERSWITCHLISTENERSWITCH, CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), RockerSwitch2RockerStyle2(RORG.RPS, 0x02, 0x02, false, F6_02_02.class, THING_TYPE_ROCKERSWITCH, - CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED, - CHANNEL_ROCKERSWITCH_ACTION, CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, - CHANNEL_VIRTUALROCKERSWITCHB, CHANNEL_ROCKERSWITCHLISTENERSWITCH, - CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), + CHANNEL_ROCKERSWITCH_CHANNELA, CHANNEL_ROCKERSWITCH_CHANNELB, CHANNEL_ROCKERSWITCH_ACTION, + CHANNEL_VIRTUALSWITCHA, CHANNEL_VIRTUALROLLERSHUTTERA, CHANNEL_VIRTUALROCKERSWITCHB, + CHANNEL_ROCKERSWITCHLISTENERSWITCH, CHANNEL_ROCKERSWITCHLISTENERROLLERSHUTTER), MechanicalHandle00(RORG.RPS, 0x10, 0x00, false, F6_10_00.class, THING_TYPE_MECHANICALHANDLE, CHANNEL_WINDOWHANDLESTATE, CHANNEL_CONTACT), diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java index a5834c915cd17..f53c5b352f73a 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java @@ -12,7 +12,10 @@ */ package org.openhab.binding.enocean.internal.eep.F6_02; +import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; + import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchActionConfig; +import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchConfigBase.SwitchMode; import org.openhab.binding.enocean.internal.eep.Base._RPSMessage; import org.openhab.binding.enocean.internal.messages.ERP1Message; import org.openhab.core.config.core.Configuration; @@ -20,6 +23,7 @@ import org.openhab.core.library.types.UpDownType; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.types.State; +import org.openhab.core.types.UnDefType; /** * @@ -65,10 +69,6 @@ private String getChannelBDir() { return DIR1; } else if ((bytes[0] >>> 5) == BI && (bytes[0] & PRESSED) != 0) { return DIR2; - } else if (((bytes[0] & 0xf) >>> 1) == B0 && (bytes[0] & PRESSED_SEC) != 0) { - return DIR1; - } else if (((bytes[0] & 0xf) >>> 1) == BI && (bytes[0] & PRESSED_SEC) != 0) { - return DIR2; } else { return NODIR; } @@ -89,21 +89,85 @@ protected String getRockerSwitchAction(Configuration config) { } protected String getChannelEvent(byte dir1, byte dir2) { - if ((bytes[0] >>> 5) == dir1) { + if ((bytes[0] & PRESSED_SEC) != 0) { + // Do not emit an event if channelA is pressed together with channelB as it is undetermined which one gets + // fired first + return null; + } else if ((bytes[0] >>> 5) == dir1) { return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR1_PRESSED : CommonTriggerEvents.DIR1_RELEASED; } else if ((bytes[0] >>> 5) == dir2) { return ((bytes[0] & PRESSED) != 0) ? CommonTriggerEvents.DIR2_PRESSED : CommonTriggerEvents.DIR2_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR1_PRESSED - : CommonTriggerEvents.DIR1_RELEASED; - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - return ((bytes[0] & PRESSED_SEC) != 0) ? CommonTriggerEvents.DIR2_PRESSED - : CommonTriggerEvents.DIR2_RELEASED; } else { return null; } } + protected State getState(byte dir1, byte dir2, boolean handleSecondAction, SwitchMode switchMode, + String channelTypeId, State currentState) { + // We are just listening on the pressed event here + switch (switchMode) { + case RockerSwitch: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON : UpDownType.UP; + } + } else if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } + } else if (handleSecondAction && ((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON : UpDownType.UP; + } + } else if (handleSecondAction && ((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF + : UpDownType.DOWN; + } + } + break; + case ToggleDir1: + if ((bytes[0] >>> 5) == dir1) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (handleSecondAction && ((bytes[0] & 0xf) >>> 1) == dir1) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } + break; + case ToggleDir2: + if ((bytes[0] >>> 5) == dir2) { + if (((bytes[0] & PRESSED) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } else if (handleSecondAction && ((bytes[0] & 0xf) >>> 1) == dir2) { + if (((bytes[0] & PRESSED_SEC) != 0)) { + return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) + ? (currentState == UnDefType.UNDEF ? OnOffType.ON : inverse((OnOffType) currentState)) + : (currentState == UnDefType.UNDEF ? UpDownType.UP + : inverse((UpDownType) currentState)); + } + } + break; + default: + break; + } + + return UnDefType.UNDEF; + } + protected State inverse(OnOffType currentState) { return currentState == OnOffType.ON ? OnOffType.OFF : OnOffType.ON; } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java index afcbfa70005d1..f14d3edc70b3c 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_01.java @@ -17,13 +17,11 @@ import java.util.function.Function; import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchConfigBase.Channel; -import org.openhab.binding.enocean.internal.config.EnOceanChannelVirtualRockerSwitchConfig; +import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchListenerConfig; import org.openhab.binding.enocean.internal.eep.Base._RPSMessage; import org.openhab.binding.enocean.internal.messages.ERP1Message; import org.openhab.core.config.core.Configuration; -import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; -import org.openhab.core.library.types.UpDownType; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.types.Command; import org.openhab.core.types.State; @@ -75,7 +73,7 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command, Function getCurrentStateFunc, Configuration config) { if (command instanceof StringType) { - StringType s = (StringType) command; + String s = ((StringType) command).toString(); if (s.equals(CommonTriggerEvents.DIR1_RELEASED) || s.equals(CommonTriggerEvents.DIR2_RELEASED)) { setStatus(_RPSMessage.T21Flag); @@ -99,89 +97,15 @@ protected void convertFromCommandImpl(String channelId, String channelTypeId, Co @Override protected State convertToStateImpl(String channelId, String channelTypeId, Function getCurrentStateFunc, Configuration config) { - // this method is used by the classic device listener channels to convert an rocker switch message into an + // this method is used by the classic device listener channels to convert a rocker switch message into an // appropriate item update State currentState = getCurrentStateFunc.apply(channelId); if (t21 && nu) { - if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { - return ((bytes[0] & PRESSED_SEC) != 0) ? OnOffType.ON : OnOffType.OFF; - } else { - EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); - byte dir1 = c.getChannel() == Channel.ChannelA ? A0 : B0; - byte dir2 = c.getChannel() == Channel.ChannelA ? AI : BI; - - // We are just listening on the pressed event here - switch (c.getSwitchMode()) { - case RockerSwitch: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } - break; - case ToggleDir1: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - case ToggleDir2: - if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - default: - break; - } - } - } else if (t21 && !nu) { - // always unset SecondActionPressed if any rocker switch action is released - if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { - return OnOffType.OFF; - } + EnOceanChannelRockerSwitchListenerConfig c = config.as(EnOceanChannelRockerSwitchListenerConfig.class); + byte dir1 = c.getChannel() == Channel.ChannelA ? A0 : B0; + byte dir2 = c.getChannel() == Channel.ChannelA ? AI : BI; + + return getState(dir1, dir2, c.handleSecondAction, c.getSwitchMode(), channelTypeId, currentState); } return UnDefType.UNDEF; diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java index a5e61f775441f..5b7fdca8d10c7 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java @@ -17,13 +17,11 @@ import java.util.function.Function; import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchConfigBase.Channel; -import org.openhab.binding.enocean.internal.config.EnOceanChannelVirtualRockerSwitchConfig; +import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchListenerConfig; import org.openhab.binding.enocean.internal.eep.Base._RPSMessage; import org.openhab.binding.enocean.internal.messages.ERP1Message; import org.openhab.core.config.core.Configuration; -import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.StringType; -import org.openhab.core.library.types.UpDownType; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.types.Command; import org.openhab.core.types.State; @@ -98,89 +96,15 @@ protected void convertFromCommandImpl(String channelId, String channelTypeId, Co @Override protected State convertToStateImpl(String channelId, String channelTypeId, Function getCurrentStateFunc, Configuration config) { - // this method is used by the classic device listener channels to convert an rocker switch message into an + // this method is used by the classic device listener channels to convert a rocker switch message into an // appropriate item update State currentState = getCurrentStateFunc.apply(channelId); if (t21 && nu) { - if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { - return ((bytes[0] & PRESSED_SEC) != 0) ? OnOffType.ON : OnOffType.OFF; - } else { - EnOceanChannelVirtualRockerSwitchConfig c = config.as(EnOceanChannelVirtualRockerSwitchConfig.class); - byte dir1 = c.getChannel() == Channel.ChannelA ? AI : BI; - byte dir2 = c.getChannel() == Channel.ChannelA ? A0 : B0; - - // We are just listening on the pressed event here - switch (c.getSwitchMode()) { - case RockerSwitch: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.ON - : UpDownType.UP; - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) ? OnOffType.OFF - : UpDownType.DOWN; - } - } - break; - case ToggleDir1: - if ((bytes[0] >>> 5) == dir1) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir1) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - case ToggleDir2: - if ((bytes[0] >>> 5) == dir2) { - if (((bytes[0] & PRESSED) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } else if (((bytes[0] & 0xf) >>> 1) == dir2) { - if (((bytes[0] & PRESSED_SEC) != 0)) { - return channelTypeId.equals(CHANNEL_ROCKERSWITCHLISTENERSWITCH) - ? (currentState == UnDefType.UNDEF ? OnOffType.ON - : inverse((OnOffType) currentState)) - : (currentState == UnDefType.UNDEF ? UpDownType.UP - : inverse((UpDownType) currentState)); - } - } - break; - default: - break; - } - } - } else if (t21 && !nu) { - // always unset SecondActionPressed if any rocker switch action is released - if (CHANNEL_ROCKERSWITCH_SECONDACTIONPRESSED.equals(channelTypeId)) { - return OnOffType.OFF; - } + EnOceanChannelRockerSwitchListenerConfig c = config.as(EnOceanChannelRockerSwitchListenerConfig.class); + byte dir1 = c.getChannel() == Channel.ChannelA ? AI : BI; + byte dir2 = c.getChannel() == Channel.ChannelA ? A0 : B0; + + return getState(dir1, dir2, c.handleSecondAction, c.getSwitchMode(), channelTypeId, currentState); } return UnDefType.UNDEF; diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java index d0f7386c1982e..04e3fe1093a24 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java @@ -25,6 +25,8 @@ /** * @author Daniel Weber - Initial contribution + * This profile is used for channel rockerSwitchAction to be able to bind this trigger channel directly to a + * player item */ @NonNullByDefault public class RockerSwitchActionTogglePlayerProfile implements TriggerProfile { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java index 2a65f4db372f7..73f71c0857544 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java @@ -25,6 +25,8 @@ /** * @author Daniel Weber - Initial contribution + * This profile is used for channel rockerSwitchAction to be able to bind this trigger channel directly to a + * switch item */ @NonNullByDefault public class RockerSwitchActionToggleSwitchProfile implements TriggerProfile { diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml index ebd49c604dd7b..54c150138ddf1 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml @@ -29,6 +29,11 @@ channelA + + + React if selected channel is pressed as second action too + false + From 0dd77db23f4a8939da960947f54f6a1a20299412 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Mon, 11 Oct 2021 12:57:40 +0200 Subject: [PATCH 5/6] [enocean] Add second action for two rocker switches (Fixes #9750) * Moved channel config for "rockerSwitchAction" into profiles * Updated and cleaned README Signed-off-by: Daniel Weber --- bundles/org.openhab.binding.enocean/README.md | 13 ++++- ...OceanProfileRockerSwitchActionConfig.java} | 7 ++- .../enocean/internal/eep/F6_02/F6_02.java | 15 ++--- .../enocean/internal/eep/F6_02/F6_02_02.java | 2 +- .../profiles/EnOceanProfileFactory.java | 4 +- .../RockerSwitchActionBaseProfile.java | 57 +++++++++++++++++++ ...RockerSwitchActionTogglePlayerProfile.java | 20 +++---- ...RockerSwitchActionToggleSwitchProfile.java | 20 +++---- .../main/resources/OH-INF/config/config.xml | 23 ++++++++ .../resources/OH-INF/thing/RockerSwitch.xml | 6 +- .../main/resources/OH-INF/thing/channels.xml | 29 ---------- 11 files changed, 122 insertions(+), 74 deletions(-) rename bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/{EnOceanChannelRockerSwitchActionConfig.java => EnOceanProfileRockerSwitchActionConfig.java} (70%) create mode 100644 bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionBaseProfile.java diff --git a/bundles/org.openhab.binding.enocean/README.md b/bundles/org.openhab.binding.enocean/README.md index 257bb8eb77bcb..30fe3d0a2fd2c 100644 --- a/bundles/org.openhab.binding.enocean/README.md +++ b/bundles/org.openhab.binding.enocean/README.md @@ -75,7 +75,7 @@ Hence if your device supports one of the following EEPs the chances are good tha |---------------------------------|-------------|---------------|------------------------------|--------------------------------|-----------| | bridge | - | - | repeaterMode, setBaseId | USB300, EnOceanPi | - | | pushButton | F6-01/D2-03 | 0x01/0x0A | pushButton, doublePress,
longPress, batteryLevel | NodOn soft button | Manually/Discovery | -| rockerSwitch | F6-02 | 0x01-02 | rockerswitchA, rockerswitchB,
secondActionPressed, rockerSwitchAction | Eltako FT55 | Discovery | +| rockerSwitch | F6-02 | 0x01-02 | rockerswitchA, rockerswitchB,
rockerSwitchAction | Eltako FT55 | Discovery | | mechanicalHandle | F6-10 | 0x00-01 | windowHandleState, contact | Hoppe SecuSignal handles, Eltako TF-FGB | Discovery | | contact | D5-00 | 0x01 | contact | Eltako FTK(E) & TF-FKB | Discovery | | temperatureSensor | A5-02 | 0x01-30 | temperature | Thermokon SR65 | Discovery | @@ -102,7 +102,7 @@ Furthermore following supporting EEP family is available too: A5-11, types 0x03 A `rockerSwitch` is used to receive messages from a physical EnOcean Rocker Switch. Channel `rockerswitchA` and `rockerswitchA` just react if corresponding rocker switch channel is pressed as single action. These channels do not emit an event if ChannelA and ChannelB are pressed simultaneously. -To handle simultaneously pressed channels you have to use the `rockerSwitchAction` channel and configure it accordingly. +To handle simultaneously pressed channels you have to use the `rockerSwitchAction` channel. A `classicDevice` is used for older EnOcean devices which react only on rocker switch messages (like Opus GN-A-R12V-SR-4). As these devices do not send their current status, you have to add additional listener channels for each physical Rocker Switch to your thing. In this way you can still sync your item status with the physical status of your device whenever it gets modified by a physical rocker switch. @@ -369,6 +369,14 @@ then end ``` +If you also want to react to simultaneously pressed channels you have to use the `rockerSwitchAction` channel. +This channel emits events in the following form "DirectionChannelA|DirectionChannelB" (for example "Dir1|Dir2"). +If a channel is not pressed a "-" is emitted. +To bind this channel to an item you have to use the `rockerswitchaction-toggle-switch` or the `rockerswitchaction-toggle-player` profile. +To define for which button press combination the linked item should toggle you have to set the configuration parameters `channelAFilter` and `channelBFilter` accordingly. +The options for these parameters are "*" (any direction), "Dir1", "Dir2", "-" (corresponding channel not pressed at all). +An example can be found below. + ## Example ```xtend @@ -396,6 +404,7 @@ Bridge enocean:bridge:gtwy "EnOcean Gateway" [ path="/dev/ttyAMA0" ] { ```xtend Player Kitchen_Sonos "Sonos" (Kitchen) {channel="sonos:PLAY1:ID:control", channel="enocean:rockerSwitch:gtwy:rs01:rockerswitchA" [profile="system:rawrocker-to-play-pause"]} +Switch Light_Switch { channel="enocean:rockerSwitch:gtwy:rs01:rockerSwitchAction" [profile="enocean:rockerswitchaction-toggle-switch", channelAFilter="DIR1", channelBFilter="DIR1"]} Dimmer Kitchen_Hue "Hue" {channel="enocean:rockerSwitch:gtwy:rs01:rockerswitchB" [profile="system:rawrocker-to-dimmer"], channel="hue:0220:0017884f6626:9:brightness"} Rollershutter Kitchen_Rollershutter "Roller shutter" (Kitchen) {channel="enocean:rollershutter:gtwy:r01:rollershutter", autoupdate="false"} Switch Garage_Light "Switch" { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanProfileRockerSwitchActionConfig.java similarity index 70% rename from bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java rename to bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanProfileRockerSwitchActionConfig.java index d5bad6edf4520..92747ddff870f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanChannelRockerSwitchActionConfig.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/config/EnOceanProfileRockerSwitchActionConfig.java @@ -13,16 +13,17 @@ package org.openhab.binding.enocean.internal.config; /** + * This {@link EnOceanProfileRockerSwitchActionConfig} config class is used for rockerSwitchAction profiles to define in + * which case it should react. * * @author Daniel Weber - Initial contribution - * This config class is used for channel rockerSwitchAction to define in which case it triggers. */ -public class EnOceanChannelRockerSwitchActionConfig { +public class EnOceanProfileRockerSwitchActionConfig { public String channelAFilter; public String channelBFilter; - public EnOceanChannelRockerSwitchActionConfig() { + public EnOceanProfileRockerSwitchActionConfig() { channelAFilter = "*"; channelBFilter = "*"; } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java index f53c5b352f73a..cab0535e0280f 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02.java @@ -14,7 +14,6 @@ import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*; -import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchActionConfig; import org.openhab.binding.enocean.internal.config.EnOceanChannelRockerSwitchConfigBase.SwitchMode; import org.openhab.binding.enocean.internal.eep.Base._RPSMessage; import org.openhab.binding.enocean.internal.messages.ERP1Message; @@ -40,7 +39,6 @@ public abstract class F6_02 extends _RPSMessage { final String DIR1 = "DIR1"; final String DIR2 = "DIR2"; - final String ANYDIR = "*"; final String NODIR = "-"; int secondByte = -1; @@ -69,23 +67,20 @@ private String getChannelBDir() { return DIR1; } else if ((bytes[0] >>> 5) == BI && (bytes[0] & PRESSED) != 0) { return DIR2; + } else if (((bytes[0] & 0xf) >>> 1) == B0 && (bytes[0] & PRESSED_SEC) != 0) { + return DIR1; + } else if (((bytes[0] & 0xf) >>> 1) == BI && (bytes[0] & PRESSED_SEC) != 0) { + return DIR2; } else { return NODIR; } } protected String getRockerSwitchAction(Configuration config) { - EnOceanChannelRockerSwitchActionConfig conf = config.as(EnOceanChannelRockerSwitchActionConfig.class); String dirA = getChannelADir(); String dirB = getChannelBDir(); - if (!(conf.channelAFilter.equals(ANYDIR) || conf.channelAFilter.equals(dirA))) { - return null; - } else if (!(conf.channelBFilter.equals(ANYDIR) || conf.channelBFilter.equals(dirB))) { - return null; - } else { - return dirA + "|" + dirB; - } + return dirA + "|" + dirB; } protected String getChannelEvent(byte dir1, byte dir2) { diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java index 5b7fdca8d10c7..b3f41dbb38bc6 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/eep/F6_02/F6_02_02.java @@ -72,7 +72,7 @@ protected String convertToEventImpl(String channelId, String channelTypeId, Stri protected void convertFromCommandImpl(String channelId, String channelTypeId, Command command, Function getCurrentStateFunc, Configuration config) { if (command instanceof StringType) { - StringType s = (StringType) command; + String s = ((StringType) command).toString(); if (s.equals(CommonTriggerEvents.DIR1_RELEASED) || s.equals(CommonTriggerEvents.DIR2_RELEASED)) { setStatus(_RPSMessage.T21Flag); diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java index 3afc467a9660d..e2c2afbde6eef 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/EnOceanProfileFactory.java @@ -94,9 +94,9 @@ public Collection getProfileTypes(@Nullable Locale locale) { public @Nullable Profile createProfile(ProfileTypeUID profileTypeUID, ProfileCallback callback, ProfileContext profileContext) { if (ROCKERSWITCHACTION_TOGGLE_PLAYER.equals(profileTypeUID)) { - return new RockerSwitchActionTogglePlayerProfile(callback); + return new RockerSwitchActionTogglePlayerProfile(callback, profileContext); } else if (ROCKERSWITCHACTION_TOGGLE_SWITCH.equals(profileTypeUID)) { - return new RockerSwitchActionToggleSwitchProfile(callback); + return new RockerSwitchActionToggleSwitchProfile(callback, profileContext); } else { return null; } diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionBaseProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionBaseProfile.java new file mode 100644 index 0000000000000..6a0dff5772a5b --- /dev/null +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionBaseProfile.java @@ -0,0 +1,57 @@ +/** + * 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.profiles; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.enocean.internal.config.EnOceanProfileRockerSwitchActionConfig; +import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileContext; +import org.openhab.core.thing.profiles.TriggerProfile; +import org.openhab.core.types.State; + +/** + * @author Daniel Weber - Initial contribution + */ +@NonNullByDefault +public abstract class RockerSwitchActionBaseProfile implements TriggerProfile { + + protected final ProfileCallback callback; + protected ProfileContext context; + + protected @Nullable State previousState; + + final String ANYDIR = "*"; + + public RockerSwitchActionBaseProfile(ProfileCallback callback, ProfileContext context) { + this.callback = callback; + this.context = context; + } + + protected boolean isEventValid(String event) { + String[] directions = event.split("\\|"); + if (directions.length != 2) { + return false; + } + + EnOceanProfileRockerSwitchActionConfig config = context.getConfiguration() + .as(EnOceanProfileRockerSwitchActionConfig.class); + if (!(config.channelAFilter.equals(ANYDIR) || config.channelAFilter.equals(directions[0]))) { + return false; + } else if (!(config.channelBFilter.equals(ANYDIR) || config.channelBFilter.equals(directions[1]))) { + return false; + } + + return true; + } +} diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java index 04e3fe1093a24..d3213020b1822 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionTogglePlayerProfile.java @@ -15,28 +15,24 @@ import static org.openhab.binding.enocean.internal.profiles.EnOceanProfiles.*; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.types.PlayPauseType; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileContext; import org.openhab.core.thing.profiles.ProfileTypeUID; -import org.openhab.core.thing.profiles.TriggerProfile; import org.openhab.core.types.State; /** + * The {@link RockerSwitchActionTogglePlayerProfile} is used for channel rockerSwitchAction to be able to bind this + * trigger channel directly to a player item + * * @author Daniel Weber - Initial contribution - * This profile is used for channel rockerSwitchAction to be able to bind this trigger channel directly to a - * player item */ @NonNullByDefault -public class RockerSwitchActionTogglePlayerProfile implements TriggerProfile { +public class RockerSwitchActionTogglePlayerProfile extends RockerSwitchActionBaseProfile { - private final ProfileCallback callback; - - private @Nullable State previousState; - - public RockerSwitchActionTogglePlayerProfile(ProfileCallback callback) { - this.callback = callback; + public RockerSwitchActionTogglePlayerProfile(ProfileCallback callback, ProfileContext context) { + super(callback, context); } @Override @@ -52,7 +48,7 @@ public void onStateUpdateFromItem(State state) { @Override public void onTriggerFromHandler(String event) { // Ignore released event - if (!CommonTriggerEvents.RELEASED.equals(event)) { + if (!CommonTriggerEvents.RELEASED.equals(event) && isEventValid(event)) { PlayPauseType newState = PlayPauseType.PLAY.equals(previousState) ? PlayPauseType.PAUSE : PlayPauseType.PLAY; callback.sendCommand(newState); diff --git a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java index 73f71c0857544..2dcf4772c19db 100644 --- a/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java +++ b/bundles/org.openhab.binding.enocean/src/main/java/org/openhab/binding/enocean/internal/profiles/RockerSwitchActionToggleSwitchProfile.java @@ -15,28 +15,24 @@ import static org.openhab.binding.enocean.internal.profiles.EnOceanProfiles.*; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.CommonTriggerEvents; import org.openhab.core.thing.profiles.ProfileCallback; +import org.openhab.core.thing.profiles.ProfileContext; import org.openhab.core.thing.profiles.ProfileTypeUID; -import org.openhab.core.thing.profiles.TriggerProfile; import org.openhab.core.types.State; /** + * The {@link RockerSwitchActionToggleSwitchProfile} is used for channel rockerSwitchAction to be able to bind this + * trigger channel directly to a switch item + * * @author Daniel Weber - Initial contribution - * This profile is used for channel rockerSwitchAction to be able to bind this trigger channel directly to a - * switch item */ @NonNullByDefault -public class RockerSwitchActionToggleSwitchProfile implements TriggerProfile { +public class RockerSwitchActionToggleSwitchProfile extends RockerSwitchActionBaseProfile { - private final ProfileCallback callback; - - private @Nullable State previousState; - - public RockerSwitchActionToggleSwitchProfile(ProfileCallback callback) { - this.callback = callback; + public RockerSwitchActionToggleSwitchProfile(ProfileCallback callback, ProfileContext context) { + super(callback, context); } @Override @@ -52,7 +48,7 @@ public void onStateUpdateFromItem(State state) { @Override public void onTriggerFromHandler(String event) { // Ignore released event - if (!CommonTriggerEvents.RELEASED.equals(event)) { + if (!CommonTriggerEvents.RELEASED.equals(event) && isEventValid(event)) { OnOffType newState = OnOffType.ON.equals(previousState) ? OnOffType.OFF : OnOffType.ON; callback.sendCommand(newState); previousState = newState; diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml index 54c150138ddf1..2d964020a3c3e 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/config/config.xml @@ -61,4 +61,27 @@
+ + + + * + + + + + + + + + + * + + + + + + + + + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml index dda3fc9edb886..c17b070eb5909 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/RockerSwitch.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd"> - + @@ -20,8 +20,8 @@ - - + + diff --git a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml index 2c97c83d9afca..744ec2ad0fe74 100644 --- a/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml +++ b/bundles/org.openhab.binding.enocean/src/main/resources/OH-INF/thing/channels.xml @@ -752,13 +752,6 @@ - - Switch - - Indicates if second action of rocker switch is pressed. - - - trigger @@ -776,28 +769,6 @@ - - - - * - - - - - - - - - - * - - - - - - - - From 15a7ee6000287fdf9b6dcbe7b84f34e7857a2b3a Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Mon, 11 Oct 2021 13:07:59 +0200 Subject: [PATCH 6/6] [enocean] Add second action for two rocker switches (Fixes #9750) * Updated and cleaned README Signed-off-by: Daniel Weber --- bundles/org.openhab.binding.enocean/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bundles/org.openhab.binding.enocean/README.md b/bundles/org.openhab.binding.enocean/README.md index 30fe3d0a2fd2c..c72cda7c99596 100644 --- a/bundles/org.openhab.binding.enocean/README.md +++ b/bundles/org.openhab.binding.enocean/README.md @@ -100,7 +100,7 @@ Hence if your device supports one of the following EEPs the chances are good tha Furthermore following supporting EEP family is available too: A5-11, types 0x03 (rollershutter position status), 0x04 (extended light status) and D0-06 (battery level indication). A `rockerSwitch` is used to receive messages from a physical EnOcean Rocker Switch. -Channel `rockerswitchA` and `rockerswitchA` just react if corresponding rocker switch channel is pressed as single action. +Channel `rockerswitchA` and `rockerswitchB` just react if corresponding rocker switch channel is pressed as single action. These channels do not emit an event if ChannelA and ChannelB are pressed simultaneously. To handle simultaneously pressed channels you have to use the `rockerSwitchAction` channel. A `classicDevice` is used for older EnOcean devices which react only on rocker switch messages (like Opus GN-A-R12V-SR-4). @@ -340,8 +340,6 @@ Some channels can be configured with parameters. | totalusage | validateValue | Filter out increases more than 10.0 kWh and decreases less than 1.0 kWh | true / false | | | tariff | Tariff info or measurement channel to listen to | 0-15 | | contact | inverted | Swap OPEN / CLOSED. Set True for Eltako FPE-2. | true / false. Defaults to false. | -| rockerSwitchAction | channelAFilter | Defines for which channel A events this trigger should fire | *: Any Direction, DIR1, DIR2, -:No Direction. Defaults to * | -| rockerSwitchAction | channelBFilter | Defines for which channel B events this trigger should fire | *: Any Direction, DIR1, DIR2, -:No Direction. Defaults to * | Possible declaration in Thing DSL: