Skip to content

Commit

Permalink
[enocean] Adds support for the D2_06_50 EEP type (openhab#10949)
Browse files Browse the repository at this point in the history
* Initial D2_06_20 EEP Implementation.

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added data validation

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added channels for calibration

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added manufacturer ID for discovery

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* Revert "added data validation"

This reverts commit 9451010.

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* fixing discovery by setting manufacturerId

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* fix spotless

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added calibration channels

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* removed validation override

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added manufacturer suffix

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* channel description updated

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* added calibration channels

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* mentioning calibration channels in documentation

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

* shortened thing label

Signed-off-by: Thomas Lauterbach <lauterbachthomas@gmail.com>

Co-authored-by: Thomas Lauterbach <lauterbachthomas@gmail.com>
  • Loading branch information
2 people authored and frederictobiasc committed Oct 26, 2021
1 parent 4eaf15f commit 71d9526
Show file tree
Hide file tree
Showing 7 changed files with 294 additions and 4 deletions.
9 changes: 9 additions & 0 deletions bundles/org.openhab.binding.enocean/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ This binding is developed on and tested with the following devices
* Thermokon SR04 room control
* Hoppe SecuSignal window handles
* Rocker switches (NodOn, Eltako FT55 etc)
* Siegenia Senso Secure window sensors

However, because of the standardized EnOcean protocol it is more important which EEP this binding supports.
Hence if your device supports one of the following EEPs the chances are good that your device is also supported by this binding.
Expand All @@ -89,6 +90,7 @@ Hence if your device supports one of the following EEPs the chances are good tha
| centralCommand | A5-38 | 0x08 | dimmer, generalSwitch | Eltako FUD14, FSR14 | Teach-in |
| rollershutter | A5-3F/D2-05/A5-38 | 0x7F/00/08 | rollershutter | Eltako FSB14, NodOn SIN-2-RS-01| Teach-in/Discovery |
| measurementSwitch | D2-01 | 0x00-0F,11,12 | generalSwitch(/A/B), instantpower,<br/>totalusage, repeaterMode | NodOn In Wall Switch | Discovery |
| windowSashHandleSensor | D2-06 | 0x50 | windowHandleState, windowSashState, batteryLevel, batteryLow, windowBreachEvent, windowCalibrationState, windowCalibrationStep | Siegenia Senso Secure | Discovery |
| multiFunctionSmokeDetector | D2-14/F6-05 | 0x30/02 | smokeDetection, batteryLow | Insafe+, Afriso ASD | Discovery |
| heatRecoveryVentilation | D2-50 | 0x00,01,10,11 | a lot of different state channels | Dimplex DL WE2 | Discovery |
| classicDevice | F6-02 | 0x01-02 | virtualRockerswitchA, virtualRockerswitchB | - | Teach-in |
Expand Down Expand Up @@ -225,6 +227,8 @@ If you change the SenderId of your thing, you have to pair again the thing with
| | broadcastMessages | | true, false |
| | pollingInterval | | Integer |
| | suppressRepeating | | true, false |
| windowSashHandleSensor | receivingEEPId | | D2_06_50 |
| | enoceanId | | |
| multiFunctionSmokeDetector | receivingEEPId | | F6_05_02, D2_14_30 |
| | enoceanId | | |
| heatRecoveryVentilation | senderIdOffset | | 1-127 |
Expand Down Expand Up @@ -255,6 +259,9 @@ The channels of a thing are determined automatically based on the chosen EEP.
| 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 |
| windowHandleState | String | Textual representation of handle position (OPEN, CLOSED, TILTED) |
| windowSashState | String | Textual representation of sash position (OPEN, CLOSED, TILTED) |
| windowCalibrationState | String | Textual representation of the calibration state (OK, ERROR, INVALID) |
| windowCalibrationStep | String | Textual representation of the next step that must be performed for calibrating the device (e.g. NONE, SASH CLOSED HANDLE CLOSED, SASH CLOSED HANDLE OPEN, SASH OPEN HANDLE TILTED, and so on) |
| contact | Contact | State OPEN/CLOSED (tilted handle => OPEN) |
| temperature | Number:Temperature | Temperature in degree Celsius |
| humidity | Number | Relative humidity level in percentages |
Expand Down Expand Up @@ -317,6 +324,8 @@ The channels of a thing are determined automatically based on the chosen EEP.
| repeatCount | Number | Number of repeaters involved in the transmission of the telegram |
| lastReceived | DateTime | Date and time the last telegram was received |
| statusRequestEvent | Trigger | Emits event 'requestAnswer' |
| windowBreachEvent | Trigger | Emits event 'ALARM' |


Items linked to bi-directional actuators (actuator sends status messages back) should always disable the `autoupdate`.
This is especially true for Eltako rollershutter, as their position is calculated out of the current position and the moving time.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,17 @@ public class EnOceanBindingConstants {

public static final ThingTypeUID THING_TYPE_HEATRECOVERYVENTILATION = new ThingTypeUID(BINDING_ID,
"heatRecoveryVentilation");
public static final ThingTypeUID THING_TYPE_WINDOWSASHHANDLESENSOR = new ThingTypeUID(BINDING_ID,
"windowSashHandleSensor");

public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(THING_TYPE_PUSHBUTTON,
THING_TYPE_ROCKERSWITCH, THING_TYPE_CLASSICDEVICE, THING_TYPE_CENTRALCOMMAND, THING_TYPE_ROOMOPERATINGPANEL,
THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT, THING_TYPE_MEASUREMENTSWITCH, THING_TYPE_TEMPERATURESENSOR,
THING_TYPE_TEMPERATUREHUMIDITYSENSOR, THING_TYPE_GENERICTHING, THING_TYPE_ROLLERSHUTTER,
THING_TYPE_OCCUPANCYSENSOR, THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR,
THING_TYPE_ENVIRONMENTALSENSOR, THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_THERMOSTAT,
THING_TYPE_MULTFUNCTIONSMOKEDETECTOR, THING_TYPE_HEATRECOVERYVENTILATION);
THING_TYPE_MULTFUNCTIONSMOKEDETECTOR, THING_TYPE_HEATRECOVERYVENTILATION,
THING_TYPE_WINDOWSASHHANDLESENSOR);

// List of all Channel Type Ids, these type ids are also used as channel ids during dynamic creation of channels
// this makes it a lot easier as we do not have to manage a type id and an id, drawback long channel names
Expand Down Expand Up @@ -138,6 +141,10 @@ public class EnOceanBindingConstants {
public static final String CHANNEL_ROCKERSWITCHLISTENER_START = "rockerswitchListener";

public static final String CHANNEL_WINDOWHANDLESTATE = "windowHandleState";
public static final String CHANNEL_WINDOWSASHSTATE = "windowSashState";
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_CONTACT = "contact";
public static final String CHANNEL_TEACHINCMD = "teachInCMD";
public static final String CHANNEL_INSTANTPOWER = "instantpower";
Expand Down Expand Up @@ -293,8 +300,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,
Expand All @@ -303,6 +309,19 @@ public class EnOceanBindingConstants {
Map.entry(CHANNEL_WINDOWHANDLESTATE,
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWHANDLESTATE),
CoreItemFactory.STRING)),
Map.entry(CHANNEL_WINDOWSASHSTATE,
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWSASHSTATE),
CoreItemFactory.STRING)),
Map.entry(CHANNEL_WINDOWCALIBRATIONSTATE,
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWCALIBRATIONSTATE),
CoreItemFactory.STRING)),
Map.entry(CHANNEL_WINDOWCALIBRATIONSTEP,
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWCALIBRATIONSTEP),
CoreItemFactory.STRING)),

