added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
33
bundles/org.openhab.binding.bluetooth.ruuvitag/.classpath
Normal file
33
bundles/org.openhab.binding.bluetooth.ruuvitag/.classpath
Normal file
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="lib/ruuvitag-common-1.0.0.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
23
bundles/org.openhab.binding.bluetooth.ruuvitag/.project
Normal file
23
bundles/org.openhab.binding.bluetooth.ruuvitag/.project
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.openhab.binding.bluetooth.ruuvitag</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
21
bundles/org.openhab.binding.bluetooth.ruuvitag/NOTICE
Normal file
21
bundles/org.openhab.binding.bluetooth.ruuvitag/NOTICE
Normal file
@@ -0,0 +1,21 @@
|
||||
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
|
||||
|
||||
== Third-party Content
|
||||
|
||||
[ruuvitag-common-java]
|
||||
* License: MIT License
|
||||
* Project: https://github.com/Scrin/ruuvitag-common-java
|
||||
* Source: https://github.com/Scrin/ruuvitag-common-java
|
||||
|
||||
64
bundles/org.openhab.binding.bluetooth.ruuvitag/README.md
Normal file
64
bundles/org.openhab.binding.bluetooth.ruuvitag/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Ruuvi Tag
|
||||
|
||||
This extension adds support for [Ruuvi Tag](https://ruuvi.com/) Sensor Beacons.
|
||||
|
||||
## Supported Things
|
||||
|
||||
Only a single thing type is added by this extension:
|
||||
|
||||
| Thing Type ID | Description |
|
||||
| --------------- | ------------------------- |
|
||||
| ruuvitag_beacon | A Ruuvi Tag Sensor Beacon |
|
||||
|
||||
|
||||
Under normal conditions the ruuvitag should submit data every 10 seconds.
|
||||
However, if no data has been retrieved after 1 minute the ruuvitag is set to OFFLINE and the state of channels is set to UNDEF.
|
||||
When new data is retrieved when OFFLINE the ruuvtag is set ONLINE again.
|
||||
|
||||
## Discovery
|
||||
|
||||
As any other Bluetooth device, Ruuvi Tag Beacons are discovered automatically by the corresponding bridge.
|
||||
|
||||
## 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").
|
||||
|
||||
## Channels
|
||||
|
||||
A Ruuvi Tag Smart Beacon has the following channels:
|
||||
|
||||
| Channel ID | Item Type | Description |
|
||||
| ------------------------- | ------------------------ | ------------------------------ |
|
||||
| temperature | Number:Temperature | The measured temperature |
|
||||
| humidity | Number:Dimensionless | The measured humidity |
|
||||
| pressure | Number:Pressure | The measured air pressure |
|
||||
| batteryVoltage | Number:ElectricPotential | The measured battery voltage |
|
||||
| accelerationx | Number:Acceleration | The measured acceleration of X |
|
||||
| accelerationy | Number:Acceleration | The measured acceleration of Y |
|
||||
| accelerationz | Number:Acceleration | The measured acceleration of Z |
|
||||
| txPower | Number:Power | TX power |
|
||||
| dataFormat | Number | Data format version |
|
||||
| measurementSequenceNumber | Number:Dimensionless | Measurement sequence number |
|
||||
| movementCounter | Number:Dimensionless | Movement counter |
|
||||
|
||||
Note: not all channels are always available. Available fields depends on [Ruuvi Data Format](https://github.com/ruuvi/ruuvi-sensor-protocols).
|
||||
|
||||
## Example
|
||||
|
||||
demo.things:
|
||||
|
||||
```
|
||||
bluetooth:ruuvitag:hci0:beacon "RuuviTag Sensor Beacon" (bluetooth:bluez:hci0) [ address="12:34:56:78:9A:BC" ]
|
||||
```
|
||||
|
||||
demo.items:
|
||||
|
||||
```
|
||||
Number:Temperature temperature "Room Temperature [%.1f %unit%]" { channel="bluetooth:ruuvitag:hci0:beacon:temperature" }
|
||||
Number:Dimensionless humidity "Humidity [%.0f %unit%]" { channel="bluetooth:ruuvitag:hci0:beacon:humidity" }
|
||||
Number:Pressure pressure "Air Pressure [%.0f %unit%]" { channel="bluetooth:ruuvitag:hci0:beacon:pressure" }
|
||||
|
||||
// Examples of converting units
|
||||
Number:Acceleration acceleration_ms "Acceleration z [%.2f m/s²]" { channel="bluetooth:ruuvitag:hci0:beacon:accelerationz" }
|
||||
Number:Acceleration acceleration_g "Acceleration z (g-force) [%.2f gₙ]" { channel="bluetooth:ruuvitag:hci0:beacon:accelerationz" }
|
||||
```
|
||||
Binary file not shown.
25
bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml
Normal file
25
bundles/org.openhab.binding.bluetooth.ruuvitag/pom.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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.ruuvitag</artifactId>
|
||||
|
||||
<name>openHAB Add-ons :: Bundles :: RuuviTag 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>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.bluetooth.ruuvitag-${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/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-bluetooth-ruuvitag" description="Bluetooth Binding Ruuvitag" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-serial</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.ruuvitag/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
</features>
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.ruuvitag.internal;
|
||||
|
||||
import org.openhab.binding.bluetooth.BluetoothBindingConstants;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link RuuviTagBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
public class RuuviTagBindingConstants {
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID THING_TYPE_BEACON = new ThingTypeUID(BluetoothBindingConstants.BINDING_ID,
|
||||
"ruuvitag_beacon");
|
||||
|
||||
// Channel IDs
|
||||
public static final String CHANNEL_ID_BATTERY = "batteryVoltage";
|
||||
public static final String CHANNEL_ID_DATA_FORMAT = "dataFormat";
|
||||
public static final String CHANNEL_ID_TEMPERATURE = "temperature";
|
||||
public static final String CHANNEL_ID_HUMIDITY = "humidity";
|
||||
public static final String CHANNEL_ID_PRESSURE = "pressure";
|
||||
public static final String CHANNEL_ID_TX_POWER = "txPower";
|
||||
|
||||
public static final String CHANNEL_ID_ACCELERATIONX = "accelerationx";
|
||||
public static final String CHANNEL_ID_ACCELERATIONY = "accelerationy";
|
||||
public static final String CHANNEL_ID_ACCELERATIONZ = "accelerationz";
|
||||
public static final String CHANNEL_ID_MEASUREMENT_SEQUENCE_NUMBER = "measurementSequenceNumber";
|
||||
public static final String CHANNEL_ID_MOVEMENT_COUNTER = "movementCounter";
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.ruuvitag.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;
|
||||
|
||||
/**
|
||||
* This discovery participant is able to recognize ruuvitag devices and create discovery results for them.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(immediate = true)
|
||||
public class RuuviTagDiscoveryParticipant implements BluetoothDiscoveryParticipant {
|
||||
|
||||
private static final int RUUVITAG_COMPANY_ID = 1177;
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return Collections.singleton(RuuviTagBindingConstants.THING_TYPE_BEACON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingUID getThingUID(BluetoothDiscoveryDevice device) {
|
||||
Integer manufacturerId = device.getManufacturerId();
|
||||
if (manufacturerId != null && manufacturerId == RUUVITAG_COMPANY_ID) {
|
||||
return new ThingUID(RuuviTagBindingConstants.THING_TYPE_BEACON, 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 = "Ruuvi Tag";
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put(BluetoothBindingConstants.CONFIGURATION_ADDRESS, device.getAddress().toString());
|
||||
properties.put(Thing.PROPERTY_VENDOR, "Ruuvi Innovations Ltd (Oy)");
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* 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.ruuvitag.internal;
|
||||
|
||||
import static org.openhab.binding.bluetooth.ruuvitag.internal.RuuviTagBindingConstants.*;
|
||||
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import javax.measure.Quantity;
|
||||
import javax.measure.Unit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.bluetooth.BeaconBluetoothHandler;
|
||||
import org.openhab.binding.bluetooth.notification.BluetoothScanNotification;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
import org.openhab.core.library.unit.SIUnits;
|
||||
import org.openhab.core.library.unit.SmartHomeUnits;
|
||||
import org.openhab.core.thing.Channel;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import fi.tkgwf.ruuvi.common.bean.RuuviMeasurement;
|
||||
import fi.tkgwf.ruuvi.common.parser.impl.AnyDataFormatParser;
|
||||
|
||||
/**
|
||||
* The {@link RuuviTagHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class RuuviTagHandler extends BeaconBluetoothHandler {
|
||||
|
||||
// Ruuvitag sends an update every 10 seconds. So we keep a heartbeat to give it some slack
|
||||
private static final int HEARTBEAT_TIMEOUT_MINUTES = 1;
|
||||
private final Logger logger = LoggerFactory.getLogger(RuuviTagHandler.class);
|
||||
private final AnyDataFormatParser parser = new AnyDataFormatParser();
|
||||
private final AtomicBoolean receivedStatus = new AtomicBoolean();
|
||||
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> heartbeatFuture;
|
||||
|
||||
public RuuviTagHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
if (getThing().getStatus() != ThingStatus.OFFLINE) {
|
||||
heartbeatFuture = scheduler.scheduleWithFixedDelay(this::heartbeat, 0, HEARTBEAT_TIMEOUT_MINUTES,
|
||||
TimeUnit.MINUTES);
|
||||
}
|
||||
}
|
||||
|
||||
private void heartbeat() {
|
||||
synchronized (receivedStatus) {
|
||||
if (!receivedStatus.getAndSet(false) && getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
getThing().getChannels().stream().map(Channel::getUID).filter(this::isLinked)
|
||||
.forEach(c -> updateState(c, UnDefType.UNDEF));
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"No data received for some time");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
try {
|
||||
super.dispose();
|
||||
} finally {
|
||||
if (heartbeatFuture != null) {
|
||||
heartbeatFuture.cancel(true);
|
||||
heartbeatFuture = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanRecordReceived(BluetoothScanNotification scanNotification) {
|
||||
synchronized (receivedStatus) {
|
||||
receivedStatus.set(true);
|
||||
super.onScanRecordReceived(scanNotification);
|
||||
final byte[] manufacturerData = scanNotification.getManufacturerData();
|
||||
if (manufacturerData != null && manufacturerData.length > 0) {
|
||||
final RuuviMeasurement ruuvitagData = parser.parse(manufacturerData);
|
||||
logger.trace("Ruuvi received new scan notification for {}: {}", scanNotification.getAddress(),
|
||||
ruuvitagData);
|
||||
if (ruuvitagData != null) {
|
||||
boolean atLeastOneRuuviFieldPresent = false;
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
switch (channelUID.getId()) {
|
||||
case CHANNEL_ID_ACCELERATIONX:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getAccelerationX(), SmartHomeUnits.STANDARD_GRAVITY);
|
||||
break;
|
||||
case CHANNEL_ID_ACCELERATIONY:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getAccelerationY(), SmartHomeUnits.STANDARD_GRAVITY);
|
||||
break;
|
||||
case CHANNEL_ID_ACCELERATIONZ:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getAccelerationZ(), SmartHomeUnits.STANDARD_GRAVITY);
|
||||
break;
|
||||
case CHANNEL_ID_BATTERY:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getBatteryVoltage(), SmartHomeUnits.VOLT);
|
||||
break;
|
||||
case CHANNEL_ID_DATA_FORMAT:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getDataFormat());
|
||||
break;
|
||||
case CHANNEL_ID_HUMIDITY:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getHumidity(), SmartHomeUnits.PERCENT);
|
||||
break;
|
||||
case CHANNEL_ID_MEASUREMENT_SEQUENCE_NUMBER:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getMeasurementSequenceNumber(), SmartHomeUnits.ONE);
|
||||
break;
|
||||
case CHANNEL_ID_MOVEMENT_COUNTER:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getMovementCounter(), SmartHomeUnits.ONE);
|
||||
break;
|
||||
case CHANNEL_ID_PRESSURE:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getPressure(), SIUnits.PASCAL);
|
||||
break;
|
||||
case CHANNEL_ID_TEMPERATURE:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getTemperature(), SIUnits.CELSIUS);
|
||||
break;
|
||||
case CHANNEL_ID_TX_POWER:
|
||||
atLeastOneRuuviFieldPresent |= updateStateIfLinked(channelUID,
|
||||
ruuvitagData.getTxPower(), SmartHomeUnits.DECIBEL_MILLIWATTS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (atLeastOneRuuviFieldPresent) {
|
||||
// In practice, updated to ONLINE by super.onScanRecordReceived already, based on RSSI value
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Received Ruuvi Tag data but no fields could be parsed");
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Received bluetooth data which could not be parsed to any known Ruuvi Tag data formats");
|
||||
}
|
||||
} else {
|
||||
// Received Bluetooth scan with no manufacturer data
|
||||
// This happens -- we ignore this silently.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update QuantityType channel state
|
||||
*
|
||||
* Update is not done when value is null.
|
||||
*
|
||||
* @param channelUID channel UID
|
||||
* @param value value to update
|
||||
* @param unit unit associated with the value
|
||||
* @return whether the value was present
|
||||
*/
|
||||
private <T extends Quantity<T>> boolean updateStateIfLinked(ChannelUID channelUID, @Nullable Number value,
|
||||
Unit<T> unit) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
if (isLinked(channelUID)) {
|
||||
updateState(channelUID, new QuantityType<>(value, unit));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DecimalType channel state
|
||||
*
|
||||
* Update is not done when value is null.
|
||||
*
|
||||
* @param channelUID channel UID
|
||||
* @param value value to update
|
||||
* @return whether the value was present
|
||||
*/
|
||||
private <T extends Quantity<T>> boolean updateStateIfLinked(ChannelUID channelUID, @Nullable Integer value) {
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
if (isLinked(channelUID)) {
|
||||
updateState(channelUID, new DecimalType(value));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.ruuvitag.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 RuuviTagHandlerFactory} is responsible for creating things and thing handlers.
|
||||
*
|
||||
* @author Sami Salonen - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.ruuvitag")
|
||||
public class RuuviTagHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.singleton(RuuviTagBindingConstants.THING_TYPE_BEACON);
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(RuuviTagBindingConstants.THING_TYPE_BEACON)) {
|
||||
return new RuuviTagHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?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="ruuvitag_beacon">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="roaming"/>
|
||||
<bridge-type-ref id="bluegiga"/>
|
||||
<bridge-type-ref id="bluez"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>RuuviTag SmartBeacon</label>
|
||||
<description>A RuuviTag SmartBeacon</description>
|
||||
|
||||
<channels>
|
||||
<channel id="rssi" typeId="rssi"/>
|
||||
<channel id="accelerationx" typeId="ruuvitag_accelerationx"/>
|
||||
<channel id="accelerationy" typeId="ruuvitag_accelerationy"/>
|
||||
<channel id="accelerationz" typeId="ruuvitag_accelerationz"/>
|
||||
<channel id="batteryVoltage" typeId="ruuvitag_batteryVoltage"/>
|
||||
<channel id="dataFormat" typeId="ruuvitag_dataFormat"/>
|
||||
<channel id="humidity" typeId="ruuvitag_humidity"/>
|
||||
<channel id="measurementSequenceNumber" typeId="ruuvitag_measurementSequenceNumber"/>
|
||||
<channel id="movementCounter" typeId="ruuvitag_movementCounter"/>
|
||||
<channel id="pressure" typeId="ruuvitag_pressure"/>
|
||||
<channel id="temperature" typeId="ruuvitag_temperature"/>
|
||||
<channel id="txPower" typeId="ruuvitag_txPower"/>
|
||||
</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>
|
||||
|
||||
<channel-type id="ruuvitag_accelerationx">
|
||||
<item-type>Number:Acceleration</item-type>
|
||||
<label>Acceleration X</label>
|
||||
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_accelerationy">
|
||||
<item-type>Number:Acceleration</item-type>
|
||||
<label>Acceleration Y</label>
|
||||
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_accelerationz">
|
||||
<item-type>Number:Acceleration</item-type>
|
||||
<label>Acceleration Z</label>
|
||||
<state readOnly="true" pattern="%.3f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_batteryVoltage">
|
||||
<item-type>Number:ElectricPotential</item-type>
|
||||
<label>Battery Voltage</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_dataFormat" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Data Format Version</label>
|
||||
<state readOnly="true" pattern="%.0f"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_humidity">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Humidity</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_measurementSequenceNumber" advanced="true">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Measurement Sequence Number</label>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_movementCounter" advanced="true">
|
||||
<item-type>Number:Dimensionless</item-type>
|
||||
<label>Measurement Counter</label>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_pressure">
|
||||
<item-type>Number:Pressure</item-type>
|
||||
<label>Pressure</label>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Temperature</label>
|
||||
<state readOnly="true" pattern="%.1f %unit%"/>
|
||||
</channel-type>
|
||||
<channel-type id="ruuvitag_txPower">
|
||||
<item-type>Number:Power</item-type>
|
||||
<label>TX Power</label>
|
||||
<state readOnly="true" pattern="%.0f %unit%"/>
|
||||
</channel-type>
|
||||
</thing:thing-descriptions>
|
||||
Reference in New Issue
Block a user