[enocean] Add support for Soda Handles (EEP D2-06-01) (#11230)
* added data validation Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * Revert "added data validation" This reverts commit 945101056b7d0a79b6d53985cfcef8e06bf0a8aa. Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * added calibration channels Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * added calibration channels Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * initial d20601 impl Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * fixed D20601 temp and battery Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * README updated and changed D20601 to mechanical handle Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * spotless Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * use common events Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * fix spotless Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * Revert "added calibration channels" This reverts commit 6287b4be19fc37e8d1c2211109628fff513ecc8e. Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * Revert "added calibration channels" This reverts commit fca8b4b11d1df0345bc02466311cf3f139044562. Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * Revert "Revert "added data validation"" This reverts commit e8ff27fa44461a108f3942f5e9547d72bb280d65. Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * Revert "added data validation" This reverts commit 8d7bd95629426640d9f63d53c05335f3dcbd9b5b. Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * added more comments and fixed channel labels Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * added state enums Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * added missing modifiers Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * fixed typo in comment Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> * upstream changes Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com> Co-authored-by: Thomas Lauterbach <lauterbachthomas@gmail.com>
This commit is contained in:
committed by
GitHub
parent
1e57450e3f
commit
a253250427
@@ -127,6 +127,7 @@ public class EnOceanBindingConstants {
|
||||
public static final String CHANNEL_INDOORAIRANALYSIS = "indoorAirAnalysis";
|
||||
|
||||
public static final String CHANNEL_PUSHBUTTON = "pushButton";
|
||||
public static final String CHANNEL_PUSHBUTTON2 = "pushButton2";
|
||||
public static final String CHANNEL_DOUBLEPRESS = "doublePress";
|
||||
public static final String CHANNEL_LONGPRESS = "longPress";
|
||||
|
||||
@@ -148,6 +149,8 @@ public class EnOceanBindingConstants {
|
||||
public static final String CHANNEL_WINDOWCALIBRATIONSTATE = "windowCalibrationState";
|
||||
public static final String CHANNEL_WINDOWCALIBRATIONSTEP = "windowCalibrationStep";
|
||||
public static final String CHANNEL_WINDOWBREACHEVENT = "windowBreachEvent";
|
||||
public static final String CHANNEL_PROTECTIONPLUSEVENT = "protectionPlusEvent";
|
||||
public static final String CHANNEL_VACATIONMODETOGGLEEVENT = "vacationModeToggleEvent";
|
||||
public static final String CHANNEL_CONTACT = "contact";
|
||||
public static final String CHANNEL_TEACHINCMD = "teachInCMD";
|
||||
public static final String CHANNEL_INSTANTPOWER = "instantpower";
|
||||
@@ -325,6 +328,12 @@ public class EnOceanBindingConstants {
|
||||
Map.entry(CHANNEL_WINDOWBREACHEVENT,
|
||||
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWBREACHEVENT), null, null,
|
||||
false, true)),
|
||||
Map.entry(CHANNEL_PROTECTIONPLUSEVENT,
|
||||
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_PROTECTIONPLUSEVENT), null,
|
||||
null, false, true)),
|
||||
Map.entry(CHANNEL_VACATIONMODETOGGLEEVENT,
|
||||
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_VACATIONMODETOGGLEEVENT), null,
|
||||
null, false, true)),
|
||||
Map.entry(
|
||||
CHANNEL_BATTERY_VOLTAGE,
|
||||
new EnOceanChannelDescription(
|
||||
@@ -347,6 +356,9 @@ public class EnOceanBindingConstants {
|
||||
Map.entry(CHANNEL_PUSHBUTTON,
|
||||
new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
|
||||
"Push button", false, true)),
|
||||
Map.entry(CHANNEL_PUSHBUTTON2,
|
||||
new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
|
||||
"Push button 2", false, true)),
|
||||
Map.entry(CHANNEL_DOUBLEPRESS,
|
||||
new EnOceanChannelDescription(DefaultSystemChannelTypeProvider.SYSTEM_RAWBUTTON.getUID(), null,
|
||||
"Double press", false, true)),
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.enocean.internal.eep.D2_06;
|
||||
|
||||
import static org.openhab.binding.enocean.internal.EnOceanBindingConstants.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.openhab.binding.enocean.internal.eep.Base._VLDMessage;
|
||||
import org.openhab.binding.enocean.internal.messages.ERP1Message;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.Units;
|
||||
import org.openhab.core.thing.CommonTriggerEvents;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* Implementation of the D2_06_01 EEP as used by window handles manufactured by Soda GmbH. All channels except the
|
||||
* battery channels may be not supported by the physical device (depending on the actual model). If a channel is not
|
||||
* supported by a device it will transmit a 'not supported' message which is ignored by this implementation.
|
||||
* Consequently channels that are not supported by the physical device will never send updates to linked items.
|
||||
*
|
||||
* @author Thomas Lauterbach - Initial contribution
|
||||
*/
|
||||
public class D2_06_01 extends _VLDMessage {
|
||||
|
||||
private enum MessageType {
|
||||
|
||||
SENSORVALUES(0x00),
|
||||
CONFIGURATIONREPORT(0x10),
|
||||
LOGDATA01(0x20),
|
||||
LOGDATA02(0x21),
|
||||
LOGDATA03(0x22),
|
||||
LOGDATA04(0x23),
|
||||
CONTROLANDSETTINGS(0x80);
|
||||
|
||||
private int intValue;
|
||||
|
||||
private MessageType(int intValue) {
|
||||
this.intValue = intValue;
|
||||
}
|
||||
|
||||
private int getIntValue() {
|
||||
return this.intValue;
|
||||
}
|
||||
}
|
||||
|
||||
private enum SashState {
|
||||
|
||||
// WINDOWSTATEUNDEFINED(0x00, "UNDEFINED"),
|
||||
NOTTILTED(0x01, "NOT TILTED"),
|
||||
TILTED(0x02, "TILTED");
|
||||
|
||||
private int intValue;
|
||||
private String textValue;
|
||||
|
||||
private SashState(int intValue, String textValue) {
|
||||
this.intValue = intValue;
|
||||
this.textValue = textValue;
|
||||
}
|
||||
|
||||
private String getTextValue() {
|
||||
return this.textValue;
|
||||
}
|
||||
|
||||
private static Optional<SashState> valueOf(int intValue) {
|
||||
return Arrays.stream(values()).filter(sashState -> sashState.intValue == intValue).findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
private enum HandleState {
|
||||
|
||||
// HANDLEPOSITIONUNDEFINED(0x00, "UNDEFINED"),
|
||||
HANDLEUP(0x01, "UP"),
|
||||
HANDLEDOWN(0x02, "DOWN"),
|
||||
HANDLELEFT(0x03, "LEFT"),
|
||||
HANDLERIGHT(0x04, "RIGHT");
|
||||
|
||||
private int intValue;
|
||||
private String textValue;
|
||||
|
||||
private HandleState(int intValue, String textValue) {
|
||||
this.intValue = intValue;
|
||||
this.textValue = textValue;
|
||||
}
|
||||
|
||||
private String getTextValue() {
|
||||
return this.textValue;
|
||||
}
|
||||
|
||||
private static Optional<HandleState> valueOf(int intValue) {
|
||||
return Arrays.stream(values()).filter(handleState -> handleState.intValue == intValue).findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
private enum MotionState {
|
||||
|
||||
MOTIONNOTTRIGGERED(0x00, "OFF"),
|
||||
MOTIONTRIGGERED(0x01, "ON");
|
||||
|
||||
private int intValue;
|
||||
private String textValue;
|
||||
|
||||
private MotionState(int intValue, String textValue) {
|
||||
this.intValue = intValue;
|
||||
this.textValue = textValue;
|
||||
}
|
||||
|
||||
private String getTextValue() {
|
||||
return this.textValue;
|
||||
}
|
||||
|
||||
private static Optional<MotionState> valueOf(int intValue) {
|
||||
return Arrays.stream(values()).filter(motionState -> motionState.intValue == intValue).findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
public D2_06_01() {
|
||||
super();
|
||||
}
|
||||
|
||||
public D2_06_01(ERP1Message packet) {
|
||||
super(packet);
|
||||
}
|
||||
|
||||
protected State getWindowSashState() {
|
||||
Optional<SashState> sashState = SashState.valueOf(bytes[2] & 0x0F);
|
||||
if (sashState.isPresent()) {
|
||||
return new StringType(sashState.get().getTextValue());
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getWindowHandleState() {
|
||||
Optional<HandleState> handleState = HandleState.valueOf(bytes[2] >>> 4);
|
||||
if (handleState.isPresent()) {
|
||||
return new StringType(handleState.get().getTextValue());
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getMotionState() {
|
||||
Optional<MotionState> motionState = MotionState.valueOf(bytes[4] >>> 4);
|
||||
if (motionState.isPresent()) {
|
||||
return OnOffType.from(motionState.get().getTextValue());
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getTemperature() {
|
||||
double unscaledTemp = (double) (bytes[5] & 0xFF);
|
||||
if (unscaledTemp <= 250) {
|
||||
double scaledTemp = unscaledTemp * 0.32 - 20;
|
||||
return new QuantityType<>(scaledTemp, SIUnits.CELSIUS);
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getHumidity() {
|
||||
int unscaledHumidity = bytes[6] & 0xFF;
|
||||
if (unscaledHumidity <= 200) {
|
||||
double scaledHumidity = unscaledHumidity * 0.5;
|
||||
return new DecimalType(scaledHumidity);
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getIllumination() {
|
||||
int illumination = ((bytes[7] & 0xFF) << 8) | (bytes[8] & 0xFF);
|
||||
if (illumination <= 60000) {
|
||||
return new QuantityType<>(illumination, Units.LUX);
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected State getBatteryLevel() {
|
||||
int unscaledBatteryLevel = ((bytes[9] & 0xFF) >> 3);
|
||||
if (unscaledBatteryLevel <= 20) {
|
||||
return new DecimalType(unscaledBatteryLevel * 5);
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertToEventImpl(String channelId, String channelTypeId, String lastEvent,
|
||||
Configuration config) {
|
||||
|
||||
// Sensor values
|
||||
if (bytes[0] == MessageType.SENSORVALUES.getIntValue()) {
|
||||
switch (channelId) {
|
||||
case CHANNEL_WINDOWBREACHEVENT:
|
||||
if ((bytes[1] >>> 4) == 0x01) {
|
||||
return "ALARM";
|
||||
}
|
||||
break;
|
||||
case CHANNEL_PROTECTIONPLUSEVENT:
|
||||
if ((bytes[1] & 0x0F) == 0x01) {
|
||||
return "ALARM";
|
||||
}
|
||||
break;
|
||||
case CHANNEL_PUSHBUTTON:
|
||||
int buttonEvent = bytes[3] >>> 4;
|
||||
switch (buttonEvent) {
|
||||
case 0x01:
|
||||
return CommonTriggerEvents.PRESSED;
|
||||
case 0x02:
|
||||
return CommonTriggerEvents.RELEASED;
|
||||
}
|
||||
break;
|
||||
case CHANNEL_PUSHBUTTON2:
|
||||
int buttonEvent2 = bytes[3] & 0x0F;
|
||||
switch (buttonEvent2) {
|
||||
case 0x01:
|
||||
return CommonTriggerEvents.PRESSED;
|
||||
case 0x02:
|
||||
return CommonTriggerEvents.RELEASED;
|
||||
}
|
||||
break;
|
||||
case CHANNEL_VACATIONMODETOGGLEEVENT:
|
||||
int vacationModeToggleEvent = bytes[4] & 0x0F;
|
||||
switch (vacationModeToggleEvent) {
|
||||
case 0x01:
|
||||
return "ACTIVATED";
|
||||
case 0x02:
|
||||
return "DEACTIVATED";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public State convertToStateImpl(String channelId, String channelTypeId, Function<String, State> getCurrentStateFunc,
|
||||
Configuration config) {
|
||||
|
||||
// Sensor values
|
||||
if (bytes[0] == MessageType.SENSORVALUES.getIntValue()) {
|
||||
switch (channelId) {
|
||||
case CHANNEL_WINDOWSASHSTATE:
|
||||
return getWindowSashState();
|
||||
case CHANNEL_WINDOWHANDLESTATE:
|
||||
return getWindowHandleState();
|
||||
case CHANNEL_MOTIONDETECTION:
|
||||
return getMotionState();
|
||||
case CHANNEL_INDOORAIRTEMPERATURE:
|
||||
return getTemperature();
|
||||
case CHANNEL_HUMIDITY:
|
||||
return getHumidity();
|
||||
case CHANNEL_ILLUMINATION:
|
||||
return getIllumination();
|
||||
case CHANNEL_BATTERY_LEVEL:
|
||||
return getBatteryLevel();
|
||||
}
|
||||
}
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
}
|
||||
@@ -137,6 +137,7 @@ import org.openhab.binding.enocean.internal.eep.D2_01.D2_01_12;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_01.D2_01_12_NodON;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_03.D2_03_0A;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_05.D2_05_00;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_06.D2_06_01;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_06.D2_06_50;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_14.D2_14_30;
|
||||
import org.openhab.binding.enocean.internal.eep.D2_50.D2_50;
|
||||
@@ -196,6 +197,10 @@ public enum EEPType {
|
||||
CHANNEL_WINDOWHANDLESTATE, CHANNEL_CONTACT, CHANNEL_BATTERY_VOLTAGE),
|
||||
MechanicalHandle03(RORG._4BS, 0x14, 0x0A, false, A5_14_0A.class, THING_TYPE_MECHANICALHANDLE,
|
||||
CHANNEL_WINDOWHANDLESTATE, CHANNEL_CONTACT, CHANNEL_VIBRATION, CHANNEL_BATTERY_VOLTAGE),
|
||||
MechanicalHandle04(RORG.VLD, 0x06, 0x01, false, "Soda", 0x0043, D2_06_01.class, THING_TYPE_MECHANICALHANDLE,
|
||||
CHANNEL_WINDOWHANDLESTATE, CHANNEL_WINDOWSASHSTATE, CHANNEL_MOTIONDETECTION, CHANNEL_INDOORAIRTEMPERATURE,
|
||||
CHANNEL_HUMIDITY, CHANNEL_ILLUMINATION, CHANNEL_BATTERY_LEVEL, CHANNEL_WINDOWBREACHEVENT,
|
||||
CHANNEL_PROTECTIONPLUSEVENT, CHANNEL_PUSHBUTTON, CHANNEL_PUSHBUTTON2, CHANNEL_VACATIONMODETOGGLEEVENT),
|
||||
|
||||
ContactAndSwitch01(RORG._1BS, 0x00, 0x01, false, D5_00_01.class, THING_TYPE_CONTACT, CHANNEL_CONTACT),
|
||||
ContactAndSwitch02(RORG._4BS, 0x14, 0x01, false, A5_14_01.class, THING_TYPE_CONTACT, CHANNEL_BATTERY_VOLTAGE,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<option value="F6_10_01">F6-10-01</option>
|
||||
<option value="A5_14_09">A5-14-09</option>
|
||||
<option value="A5_14_0A">A5-14-0A</option>
|
||||
<option value="D2_06_01_Soda">D2_06_01 (Soda handle)</option>
|
||||
</options>
|
||||
<limitToOptions>true</limitToOptions>
|
||||
</parameter>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
</parameter>
|
||||
<parameter name="receivingEEPId" type="text" required="true">
|
||||
<label>EEP</label>
|
||||
<description>EEP which is used by handle</description>
|
||||
<description>EEP which is used by device</description>
|
||||
<options>
|
||||
<option value="D2_06_50_Siegenia">D2_06_50 (Siegenia Senso Secure)</option>
|
||||
</options>
|
||||
|
||||
@@ -154,6 +154,10 @@
|
||||
<option value="OPEN">Open</option>
|
||||
<option value="TILTED">Tilted</option>
|
||||
<option value="CLOSED">Closed</option>
|
||||
<option value="UP">Up</option>
|
||||
<option value="DOWN">Down</option>
|
||||
<option value="LEFT">Left</option>
|
||||
<option value="RIGHT">Right</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
@@ -166,6 +170,7 @@
|
||||
<options>
|
||||
<option value="OPEN">Open</option>
|
||||
<option value="TILTED">Tilted</option>
|
||||
<option value="NOT TILTED">Not Tilted</option>
|
||||
<option value="CLOSED">Closed</option>
|
||||
</options>
|
||||
</state>
|
||||
@@ -211,7 +216,30 @@
|
||||
<description>Is triggered 10 times in 5 seconds when the sensor detects a break-in attempt.</description>
|
||||
<event>
|
||||
<options>
|
||||
<option value="ALARM">alarm</option>
|
||||
<option value="ALARM">Alarm</option>
|
||||
</options>
|
||||
</event>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="protectionPlusEvent">
|
||||
<kind>trigger</kind>
|
||||
<label>Protection Plus Event</label>
|
||||
<description>Triggered when a Protection Plus capable device detects a break-in attempt.</description>
|
||||
<event>
|
||||
<options>
|
||||
<option value="ALARM">Alarm</option>
|
||||
</options>
|
||||
</event>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="vacationModeToggleEvent">
|
||||
<kind>trigger</kind>
|
||||
<label>Vacation Mode Toggle Event</label>
|
||||
<description>Triggered when the vacation mode has been toggled on the device.</description>
|
||||
<event>
|
||||
<options>
|
||||
<option value="ACTIVATED">Activated</option>
|
||||
<option value="DEACTIVATED">Deactivated</option>
|
||||
</options>
|
||||
</event>
|
||||
</channel-type>
|
||||
|
||||
Reference in New Issue
Block a user