Map.entry(CHANNEL_WINDOWBREACHEVENT,
new EnOceanChannelDescription(new ChannelTypeUID(BINDING_ID, CHANNEL_WINDOWBREACHEVENT), null, null,
false, true)),
Map.entry(
CHANNEL_BATTERY_VOLTAGE,
new EnOceanChannelDescription(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* 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.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.StringType;
import org.openhab.core.types.State;
import org.openhab.core.types.UnDefType;

/**
*
* @author Thomas Lauterbach - Initial contribution
*/
public class D2_06_50 extends _VLDMessage {

public D2_06_50() {
super();
}

public D2_06_50(ERP1Message packet) {
super(packet);
}

protected State getWindowSashState() {
int sashState = bytes[1] & 0x7f;
if (sashState == 0x00) {
return UnDefType.UNDEF;
}
if (sashState < 0x04) {
return new StringType("CLOSED");
} else if (sashState < 0x07) {
return new StringType("OPEN");
} else if (sashState < 0x0A) {
return new StringType("TILTED");
}

return UnDefType.UNDEF;
}

protected State getWindowHandleState() {
int handleState = bytes[1] & 0x7f;
if (handleState == 0x01 || handleState == 0x04 || handleState == 0x07) {
return new StringType("CLOSED");
} else if (handleState == 0x02 || handleState == 0x05 || handleState == 0x08) {
return new StringType("OPEN");
} else if (handleState == 0x03 || handleState == 0x06 || handleState == 0x09) {
return new StringType("TILTED");
}

return UnDefType.UNDEF;
}

protected State getCalibrationState() {
int calibrationState = bytes[1] >>> 6;
if (calibrationState == 0x00) {
return new StringType("OK");
} else if (calibrationState == 0x01) {
return new StringType("ERROR");
} else if (calibrationState == 0x02) {
return new StringType("INVALID");
}

return UnDefType.UNDEF;
}

protected State getCalibrationStep() {
int calibrationStep = bytes[1] & 0x3F;
switch (calibrationStep) {
case 0x00:
return new StringType("NONE");
case 0x01:
return new StringType("SASH CLOSED HANDLE CLOSED");
case 0x02:
return new StringType("SASH CLOSED HANDLE OPEN");
case 0x03:
return new StringType("SASH CLOSED HANDLE TILTED");
case 0x04:
return new StringType("SASH OPEN HANDLE CLOSED");
case 0x05:
return new StringType("SASH OPEN HANDLE OPEN");
case 0x06:
return new StringType("SASH OPEN HANDLE TILTED");
case 0x07:
return new StringType("SASH TILTED HANDLE CLOSED");
case 0x08:
return new StringType("SASH TILTED HANDLE OPEN");
case 0x09:
return new StringType("SASH TILTED HANDLE TILTED");
case 0x0A:
return new StringType("FRAME MAGNET VALIDATION");
}

return UnDefType.UNDEF;
}

@Override
protected String convertToEventImpl(String channelId, String channelTypeId, String lastEvent,
Configuration config) {

// Alarm
if (bytes[0] == 0x02) {
switch (channelId) {
case CHANNEL_WINDOWBREACHEVENT:
if (bytes[1] == 0x01) {
return "ALARM";
}
}
}
return null;
}

@Override
public State convertToStateImpl(String channelId, String channelTypeId, Function<String, State> getCurrentStateFunc,
Configuration config) {

// Window status
if (bytes[0] == 0x01) {
switch (channelId) {
case CHANNEL_WINDOWSASHSTATE:
return getWindowSashState();
case CHANNEL_WINDOWHANDLESTATE:
return getWindowHandleState();
case CHANNEL_BATTERY_LEVEL:
return new DecimalType(bytes[6] & 0x7f);
case CHANNEL_BATTERYLOW:
return getBit(bytes[6], 7) ? OnOffType.ON : OnOffType.OFF;
}
}

// Calibration
if (bytes[0] == 0x11) {
switch (channelId) {
case CHANNEL_WINDOWCALIBRATIONSTATE:
return getCalibrationState();
case CHANNEL_WINDOWCALIBRATIONSTEP:
return getCalibrationStep();
}
}

return UnDefType.UNDEF;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
import org.openhab.binding.enocean.internal.eep.D2_01.D2_01_12_NodON;
import org.openhab.binding.enocean.internal.eep.D2_03.D2_03_0A;
import org.openhab.binding.enocean.internal.eep.D2_05.D2_05_00;
import org.openhab.binding.enocean.internal.eep.D2_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;
import org.openhab.binding.enocean.internal.eep.D5_00.D5_00_01;
Expand Down Expand Up @@ -464,6 +465,11 @@ public enum EEPType {

Rollershutter_D2(RORG.VLD, 0x05, 0x00, true, D2_05_00.class, THING_TYPE_ROLLERSHUTTER, CHANNEL_ROLLERSHUTTER),

WindowSashHandleSensor_50(RORG.VLD, 0x06, 0x50, false, "Siegenia", 0x005D, D2_06_50.class,
THING_TYPE_WINDOWSASHHANDLESENSOR, CHANNEL_WINDOWHANDLESTATE, CHANNEL_WINDOWSASHSTATE,
CHANNEL_BATTERY_LEVEL, CHANNEL_BATTERYLOW, CHANNEL_WINDOWBREACHEVENT, CHANNEL_WINDOWCALIBRATIONSTATE,
CHANNEL_WINDOWCALIBRATIONSTEP),

MultiFunctionSensor_30(RORG.VLD, 0x14, 0x30, false, D2_14_30.class, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR,
CHANNEL_SMOKEDETECTION, CHANNEL_SENSORFAULT, CHANNEL_TIMESINCELASTMAINTENANCE, CHANNEL_BATTERY_LEVEL,
CHANNEL_REMAININGPLT, CHANNEL_TEMPERATURE, CHANNEL_HUMIDITY, CHANNEL_HYGROCOMFORTINDEX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ public class EnOceanBaseSensorHandler extends EnOceanBaseThingHandler implements
THING_TYPE_MECHANICALHANDLE, THING_TYPE_CONTACT, THING_TYPE_TEMPERATURESENSOR,
THING_TYPE_TEMPERATUREHUMIDITYSENSOR, THING_TYPE_ROCKERSWITCH, THING_TYPE_OCCUPANCYSENSOR,
THING_TYPE_LIGHTTEMPERATUREOCCUPANCYSENSOR, THING_TYPE_LIGHTSENSOR, THING_TYPE_PUSHBUTTON,
THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_ENVIRONMENTALSENSOR, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR);
THING_TYPE_AUTOMATEDMETERSENSOR, THING_TYPE_ENVIRONMENTALSENSOR, THING_TYPE_MULTFUNCTIONSMOKEDETECTOR,
THING_TYPE_WINDOWSASHHANDLESENSOR);

protected final Hashtable<RORG, EEPType> receivingEEPTypes = new Hashtable<>();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="enocean"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">

<!-- WindowSashHandleSensor -->
<thing-type id="windowSashHandleSensor">
<supported-bridge-type-refs>
<bridge-type-ref id="bridge"/>
</supported-bridge-type-refs>

<label>Sash Handle Sensor</label>
<description>Combined sensor for window/door sash state and handle state</description>

<config-description>
<parameter name="enoceanId" type="text" required="true">
<label>EnOceanId</label>
<description>EnOceanId of device this thing belongs to</description>
</parameter>
<parameter name="receivingEEPId" type="text" required="true">
<label>EEP</label>
<description>EEP which is used by handle</description>
<options>
<option value="D2_06_50_Siegenia">D2_06_50 (Siegenia Senso Secure)</option>
</options>
<limitToOptions>true</limitToOptions>
</parameter>
<parameter name="receivingSIGEEP" type="boolean">
<label>Receive Battery Status Signal Messages</label>
<default>false</default>
</parameter>
</config-description>

</thing-type>

</thing:thing-descriptions>
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,64 @@
</state>
</channel-type>

<channel-type id="windowSashState">
<item-type>String</item-type>
<label>Window Sash State</label>
<description>Describes the window sash state</description>
<state readOnly="true">
<options>
<option value="OPEN">Open</option>
<option value="TILTED">Tilted</option>
<option value="CLOSED">Closed</option>
</options>
</state>
</channel-type>

<channel-type id="windowCalibrationState">
<item-type>String</item-type>
<label>Window Calibration State</label>
<description>Describes the window calibration state</description>
<state readOnly="true">
<options>
<option value="OK">Ok</option>
<option value="ERROR">Error</option>
<option value="INVALID">Invalid</option>
</options>
</state>
</channel-type>

<channel-type id="windowCalibrationStep">
<item-type>String</item-type>
<label>Window Calibration Step</label>
<description>Calibration step that should be performed next</description>
<state readOnly="true">
<options>
<option value="NONE">None</option>
<option value="SASH CLOSED HANDLE CLOSED">Sash closed handle closed</option>
<option value="SASH CLOSED HANDLE OPEN">Sash closed handle open</option>
<option value="SASH CLOSED HANDLE TILTED">Sash closed handle tilted</option>
<option value="SASH OPEN HANDLE CLOSED">Sash open handle closed</option>
<option value="SASH OPEN HANDLE OPEN">Sash open handle open</option>
<option value="SASH OPEN HANDLE TILTED">Sash open handle tilted</option>
<option value="SASH TILTED HANDLE CLOSED">Sash tilted handle closed</option>
<option value="SASH TILTED HANDLE OPEN">Sash tilted handle open</option>
<option value="SASH TILTED HANDLE TILTED">Sash tilted handle tilted</option>
<option value="FRAME MAGNET VALIDATION">Frame magnet validation</option>
</options>
</state>
</channel-type>

<channel-type id="windowBreachEvent">
<kind>trigger</kind>
<label>Window Breach Event</label>
<description>Is triggered 10 times in 5 seconds when the sensor detects a break-in attempt.</description>
<event>
<options>
<option value="ALARM">alarm</option>
</options>
</event>
</channel-type>

<channel-type id="instantpower">
<item-type>Number:Power</item-type>
<label>Instant Power</label>
Expand Down

0 comments on commit 71d9526

Please sign in to comment.