[bluetooth.enoceanble] Initial contribution EnOcean BLE Binding (#9223)

* [bluetooth.enoceanble] Initial contribution EnOcean BLE Binding

Signed-off-by: Patrick Fink <mail@pfink.de>

* Put @Nullable annotation inline

Signed-off-by: Patrick Fink <mail@pfink.de>

Co-authored-by: Connor Petty <mistercpp2000@gmail.com>

* [bluetooth.enoceanble] Add binding to CODEOWNERS

Signed-off-by: Patrick Fink <mail@pfink.de>

* [bluetooth.enoceanble] Remove obsolete transport serial feature

Signed-off-by: Patrick Fink <mail@pfink.de>

* [bluetooth.enoceanble] Add binding to footer.xml

Signed-off-by: Patrick Fink <mail@pfink.de>

* [bluetooth.enoceanble] Replace ruuvitag leftovers

Signed-off-by: Patrick Fink <mail@pfink.de>

* [bluetooth.enoceanble] Remove tinyB reference

Signed-off-by: Patrick Fink <mail@pfink.de>

Co-authored-by: Connor Petty <mistercpp2000@gmail.com>
This commit is contained in:
Patrick Fink 2020-12-05 19:11:38 +01:00 committed by GitHub
parent 68dd5569f0
commit 601415db17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 573 additions and 0 deletions

View File

@ -27,6 +27,7 @@
/bundles/org.openhab.binding.bluetooth.bluez/ @cdjackson @kaikreuzer
/bundles/org.openhab.binding.bluetooth.blukii/ @kaikreuzer
/bundles/org.openhab.binding.bluetooth.daikinmadoka/ @blafois
/bundles/org.openhab.binding.bluetooth.enoceanble/ @pfink
/bundles/org.openhab.binding.bluetooth.generic/ @cpmeister
/bundles/org.openhab.binding.bluetooth.roaming/ @cpmeister
/bundles/org.openhab.binding.bluetooth.ruuvitag/ @ssalonen

View File

@ -0,0 +1,14 @@
This content is produced and maintained by the openHAB project.
* Project home: https://www.openhab.org
== Declared Project Licenses
This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.
== Source Code
https://github.com/openhab/openhab-addons

View File

@ -0,0 +1,60 @@
# EnOcean BLE Binding
This binding adds support for the
[EnOcean BLE PTM215B](https://www.enocean.com/de/produkte/enocean_module_24ghz_ble/ptm-215b/) rocker.
**Currently, it does not work with the
[BlueZ Binding](https://www.openhab.org/addons/bindings/bluetooth.bluez)**.
The recommended / tested Bluetooth bridge binding is the
[BlueGiga Binding](https://www.openhab.org/addons/bindings/bluetooth.bluegiga).
## Supported Things
Only a single thing type is added by this extension:
| Thing Type ID | Description |
| --------------- | ------------------------- |
| ptm215b | The EnOcean PTM 215B Rocker |
These rockers are battery-less, the necessary energy for the BLE transmission is generated by the button click itself
and completely depleted after 3 attempts of a "fire & forget" (unidirectional) BLE transmission.
This means, the rockers are only "on" during the button click, so there is no possibility for openHAB to actively
retrieve the online status. Therefore, initial online status will always be "UNKNOWN" until the rocker is used.
## Discovery
As any other Bluetooth device, EnOcean BLE rockers are discovered automatically by the corresponding bridge. It's
necessary to click any button of the rocker up to 15 times in quick succession to get it discovered.
## Thing Configuration
There is only a single configuration parameter `address`, which corresponds to the Bluetooth address of the device
(in format "XX:XX:XX:XX:XX:XX"). Normally, the address is printed on the back of the rocker.
## Channels
An EnOcean PTM 215B Rocker has the following channels:
| Channel ID | Item Type | Description |
| ------------------------- | ------------------------ | ------------------------------ |
| rocker1 | system.rawrocker | In case of a dual rocker, the first rocker. In case of a single rocker, usually this channel has to be used. Anyhow, it depends from the implementation of the manufacturer of the rocker, so it could be that events are coming in on the second rocker channel. |
| rocker2 | system.rawrocker | In case of a dual rocker, the second rocker. |
## Example
demo.things:
```
Bridge bluetooth:bluegiga:bluegiga0 "Bluegiga Adapter" [ port="/dev/ttyBLUEGIGA", discovery=false ] {
Thing ptm215b rocker_livingroom "Rocker Living Room" [ address = "E2:15:00:00:53:F9" ]
Thing ptm215b rocker_kitchen "Rocker Kitchen" [ address = "E2:15:00:00:53:98" ]
}
```
demo.items:
```
Dimmer Light_LivingRoom { channel="milight:rgbLed:milight2:4:ledbrightness", channel="bluetooth:ptm215b:bluegiga0:rocker_livingroom:rocker1" [profile="rawrocker-to-on-off"], channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker1" [profile="rawrocker-to-on-off"] } // We have a combined kitchen / livingroom, so we control the living room lights with switches from the living room and from the kitchen
Switch Light_Kitchen { channel="hue:group:1:kitchen-bulbs:switch", channel="bluetooth:ptm215b:bluegiga0:rocker_kitchen:rocker2" [profile="rawrocker-to-on-off"] }
```

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>org.openhab.binding.bluetooth.enoceanble</artifactId>
<name>openHAB Add-ons :: Bundles :: EnOcean Bluetooth Adapter</name>
<dependencies>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.bluetooth</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.bluetooth.enoceanble-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${project.version}/xml/features</repository>
<feature name="openhab-binding-bluetooth-enoceanble" description="Bluetooth Binding EnOcean BLE" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.enoceanble/${project.version}</bundle>
</feature>
</features>

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.bluetooth.BluetoothBindingConstants;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link EnoceanBleBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Patrick Fink - Initial contribution
*/
@NonNullByDefault
public class EnoceanBleBindingConstants {
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_PTM215B = new ThingTypeUID(BluetoothBindingConstants.BINDING_ID,
"ptm215b");
// Channel IDs
public static final String CHANNEL_ID_ROCKER1 = "rocker1";
public static final String CHANNEL_ID_ROCKER2 = "rocker2";
}

View File

@ -0,0 +1,84 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.BluetoothBindingConstants;
import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryDevice;
import org.openhab.binding.bluetooth.discovery.BluetoothDiscoveryParticipant;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.osgi.service.component.annotations.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This discovery participant is able to recognize enoceanble devices and create discovery results for them.
*
* @author Patrick Fink - Initial contribution
*
*/
@NonNullByDefault
@Component
public class EnoceanBleDiscoveryParticipant implements BluetoothDiscoveryParticipant {
private final Logger logger = LoggerFactory.getLogger(EnoceanBleDiscoveryParticipant.class);
private static final int ENOCEAN_COMPANY_ID = 986;
@Override
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
return Collections.singleton(EnoceanBleBindingConstants.THING_TYPE_PTM215B);
}
@Override
public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) {
Integer manufacturerId = device.getManufacturerId();
logger.warn("Discovered device {} with manufacturerId {} and name {}", device.getAddress(), manufacturerId,
device.getName());
if (manufacturerId != null && manufacturerId == ENOCEAN_COMPANY_ID) {
return new ThingUID(EnoceanBleBindingConstants.THING_TYPE_PTM215B, device.getAdapter().getUID(),
device.getAddress().toString().toLowerCase().replace(":", ""));
}
return null;
}
@Override
public @Nullable DiscoveryResult createResult(BluetoothDiscoveryDevice device) {
ThingUID thingUID = getThingUID(device);
if (thingUID == null) {
return null;
}
String label = "Enocean PTM215B Rocker";
Map<String, Object> properties = new HashMap<>();
properties.put(BluetoothBindingConstants.CONFIGURATION_ADDRESS, device.getAddress().toString());
properties.put(Thing.PROPERTY_VENDOR, "EnOcean GmbH");
Integer txPower = device.getTxPower();
if (txPower != null) {
properties.put(BluetoothBindingConstants.PROPERTY_TXPOWER, Integer.toString(txPower));
}
// Create the discovery result and add to the inbox
return DiscoveryResultBuilder.create(thingUID).withProperties(properties)
.withRepresentationProperty(BluetoothBindingConstants.CONFIGURATION_ADDRESS)
.withBridge(device.getAdapter().getUID()).withLabel(label).build();
}
}

View File

@ -0,0 +1,54 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import java.util.Collections;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Component;
/**
* The {@link EnoceanBleHandlerFactory} is responsible for creating things and thing handlers.
*
* @author Patrick Fink - Initial contribution
*/
@NonNullByDefault
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.enoceanble")
public class EnoceanBleHandlerFactory extends BaseThingHandlerFactory {
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.singleton(EnoceanBleBindingConstants.THING_TYPE_PTM215B);
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
@Override
protected @Nullable ThingHandler createHandler(Thing thing) {
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
if (thingTypeUID.equals(EnoceanBleBindingConstants.THING_TYPE_PTM215B)) {
return new EnoceanBleRockerHandler(thing);
}
return null;
}
}

View File

@ -0,0 +1,67 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link EnoceanBlePtm215Event} class is parsing the BLE manufacturer data into an event object.
*
* @author Patrick Fink - Initial contribution
*/
@NonNullByDefault
public class EnoceanBlePtm215Event {
private static final byte PRESSED = 0x1;
private static final byte BUTTON1_DIR1 = 0x10;
private static final byte BUTTON1_DIR2 = 0x8;
private static final byte BUTTON2_DIR1 = 0x4;
private static final byte BUTTON2_DIR2 = 0x2;
private final byte byteState;
public EnoceanBlePtm215Event(byte[] manufacturerData) {
byteState = manufacturerData[6];
}
public boolean isPressed() {
return checkFlag(PRESSED);
}
public boolean isButton1() {
return checkFlag(BUTTON1_DIR1) || checkFlag(BUTTON1_DIR2);
}
public boolean isButton2() {
return checkFlag(BUTTON2_DIR1) || checkFlag(BUTTON2_DIR2);
}
public boolean isDir1() {
return checkFlag(BUTTON1_DIR1) || checkFlag(BUTTON2_DIR1);
}
public boolean isDir2() {
return checkFlag(BUTTON1_DIR2) || checkFlag(BUTTON2_DIR2);
}
private boolean checkFlag(int flag) {
return (byteState & flag) == flag;
}
@Override
public String toString() {
return "Button " + (isButton1() ? 1 : 2) + " Dir " + (isDir1() ? 1 : 2) + " "
+ (isPressed() ? "PRESSED" : "RELEASED");
}
}

View File

@ -0,0 +1,83 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.bluetooth.BeaconBluetoothHandler;
import org.openhab.binding.bluetooth.notification.BluetoothScanNotification;
import org.openhab.core.thing.CommonTriggerEvents;
import org.openhab.core.thing.Thing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link EnoceanBleRockerHandler} is responsible for handling commands, which are
* sent to one of the channels.
*
* @author Patrick Fink - Initial contribution
*/
@NonNullByDefault
public class EnoceanBleRockerHandler extends BeaconBluetoothHandler {
private final Logger logger = LoggerFactory.getLogger(EnoceanBleRockerHandler.class);
public EnoceanBleRockerHandler(Thing thing) {
super(thing);
}
@Override
public void onScanRecordReceived(BluetoothScanNotification scanNotification) {
super.onScanRecordReceived(scanNotification);
final byte[] manufacturerData = scanNotification.getManufacturerData();
logger.debug("Received new scan notification for {}: {}", device.getAddress(), manufacturerData);
try {
if (manufacturerData != null && manufacturerData.length > 0) {
EnoceanBlePtm215Event event = new EnoceanBlePtm215Event(manufacturerData);
logger.debug("Parsed manufacturer data to PTM215B event: {}", event);
triggerChannel(resolveChannel(event), resolveTriggerEvent(event));
}
} catch (IllegalStateException e) {
logger.warn("PTM215B event could not be parsed correctly, exception occured:", e);
}
}
protected String resolveChannel(EnoceanBlePtm215Event event) {
if (event.isButton1()) {
return EnoceanBleBindingConstants.CHANNEL_ID_ROCKER1;
}
if (event.isButton2()) {
return EnoceanBleBindingConstants.CHANNEL_ID_ROCKER2;
}
throw new IllegalStateException(
"PTM215B event cannot be resolved correctly to a channel, probably received message is invalid");
}
protected String resolveTriggerEvent(EnoceanBlePtm215Event event) {
if (event.isDir1()) {
if (event.isPressed()) {
return CommonTriggerEvents.DIR1_PRESSED;
} else {
return CommonTriggerEvents.DIR1_RELEASED;
}
}
if (event.isDir2()) {
if (event.isPressed()) {
return CommonTriggerEvents.DIR2_PRESSED;
} else {
return CommonTriggerEvents.DIR2_RELEASED;
}
}
throw new IllegalStateException(
"PTM215B event cannot be resolved correctly to an openHAB event, probably received message is invalid");
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="bluetooth"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
<thing-type id="ptm215b">
<supported-bridge-type-refs>
<bridge-type-ref id="roaming"/>
<bridge-type-ref id="bluegiga"/>
<bridge-type-ref id="bluez"/>
</supported-bridge-type-refs>
<label>Enocean PTM 215B Rocker</label>
<description>An Enocean BLE Rocker (PTM 215B)</description>
<channels>
<channel id="rocker1" typeId="system.rawrocker"/>
<channel id="rocker2" typeId="system.rawrocker"/>
</channels>
<config-description>
<parameter name="address" type="text">
<label>Address</label>
<description>Bluetooth address in XX:XX:XX:XX:XX:XX format</description>
</parameter>
</config-description>
</thing-type>
</thing:thing-descriptions>

View File

@ -0,0 +1,107 @@
/**
* Copyright (c) 2010-2020 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.bluetooth.enoceanble.internal;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
/**
* {@link EnoceanBlePtm215EventTest} is testing the {@link EnoceanBlePtm215Event} class
* using some sample manufacturerData
*
* @author Patrick Fink - Initial contribution
*/
@NonNullByDefault
public class EnoceanBlePtm215EventTest {
@Test
public void testButton1Dir1Pressed() {
byte[] button1Dir2PressedBytes = { -38, 3, 53, 5, 0, 0, 17, 54, 81, 61, 54 };
EnoceanBlePtm215Event button1Dir2PressedEvent = new EnoceanBlePtm215Event(button1Dir2PressedBytes);
assertTrue(button1Dir2PressedEvent.isPressed());
assertTrue(button1Dir2PressedEvent.isButton1());
assertTrue(button1Dir2PressedEvent.isDir1());
}
@Test
public void testButton1Dir1Released() {
byte[] button1Dir2ReleasedBytes = { -38, 3, 54, 5, 0, 0, 16, -83, -25, 103, 3 };
EnoceanBlePtm215Event button1Dir2ReleasedEvent = new EnoceanBlePtm215Event(button1Dir2ReleasedBytes);
assertFalse(button1Dir2ReleasedEvent.isPressed());
assertTrue(button1Dir2ReleasedEvent.isButton1());
assertTrue(button1Dir2ReleasedEvent.isDir1());
}
@Test
public void testButton1Dir2Pressed() {
byte[] button1Dir2PressedBytes = { -38, 3, -97, 32, 0, 0, 9, -99, -15, 16, -74 };
EnoceanBlePtm215Event button1Dir2PressedEvent = new EnoceanBlePtm215Event(button1Dir2PressedBytes);
assertTrue(button1Dir2PressedEvent.isPressed());
assertTrue(button1Dir2PressedEvent.isButton1());
assertTrue(button1Dir2PressedEvent.isDir2());
}
@Test
public void testButton1Dir2Released() {
byte[] button1Dir2ReleasedBytes = { -38, 3, -96, 32, 0, 0, 8, -87, -96, 98, 74 };
EnoceanBlePtm215Event button1Dir2ReleasedEvent = new EnoceanBlePtm215Event(button1Dir2ReleasedBytes);
assertFalse(button1Dir2ReleasedEvent.isPressed());
assertTrue(button1Dir2ReleasedEvent.isButton1());
assertTrue(button1Dir2ReleasedEvent.isDir2());
}
@Test
public void testButton2Dir1Pressed() {
byte[] button2Dir1PressedBytes = { -38, 3, -91, 32, 0, 0, 5, 89, 104, 24, -67 };
EnoceanBlePtm215Event button2Dir1PressedEvent = new EnoceanBlePtm215Event(button2Dir1PressedBytes);
assertTrue(button2Dir1PressedEvent.isPressed());
assertTrue(button2Dir1PressedEvent.isButton2());
assertTrue(button2Dir1PressedEvent.isDir1());
}
@Test
public void testButton2Dir1Released() {
byte[] button2Dir1ReleasedBytes = { -38, 3, -90, 32, 0, 0, 4, 120, 52, -115, 61 };
EnoceanBlePtm215Event button2Dir1ReleasedEvent = new EnoceanBlePtm215Event(button2Dir1ReleasedBytes);
assertFalse(button2Dir1ReleasedEvent.isPressed());
assertTrue(button2Dir1ReleasedEvent.isButton2());
assertTrue(button2Dir1ReleasedEvent.isDir1());
}
@Test
public void testButton2Dir2Pressed() {
byte[] button2Dir2PressedBytes = { -38, 3, -95, 32, 0, 0, 3, -105, -33, 62, 45 };
EnoceanBlePtm215Event button2Dir1PressedEvent = new EnoceanBlePtm215Event(button2Dir2PressedBytes);
assertTrue(button2Dir1PressedEvent.isPressed());
assertTrue(button2Dir1PressedEvent.isButton2());
assertTrue(button2Dir1PressedEvent.isDir2());
}
@Test
public void testButton2Dir2Released() {
byte[] button2Dir2ReleasedBytes = { -38, 3, -94, 32, 0, 0, 2, 59, 118, 52, -69 };
EnoceanBlePtm215Event button2Dir2ReleasedEvent = new EnoceanBlePtm215Event(button2Dir2ReleasedBytes);
assertFalse(button2Dir2ReleasedEvent.isPressed());
assertTrue(button2Dir2ReleasedEvent.isButton2());
assertTrue(button2Dir2ReleasedEvent.isDir2());
}
}

View File

@ -59,6 +59,7 @@
<module>org.openhab.binding.bluetooth.bluez</module>
<module>org.openhab.binding.bluetooth.blukii</module>
<module>org.openhab.binding.bluetooth.daikinmadoka</module>
<module>org.openhab.binding.bluetooth.enoceanble</module>
<module>org.openhab.binding.bluetooth.generic</module>
<module>org.openhab.binding.bluetooth.roaming</module>
<module>org.openhab.binding.bluetooth.ruuvitag</module>

View File

@ -10,6 +10,7 @@
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.bluegiga/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.blukii/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.daikinmadoka/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.enoceanble/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.generic/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.roaming/${project.version}</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.bluetooth.ruuvitag/${project.version}</bundle>