added migrated 2.x add-ons

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Kai Kreuzer
2020-09-21 01:58:32 +02:00
parent bbf1a7fd29
commit 6df6783b60
11662 changed files with 1302875 additions and 11 deletions

View File

@@ -0,0 +1,32 @@
<?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="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" 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="output" path="target/classes"/>
</classpath>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>org.openhab.binding.tellstick</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>

View File

@@ -0,0 +1,41 @@
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
async-http
* License: Apache 2.0 License
* Project: https://github.com/AsyncHttpClient/async-http-client
* Source: https://github.com/AsyncHttpClient/async-http-client
javatellstick
* License: BSD-2-Clause License
* Project: https://github.com/peec/javatellstick
* Source: https://github.com/jannegpriv/javatellstick
netty
* License: Apache 2.0 License
* Project: https://netty.io
* Source: https://github.com/netty/netty
reactive-streams
* License: CC0 1.0 License
* Project: https://www.reactive-streams.org
* Source: https://github.com/reactive-streams/reactive-streams-jvm
jna
* License: Apache 2.0 License
* Project: https://github.com/java-native-access/jna
* Source: https://github.com/java-native-access/jna

View File

@@ -0,0 +1,208 @@
# Tellstick Binding
This is an openHAB binding for Tellstick devices produced by Telldus, a Swedish company based in Lund.
The original Tellstick focused on controlling 433 MHz devices like switches, dimmers and reading sensors from different brands.
Many of the supported devices are cheaper and "low-end" and support have been made by reverse engineer the transmission protocols.
All of these 433 MHz devices is one-way, so some versions of the Tellstick monitoring the air to keep the state of all devices.
The latest versions have also implemented Z-Wave as transmission protocol which open up for more robust transmission due two-ways communication.
<p align="center">
<img src="doc/tellstick_duo.jpg" alt="Tellstick Duo with device" width="300px"/>
</p>
## Supported Things
This binding supports the following thing types:
* *Dimmable Device* - Usually for controlling lamps. `dimmer`
* *Switchable Device* - On/Off only could be lamps or other electronic equipment. `switch`
* *Sensors* - Temperature- and humidity-sensors. `sensor`
Additionally the binding have two types of bridge things which correspond to available API types:
* *Telldus Core Bridge* - Oldest API, used by USB devices. `telldus-core`
* *Telldus Live Bridge* - Telldus Cloud service, all devices with online access. `telldus-live`
***Switchbased sensors workaround***
* Some 433MHz magnetic & PIR sensors, for example, magnetic door sensors, are detected as regular `switch` Things instead of type `contact`. There is technically no way of distinguish them apart from regulur `switch` Things. For using them as sensors only (not paired to a lamp) please consult the workaround in the channel section.
## Discovery
Devices which is added to *Telldus Core* and *Telldus Live* can be discovered by openHAB.
When you add this binding it will try to discover the *Telldus Core Bridge*.
If it is installed correct its devices will show up.
If you want to use the *Telldus Live* its bridge, *Telldus Live bridge* need to be added manually.
## Binding Configuration
The binding itself requires no configuration.
## Thing Configuration
Only the bridges require manual configuration.
It is preferable that devices and sensors are discovered automatically; let the discovery/inbox initially configure them.
You can add them either with karaf: `inbox approve <thingId>` or by using the inbox of the Paper UI.
### Dimmers & switches
There is an option to override the resend count of the commands.
Use the option `repeat` for that. Default resend count is 2.
### Bridges
Depending on your tellstick device type there is different ways of using this binding.
The binding implements two different API:
**1)** *Telldus Core* which is a local only interface supported by USB based device. <br>
**2)** *Telldus Live* which is a REST based cloud service maintained by Telldus. <br>
> Not implemented yet but supported by some new devices, contributions are welcome. [API documention.](https://api.telldus.net/localapi/api.html) <br>
> **3)** *Local Rest API* is a local API which would work similar to Telldus Live but local.
Depending on your Tellstick model, different bridge-types are available:
| Model | Telldus Core | Telldus Live | Local REST API | Verified working with openHAB |
|-------------------------|:------------:|:------------:|:--------------:|:-----------------------------:|
| Tellstick Basic | X | X | | X |
| Tellstick Duo | X | X | | X |
| Tellstick Net v.1 | | X | | |
| Tellstick Net v.2 | | X | X | |
| Tellstick ZNet Lite v.1 | | X | X | X |
| Tellstick ZNet Lite v.2 | | X | X | |
#### Telldus Core Bridge
> To enable communication between openHAB and tellstick-core service (Telldus center) they must use same architecture, eg. 32-bit or 64-bit. The supplied version from Telldus is compiled against 32-bit architecture. Therefore, it is better to use 32-bit java for openHAB. To check which version of Java is currently in use, run: `java -d32 -version`
>
> *For changing architecture in Linux check out: `dpkg --add-architecture`*
The telldus-core bridge uses a library on the local computer which is a `.dll` file for Windows and a `.so` file for Linux. The default one is usually correct.
```
Bridge tellstick:telldus-core:1 "Tellstick Duo" [resendInterval=200,libraryPath="C:/Program Files/Telldus/;C:/Program Files (x86)/Telldus/"]
```
Optional:
- **libraryPath:** The path to tellduscore.dll/so semicolon seperated list of folders.
- **resendInterval:** The interval between each transmission of command in ms, default 100ms.
#### Telldus Live Bridge
To configure Telldus Live you have request OAuth tokens from Telldus.
Goto this page <https://api.telldus.com/keys/index> and request your keys and update the config.
```
Bridge tellstick:telldus-live:2 "Tellstick ZWave" [publicKey="XXX", privateKey="YYYY", token= "ZZZZ", tokenSecret="UUUU"]
```
Required:
- **privateKey:** Private key
- **publicKey:** Public key
- **token:** Token
- **tokenSecret:** Token secret
Optional:
- **refreshInterval:** How often we should contact *Telldus Live* to check for updates (in ms)
## Channels
Actuators (dimmer/switch) support the following channels:
| Channel Type ID | Item Type | Description |
|-----------------|-----------|---------------------------------------------------------------|
| dimmer | Number | This channel indicates the current dim level |
| state | Switch | This channel indicates whether a device is turned on or off. |
| timestamp | DateTime | This channel reports the last time this device state changed. |
Sensors (sensor) support the following channels:
| Channel Type ID | Item Type | Description |
|-----------------|---------------------|-------------------------------------------------------------|
| humidity | Number:Dimensionless| This channel reports the current humidity in percentage. |
| temperature | Number:Temperature | This channel reports the current temperature. |
| timestamp | DateTime | This channel reports the last time this sensor was updates. |
PowerSensors ([powersensor]) support the following channels:
| Channel Type ID | Item Type | Description |
|-----------------|------------------------|-------------------------------------------------------------|
| watt | Number:Power | This channel reports the current watt. |
| ampere | Number:ElectricCurrent | This channel reports the current ampere. |
| timestamp | DateTime | This channel reports the last time this sensor was updates. |
WindSensors ([windsensor]) support the following channels:
| Channel Type ID | Item Type | Description |
|-----------------|--------------|------------------------------|
| windgust | Number:Speed | The current peak wind gust. |
| winddirection | Number:Angle | The current wind direction. |
| windaverage | Number:Speed | The current wind average. |
RainSensors ([rainsensor]) support the following channels:
| Channel Type ID | Item Type | Description |
|-----------------|---------------|----------------------------|
| rainrate | Number:Length | This current rate of rain. |
| raintotal | Number:Length | The total rain. |
### Switchbased sensor workaround
All switchbased sensors are binary and the goal is to represent them as a `contact` item in openHAB. Eg. a door is open or closed and can't be altered by sending a radio signal.
To achieve that we will create a proxy item which is updated by a rule.
First create another proxy item for every sensor:
```
Switch front_door_sensor "Front door" <door> {channel="tellstick:switch:1:7:state"}
Contact front_door_proxy "Front door" <door>
```
Then create a rule which updates the proxy item:
```
rule "proxy_front_door_on"
when
Item front_door_sensor changed to ON
then
front_door_proxy.postUpdate(OPEN);
end
rule "proxy_front_door_off"
when
Item front_door_sensor changed to OFF
then
front_door_proxy.postUpdate(CLOSED);
end
```
## Full Example
### tellstick.things
```
Bridge tellstick:telldus-core:1 "Tellstick Duo" [resendInterval=200] {
dimmer BedroomCeilingLamp1 [protocol="arctech",model="selflearning-dimmer",name="BedroomCeilingLamp1",deviceId="8"]
switch LivingTV [protocol="arctech",name="LivingTV",deviceId="5"]
sensor OutsideSensor1 [protocol="fineoffset",model="temperaturehumidity",name="temperaturehumidity:125",deviceId="125_temperaturehumidity_fineoffset"]
}
Bridge tellstick:telldus-live:2 "Tellstick ZWave" [refreshInterval=10000, publicKey="XXXXXXXX", privateKey="YYYYYY", token= "ZZZZZZZZ", tokenSecret="UUUUUUUUUU"] {
sensor OutsideSensor2 [protocol="fineoffset",model="temperaturehumidity",name="temperaturehumidity:120",deviceId="120_temperaturehumidity_fineoffset"]
}
```
### tellstick.items
```
Number OutsideSensor1_Temperture <temperature> { channel="tellstick:sensor:tellstickgateway:OutsideSensor1:temperature"}
Number OutsideSensor1_Humidity <humidity> { channel="tellstick:sensor:tellstickgateway:OutsideSensor1:humidity"}
Switch LivingTV_Power <screen> { channel="tellstick:switch:tellstickgateway:LivingTV:switch"}
Dimmer BedroomCeilingLamp1_Brightness <lightbulb> { channel="tellstick:dimmer:tellstickgateway:BedroomCeilingLamp1:dimmer"}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,116 @@
<?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.tellstick</artifactId>
<name>openHAB Add-ons :: Bundles :: Tellstick Binding</name>
<properties>
<bnd.importpackage>!com.luckycatlabs.*,!com.jcraft.jzlib.*,!org.apache.commons.cli.*,!org.eclipse.swt.*</bnd.importpackage>
<dep.noembedding>netty-transport-native-unix-common,netty-common,netty-transport,netty-transport-native-epoll,netty-buffer,netty-resolver,netty-codec,netty-codec-http,netty-handler</dep.noembedding>
</properties>
<dependencies>
<!-- JNA -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.5.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.tellstick</groupId>
<artifactId>javatellstick</artifactId>
<version>1.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId>
<version>2.0.19</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client-netty-utils</artifactId>
<version>2.0.19</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.typesafe.netty</groupId>
<artifactId>netty-reactive-streams</artifactId>
<version>2.0.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>4.1.42.Final</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.tellstick-${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-tellstick" description="Tellstick Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<feature>openhab-transport-serial</feature>
<feature dependency="true">openhab.tp-netty</feature>
<feature dependency="true">openhab.tp-jaxb</feature>
<bundle dependency="true">mvn:net.java.dev.jna/jna/4.5.2</bundle>
<bundle dependency="true">mvn:net.java.dev.jna/jna-platform/4.5.2</bundle>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.tellstick/${project.version}</bundle>
</feature>
</features>

View File

@@ -0,0 +1,38 @@
/**
* 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.tellstick.internal;
import org.tellstick.device.TellstickException;
/**
* {@link TelldusBindingException} is used when there is exception communicating with Telldus Live.
* This exception extends the Telldus Core exception.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusBindingException extends TellstickException {
private static final long serialVersionUID = 30671795474333158L;
private String msg;
public TelldusBindingException(String message) {
super(null, 0);
this.msg = message;
}
@Override
public String getMessage() {
return msg;
}
}

View File

@@ -0,0 +1,109 @@
/**
* 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.tellstick.internal;
import static org.openhab.core.library.unit.MetricPrefix.*;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.measure.Unit;
import javax.measure.quantity.Angle;
import javax.measure.quantity.Dimensionless;
import javax.measure.quantity.ElectricCurrent;
import javax.measure.quantity.Illuminance;
import javax.measure.quantity.Length;
import javax.measure.quantity.Power;
import javax.measure.quantity.Pressure;
import javax.measure.quantity.Speed;
import javax.measure.quantity.Temperature;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.SmartHomeUnits;
import org.openhab.core.thing.ThingTypeUID;
/**
* The {@link TellstickBinding} class defines common constants, which are
* used across the whole binding.
*
* @author jarlebh - Initial contribution
*/
@NonNullByDefault
public class TellstickBindingConstants {
public static final String BINDING_ID = "tellstick";
public static final Unit<Dimensionless> HUMIDITY_UNIT = SmartHomeUnits.PERCENT;
public static final Unit<Temperature> TEMPERATURE_UNIT = SIUnits.CELSIUS;
public static final Unit<Pressure> PRESSURE_UNIT = HECTO(SIUnits.PASCAL);
public static final Unit<Speed> WIND_SPEED_UNIT_MS = SmartHomeUnits.METRE_PER_SECOND;
public static final Unit<Angle> WIND_DIRECTION_UNIT = SmartHomeUnits.DEGREE_ANGLE;
public static final Unit<Length> RAIN_UNIT = MILLI(SIUnits.METRE);
public static final Unit<Illuminance> LUX_UNIT = SmartHomeUnits.LUX;
public static final Unit<ElectricCurrent> ELECTRIC_UNIT = SmartHomeUnits.AMPERE;
public static final Unit<Power> POWER_UNIT = KILO(SmartHomeUnits.WATT);
public static final String CONFIGPATH_ID = "location";
public static final String DEVICE_ID = "deviceId";
public static final String DEVICE_PROTOCOL = "protocol";
public static final String DEVICE_MODEL = "model";
public static final String DEVICE_NAME = "name";
public static final String DEVICE_RESEND_COUNT = "repeat";
public static final String DEVICE_ISDIMMER = "dimmer";
public static final String BRIDGE_TELLDUS_CORE = "telldus-core";
public static final String BRIDGE_TELLDUS_LIVE = "telldus-live";
public static final String DEVICE_SENSOR = "sensor";
public static final String DEVICE_WINDSENSOR = "windsensor";
public static final String DEVICE_RAINSENSOR = "rainsensor";
public static final String DEVICE_POWERSENSOR = "powersensor";
public static final String DEVICE_DIMMER = "dimmer";
public static final String DEVICE_SWITCH = "switch";
// List of all Thing Type UIDs
public static final ThingTypeUID DIMMER_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_DIMMER);
public static final ThingTypeUID SWITCH_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_SWITCH);
public static final ThingTypeUID SENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_SENSOR);
public static final ThingTypeUID RAINSENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_RAINSENSOR);
public static final ThingTypeUID POWERSENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_POWERSENSOR);
public static final ThingTypeUID WINDSENSOR_THING_TYPE = new ThingTypeUID(BINDING_ID, DEVICE_WINDSENSOR);
public static final ThingTypeUID TELLDUSBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_CORE);
public static final ThingTypeUID TELLDUSCOREBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_CORE);
public static final ThingTypeUID TELLDUSLIVEBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_LIVE);
// List of all Channel ids
public static final String CHANNEL_DIMMER = "dimmer";
public static final String CHANNEL_STATE = "state";
public static final String CHANNEL_HUMIDITY = "humidity";
public static final String CHANNEL_TIMESTAMP = "timestamp";
public static final String CHANNEL_TEMPERATURE = "temperature";
public static final String CHANNEL_RAINTOTAL = "raintotal";
public static final String CHANNEL_RAINRATE = "rainrate";
public static final String CHANNEL_WINDAVERAGE = "windaverage";
public static final String CHANNEL_WINDDIRECTION = "winddirection";
public static final String CHANNEL_WINDGUST = "windgust";
public static final String CHANNEL_WATT = "watt";
public static final String CHANNEL_AMPERE = "ampere";
public static final String CHANNEL_LUX = "lux";
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections.unmodifiableSet(
Stream.of(TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(DIMMER_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE,
WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE).collect(Collectors.toSet()));
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream
.of(DIMMER_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE,
POWERSENSOR_THING_TYPE, TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE)
.collect(Collectors.toSet()));
}

View File

@@ -0,0 +1,78 @@
/**
* 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.tellstick.internal;
import static org.openhab.binding.tellstick.internal.TellstickBindingConstants.*;
import java.util.Hashtable;
import org.openhab.binding.tellstick.internal.core.TelldusCoreBridgeHandler;
import org.openhab.binding.tellstick.internal.discovery.TellstickDiscoveryService;
import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler;
import org.openhab.binding.tellstick.internal.live.TelldusLiveBridgeHandler;
import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.thing.Bridge;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link TellstickHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Jarle Hjortland - Initial contribution
*/
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.tellstick")
public class TellstickHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(TellstickHandlerFactory.class);
private TellstickDiscoveryService discoveryService = null;
@Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
}
private void registerDeviceDiscoveryService(TelldusBridgeHandler tellstickBridgeHandler) {
if (discoveryService == null) {
discoveryService = new TellstickDiscoveryService(tellstickBridgeHandler);
discoveryService.activate();
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>());
} else {
discoveryService.addBridgeHandler(tellstickBridgeHandler);
}
}
@Override
protected ThingHandler createHandler(Thing thing) {
if (thing.getThingTypeUID().equals(TELLDUSCOREBRIDGE_THING_TYPE)) {
TelldusCoreBridgeHandler handler = new TelldusCoreBridgeHandler((Bridge) thing);
registerDeviceDiscoveryService(handler);
return handler;
} else if (thing.getThingTypeUID().equals(TELLDUSLIVEBRIDGE_THING_TYPE)) {
TelldusLiveBridgeHandler handler = new TelldusLiveBridgeHandler((Bridge) thing);
registerDeviceDiscoveryService(handler);
return handler;
} else if (supportsThingType(thing.getThingTypeUID())) {
return new TelldusDevicesHandler(thing);
} else {
logger.debug("ThingHandler not found for {}", thing.getThingTypeUID());
return null;
}
}
}

View File

@@ -0,0 +1,27 @@
/**
* 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.tellstick.internal;
/**
* Runtime exception in tellstick binding.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TellstickRuntimeException extends RuntimeException {
private static final long serialVersionUID = -1644730263645760297L;
public TellstickRuntimeException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,27 @@
/**
* 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.tellstick.internal.conf;
/**
* Configuration class for {@link TellstickBridge} bridge used to connect to the
* Tellus Live service.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusLiveConfiguration {
public String publicKey;
public String privateKey;
public String token;
public String tokenSecret;
public long refreshInterval;
}

View File

@@ -0,0 +1,24 @@
/**
* 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.tellstick.internal.conf;
/**
* Configuration class for {@link TellstickBridge} bridge used to connect to the
* Telldus Core service on the local machine.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TellstickBridgeConfiguration {
public int resendInterval;
public String libraryPath;
}

View File

@@ -0,0 +1,280 @@
/**
* 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.tellstick.internal.core;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import org.openhab.binding.tellstick.internal.conf.TellstickBridgeConfiguration;
import org.openhab.binding.tellstick.internal.handler.DeviceStatusListener;
import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.JNA;
import org.tellstick.device.SupportedMethodsException;
import org.tellstick.device.TellstickDevice;
import org.tellstick.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickEventHandler;
import org.tellstick.device.TellstickSensor;
import org.tellstick.device.TellstickSensorEvent;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.DeviceChangeListener;
import org.tellstick.device.iface.SensorListener;
import org.tellstick.enums.ChangeType;
import org.tellstick.enums.DataType;
/**
* {@link TelldusCoreBridgeHandler} is the handler for Telldus Core (Duo and Basic) and connects it
* to the framework. All {@link TelldusDevicesHandler}s use the
* {@link TelldusCoreDeviceController} to execute the actual commands.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusCoreBridgeHandler extends BaseBridgeHandler
implements DeviceChangeListener, SensorListener, TelldusBridgeHandler {
public TelldusCoreBridgeHandler(Bridge br) {
super(br);
}
private Logger logger = LoggerFactory.getLogger(TelldusCoreBridgeHandler.class);
private TelldusDeviceController deviceController = null;
private List<TellstickDevice> deviceList = new Vector<>();
private List<TellstickSensor> sensorList = new Vector<>();
private TellstickEventHandler eventHandler;
private static boolean initialized = false;
private List<DeviceStatusListener> deviceStatusListeners = new CopyOnWriteArrayList<>();
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
logger.debug("Refresh command received.");
rescanTelldusDevices();
} else {
logger.warn("No bridge commands defined.");
}
}
@Override
public void dispose() {
logger.debug("Telldus Core Handler disposed.");
if (deviceController != null) {
deviceController.dispose();
deviceController = null;
}
if (eventHandler != null) {
eventHandler.remove();
eventHandler = null;
}
clearDeviceList();
initialized = false;
JNA.CLibrary.INSTANCE.tdClose();
super.dispose();
}
private String init(String libraryPath) {
if (!initialized) {
if (libraryPath != null) {
logger.info("Loading {} from {}", JNA.nativeLibrary, libraryPath);
System.setProperty("jna.library.path", libraryPath);
} else {
logger.info("Loading {} from system default paths", JNA.nativeLibrary);
}
TellstickDevice.setSupportedMethods(JNA.CLibrary.TELLSTICK_BELL | JNA.CLibrary.TELLSTICK_TURNOFF
| JNA.CLibrary.TELLSTICK_TURNON | JNA.CLibrary.TELLSTICK_DIM);
JNA.CLibrary.INSTANCE.tdInit();
initialized = true;
}
return libraryPath;
}
@Override
public void initialize() {
logger.debug("Initializing Tellstick bridge handler.");
TellstickBridgeConfiguration configuration = getConfigAs(TellstickBridgeConfiguration.class);
init(configuration.libraryPath);
scheduler.submit(() -> {
rescanTelldusDevices();
setupListeners();
setupDeviceController(configuration);
updateStatus(ThingStatus.ONLINE);
});
updateStatus(ThingStatus.UNKNOWN);
}
private void setupDeviceController(TellstickBridgeConfiguration configuration) {
deviceController = new TelldusCoreDeviceController(configuration.resendInterval);
eventHandler.addListener((TelldusCoreDeviceController) deviceController);
}
@Override
public void rescanTelldusDevices() {
try {
deviceList = Collections.synchronizedList(TellstickDevice.getDevices());
for (TellstickDevice device : deviceList) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), device);
}
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceStateChanged(getThing(), device,
new TellstickDeviceEvent(device, null, null, null, System.currentTimeMillis()));
}
}
sensorList = Collections.synchronizedList(TellstickSensor.getAllSensors());
for (TellstickSensor sensor : sensorList) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
for (DeviceStatusListener listener : deviceStatusListeners) {
for (DataType type : sensor.getData().keySet()) {
listener.onDeviceStateChanged(getThing(), sensor,
new TellstickSensorEvent(sensor.getId(), sensor.getData(type), type,
sensor.getProtocol(), sensor.getModel(), System.currentTimeMillis()));
}
}
}
} catch (SupportedMethodsException e) {
logger.error("Failed to get devices ", e);
}
}
private synchronized void setupListeners() {
eventHandler = new TellstickEventHandler(deviceList);
eventHandler.addListener(this);
}
public void onConnectionLost() {
logger.debug("Bridge connection lost. Updating thing status to OFFLINE.");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
public void onConnection() {
logger.debug("Bridge connected. Updating thing status to ONLINE.");
updateStatus(ThingStatus.ONLINE);
}
@Override
public boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
if (deviceStatusListener == null) {
throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
}
return deviceStatusListeners.add(deviceStatusListener);
}
@Override
public boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
return deviceStatusListeners.remove(deviceStatusListener);
}
public void clearDeviceList() {
deviceList.clear();
sensorList.clear();
}
private Device getDevice(String id, List<TellstickDevice> devices) {
for (Device device : devices) {
if (device.getId() == Integer.valueOf(id)) {
return device;
}
}
return null;
}
@Override
public Device getDevice(String serialNumber) {
return getDevice(serialNumber, deviceList);
}
@Override
public void onRequest(TellstickSensorEvent newEvent) {
String uuid = TellstickSensor.createUUId(newEvent.getSensorId(), newEvent.getModel(), newEvent.getProtocol());
Device device = getSensor(uuid);
logger.debug("Sensor Event for {} event {}", device, newEvent);
if (device == null) {
TellstickSensor sensor = new TellstickSensor(newEvent.getSensorId(), newEvent.getProtocol(),
newEvent.getModel());
sensor.setData(newEvent.getDataType(), newEvent.getData());
sensorList.add(sensor);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
} else {
TellstickSensor useSensor = (TellstickSensor) device;
String currentValue = useSensor.getData(newEvent.getDataType());
Calendar compdate = Calendar.getInstance();
compdate.add(Calendar.MINUTE, -1);
logger.debug("Update curr {} new {}", currentValue, newEvent.getData());
if (currentValue == null || !currentValue.equals(newEvent.getData())
|| useSensor.getTimeStamp().before(compdate.getTime())) {
// Changed or more than 1 minute since update
useSensor.setData(newEvent.getDataType(), newEvent.getData());
useSensor.setTimeStamp(new Date(newEvent.getTimestamp()));
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceStateChanged(getThing(), useSensor, newEvent);
}
} else {
logger.trace("Ignored update {}", newEvent);
}
}
}
@Override
public void onRequest(TellstickDeviceEvent newEvent) {
if (newEvent.getChangeType() == ChangeType.ADDED) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), newEvent.getDevice());
}
} else if (newEvent.getChangeType() == ChangeType.REMOVED) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceRemoved(getThing(), newEvent.getDevice());
}
} else {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceStateChanged(getThing(), newEvent.getDevice(), newEvent);
}
}
}
@Override
public Device getSensor(String deviceUUId) {
for (Device device : sensorList) {
if (device.getUUId().equals(deviceUUId)) {
return device;
}
}
return null;
}
@Override
public TelldusDeviceController getController() {
return this.deviceController;
}
}

View File

@@ -0,0 +1,328 @@
/**
* 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.tellstick.internal.core;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;
import org.openhab.binding.tellstick.internal.TelldusBindingException;
import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.JNA;
import org.tellstick.device.TellstickDevice;
import org.tellstick.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickException;
import org.tellstick.device.TellstickSensorEvent;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.DeviceChangeListener;
import org.tellstick.device.iface.DimmableDevice;
import org.tellstick.device.iface.SensorListener;
import org.tellstick.device.iface.SwitchableDevice;
/**
* Device controller for telldus core (Basic and Duo).
* This communicates with the telldus DLL using the javatellstick
* library.
*
* @author Jarle Hjortland, Elias Gabrielsson - Initial contribution
*/
public class TelldusCoreDeviceController implements DeviceChangeListener, SensorListener, TelldusDeviceController {
private final Logger logger = LoggerFactory.getLogger(TelldusCoreDeviceController.class);
private long lastSend = 0;
long resendInterval = 100;
public static final long DEFAULT_INTERVAL_BETWEEN_SEND = 250;
private TelldusCoreWorker telldusCoreWorker;
private Thread workerThread;
private SortedMap<Device, TelldusCoreSendEvent> messageQue;
public TelldusCoreDeviceController(long resendInterval) {
this.resendInterval = resendInterval;
messageQue = Collections.synchronizedSortedMap(new TreeMap<>());
telldusCoreWorker = new TelldusCoreWorker(messageQue);
workerThread = new Thread(telldusCoreWorker);
}
@Override
public void dispose() {
workerThread.interrupt();
}
@Override
public void handleSendEvent(Device device, int resendCount, boolean isDimmer, Command command)
throws TellstickException {
if (!workerThread.isAlive()) {
workerThread.start();
}
Long eventTime = System.currentTimeMillis();
synchronized (messageQue) {
messageQue.put(device, new TelldusCoreSendEvent(device, resendCount, isDimmer, command, eventTime));
messageQue.notify();
}
}
@Override
public State calcState(Device dev) {
TellstickDevice device = (TellstickDevice) dev;
State st = null;
switch (device.getStatus()) {
case JNA.CLibrary.TELLSTICK_TURNON:
st = OnOffType.ON;
break;
case JNA.CLibrary.TELLSTICK_TURNOFF:
st = OnOffType.OFF;
break;
case JNA.CLibrary.TELLSTICK_DIM:
BigDecimal dimValue = new BigDecimal(device.getData());
if (dimValue.intValue() == 0) {
st = OnOffType.OFF;
} else if (dimValue.intValue() >= 255) {
st = OnOffType.ON;
} else {
st = OnOffType.ON;
}
break;
default:
logger.warn("Could not handle {} for {}", device.getStatus(), device);
}
return st;
}
@Override
public BigDecimal calcDimValue(Device device) {
BigDecimal dimValue = new BigDecimal(0);
switch (((TellstickDevice) device).getStatus()) {
case JNA.CLibrary.TELLSTICK_TURNON:
dimValue = new BigDecimal(100);
break;
case JNA.CLibrary.TELLSTICK_TURNOFF:
break;
case JNA.CLibrary.TELLSTICK_DIM:
dimValue = new BigDecimal(((TellstickDevice) device).getData());
dimValue = dimValue.multiply(new BigDecimal(100));
dimValue = dimValue.divide(new BigDecimal(255), 0, BigDecimal.ROUND_HALF_UP);
break;
default:
logger.warn("Could not handle {} for {}", ((TellstickDevice) device).getStatus(), device);
}
return dimValue;
}
public long getLastSend() {
return lastSend;
}
public void setLastSend(long currentTimeMillis) {
lastSend = currentTimeMillis;
}
@Override
public void onRequest(TellstickSensorEvent newDevices) {
setLastSend(newDevices.getTimestamp());
}
@Override
public void onRequest(TellstickDeviceEvent newDevices) {
setLastSend(newDevices.getTimestamp());
}
private void sendEvent(Device device, int resendCount, boolean isdimmer, Command command)
throws TellstickException {
for (int i = 0; i < resendCount; i++) {
checkLastAndWait(resendInterval);
logger.debug("Send {} to {} times={}", command, device, i);
if (device instanceof DimmableDevice) {
if (command == OnOffType.ON) {
turnOn(device);
} else if (command == OnOffType.OFF) {
turnOff(device);
} else if (command instanceof PercentType) {
dim(device, (PercentType) command);
} else if (command instanceof IncreaseDecreaseType) {
increaseDecrease(device, ((IncreaseDecreaseType) command));
}
} else if (device instanceof SwitchableDevice) {
if (command == OnOffType.ON) {
if (isdimmer) {
logger.debug("Turn off first in case it is allready on");
turnOff(device);
checkLastAndWait(resendInterval);
}
turnOn(device);
} else if (command == OnOffType.OFF) {
turnOff(device);
}
} else {
logger.warn("Cannot send to {}", device);
}
}
}
private void increaseDecrease(Device dev, IncreaseDecreaseType increaseDecreaseType) throws TellstickException {
String strValue = ((TellstickDevice) dev).getData();
double value = 0;
if (strValue != null) {
value = Double.valueOf(strValue);
}
int percent = (int) Math.round((value / 255) * 100);
if (IncreaseDecreaseType.INCREASE == increaseDecreaseType) {
percent = Math.min(percent + 10, 100);
} else if (IncreaseDecreaseType.DECREASE == increaseDecreaseType) {
percent = Math.max(percent - 10, 0);
}
dim(dev, new PercentType(percent));
}
private void dim(Device dev, PercentType command) throws TellstickException {
double value = command.doubleValue();
// 0 means OFF and 100 means ON
if (value == 0 && dev instanceof SwitchableDevice) {
((SwitchableDevice) dev).off();
} else if (value == 100 && dev instanceof SwitchableDevice) {
((SwitchableDevice) dev).on();
} else if (dev instanceof DimmableDevice) {
long tdVal = Math.round((value / 100) * 255);
((DimmableDevice) dev).dim((int) tdVal);
} else {
throw new TelldusBindingException("Cannot send DIM to " + dev);
}
}
private void turnOff(Device dev) throws TellstickException {
if (dev instanceof SwitchableDevice) {
((SwitchableDevice) dev).off();
} else {
throw new TelldusBindingException("Cannot send OFF to " + dev);
}
}
private void turnOn(Device dev) throws TellstickException {
if (dev instanceof SwitchableDevice) {
((SwitchableDevice) dev).on();
} else {
throw new TelldusBindingException("Cannot send ON to " + dev);
}
}
private void checkLastAndWait(long resendInterval) {
while ((System.currentTimeMillis() - lastSend) < resendInterval) {
logger.debug("Wait for {} millisec", resendInterval);
try {
Thread.sleep(resendInterval);
} catch (InterruptedException e) {
logger.error("Failed to sleep", e);
}
}
lastSend = System.currentTimeMillis();
}
/**
* This class is a worker which execute the commands sent to the TelldusCoreDeviceController.
* This enables separation between Telldus Core and openHAB for preventing latency on the bus.
* The Tellstick have an send pace of 4 Hz which is far slower then the bus itself.
*
* @author Elias Gabrielsson
*
*/
private class TelldusCoreWorker implements Runnable {
private SortedMap<Device, TelldusCoreSendEvent> messageQue;
public TelldusCoreWorker(SortedMap<Device, TelldusCoreSendEvent> messageQue) {
this.messageQue = messageQue;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
TelldusCoreSendEvent sendEvent;
// Get event to send
synchronized (messageQue) {
while (messageQue.isEmpty()) {
messageQue.wait();
}
sendEvent = messageQue.remove(messageQue.firstKey());
}
// Send event
try {
sendEvent(sendEvent.getDevice(), sendEvent.getResendCount(), sendEvent.getDimmer(),
sendEvent.getCommand());
} catch (TellstickException e) {
logger.error("Failed to send msg:{} to {}", sendEvent.getCommand(), sendEvent.getDevice(), e);
}
} catch (InterruptedException ie) {
break; // Terminate
}
}
}
}
/**
* This is a wrapper class to enable queuing of send events between the controller and the working thread.
*
* @author Elias Gabrielsson
*
*/
private class TelldusCoreSendEvent implements Comparable<TelldusCoreSendEvent> {
private Device device;
private int resendCount;
private boolean isDimmer;
private Command command;
private Long eventTime;
public TelldusCoreSendEvent(Device device, int resendCount, boolean isDimmer, Command command, Long eventTime) {
this.device = device;
this.resendCount = resendCount;
this.isDimmer = isDimmer;
this.command = command;
this.eventTime = eventTime;
}
public Device getDevice() {
return device;
}
public int getResendCount() {
return resendCount;
}
public boolean getDimmer() {
return isDimmer;
}
public Command getCommand() {
return command;
}
public Long getEventTime() {
return eventTime;
}
@Override
public int compareTo(TelldusCoreSendEvent o) {
return eventTime.compareTo(o.getEventTime());
}
}
}

View File

@@ -0,0 +1,106 @@
/**
* 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.tellstick.internal.discovery;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.openhab.binding.tellstick.internal.TellstickBindingConstants;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.config.discovery.DiscoveryService;
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;
import org.tellstick.device.TellstickController;
/**
* The {@link TellstickBridgeDiscovery} is responsible for discovering new Telldus gateway devices on the network
*
* @author Jarle Hjortland - Initial contribution
*
*/
@Component(service = DiscoveryService.class, immediate = true, configurationPid = "discovery.tellstick")
public class TellstickBridgeDiscovery extends AbstractDiscoveryService {
private final Logger logger = LoggerFactory.getLogger(TellstickBridgeDiscovery.class);
static boolean discoveryRunning = false;
static boolean initilized = false;
public TellstickBridgeDiscovery() {
super(TellstickBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS, 15);
}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return TellstickBindingConstants.SUPPORTED_BRIDGE_THING_TYPES_UIDS;
}
@Override
public void startScan() {
discoverController();
}
@Override
protected void startBackgroundDiscovery() {
discoverController();
}
@Override
public boolean isBackgroundDiscoveryEnabled() {
return true;
}
private synchronized void discoverController() {
if (!discoveryRunning) {
discoveryRunning = true;
listBridge();
}
}
private void listBridge() {
try {
List<TellstickController> cntrls = TellstickController.getControllers();
for (TellstickController contrl : cntrls) {
discoveryResultSubmission(contrl);
}
} catch (UnsatisfiedLinkError e) {
logger.error(
"Could not load telldus core, please make sure Telldus is installed and correct 32/64 bit java.",
e);
} catch (NoClassDefFoundError e) {
logger.error(
"Could not load telldus core, please make sure Telldus is installed and correct 32/64 bit java.",
e);
} finally {
// Close the port!
discoveryRunning = false;
}
}
private void discoveryResultSubmission(TellstickController controller) {
if (controller != null && controller.isOnline()) {
logger.trace("Adding new Telldus Controller {}", controller);
Map<String, Object> properties = new HashMap<>(2);
ThingUID uid = new ThingUID(TellstickBindingConstants.TELLDUSCOREBRIDGE_THING_TYPE,
Integer.toString(controller.getId()));
thingDiscovered(DiscoveryResultBuilder.create(uid).withProperties(properties)
.withLabel(controller.getType().name() + ": " + controller.getName()).build());
}
}
}

View File

@@ -0,0 +1,186 @@
/**
* 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.tellstick.internal.discovery;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import org.openhab.binding.tellstick.internal.TellstickBindingConstants;
import org.openhab.binding.tellstick.internal.handler.DeviceStatusListener;
import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
import org.openhab.binding.tellstick.internal.live.xml.LiveDataType;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor;
import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.ThingUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.JNA;
import org.tellstick.device.TellstickSensor;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.DimmableDevice;
import org.tellstick.device.iface.SwitchableDevice;
import org.tellstick.device.iface.TellstickEvent;
import org.tellstick.enums.DataType;
/**
* The {@link TellstickDiscoveryService} class is used to discover Tellstick
* devices that are connected to the Lan gateway.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TellstickDiscoveryService extends AbstractDiscoveryService implements DeviceStatusListener {
private static final long DEFAULT_TTL = 60 * 60; // 1 Hour
public TellstickDiscoveryService(int timeout) throws IllegalArgumentException {
super(timeout);
}
private final Logger logger = LoggerFactory.getLogger(TellstickDiscoveryService.class);
private List<TelldusBridgeHandler> telldusBridgeHandlers = new Vector<>();
public TellstickDiscoveryService(TelldusBridgeHandler telldusBridgeHandler) {
super(TellstickBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS, 10, true);
this.telldusBridgeHandlers.add(telldusBridgeHandler);
}
public void activate() {
for (TelldusBridgeHandler telldusBridgeHandler : telldusBridgeHandlers) {
telldusBridgeHandler.registerDeviceStatusListener(this);
}
}
@Override
public void deactivate() {
for (TelldusBridgeHandler telldusBridgeHandler : telldusBridgeHandlers) {
telldusBridgeHandler.unregisterDeviceStatusListener(this);
}
}
@Override
public Set<ThingTypeUID> getSupportedThingTypes() {
return TellstickBindingConstants.SUPPORTED_DEVICE_THING_TYPES_UIDS;
}
@Override
public void onDeviceAdded(Bridge bridge, Device device) {
logger.debug("Adding new TellstickDevice! '{}' with id '{}' and type '{}' to smarthome inbox", device,
device.getId(), device.getDeviceType());
ThingUID thingUID = getThingUID(bridge, device);
logger.debug("Detected thingUID: {}", thingUID);
if (thingUID != null) {
DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withTTL(DEFAULT_TTL)
.withProperty(TellstickBindingConstants.DEVICE_ID, device.getUUId())
.withProperty(TellstickBindingConstants.DEVICE_NAME, device.getName()).withBridge(bridge.getUID())
.withLabel(device.getDeviceType() + ": " + device.getName()).build();
thingDiscovered(discoveryResult);
} else {
logger.warn("Discovered Tellstick! device is unsupported: type '{}' with id '{}'", device.getDeviceType(),
device.getId());
}
}
@Override
protected void startScan() {
for (TelldusBridgeHandler telldusBridgeHandler : telldusBridgeHandlers) {
telldusBridgeHandler.rescanTelldusDevices();
}
}
@Override
public void onDeviceStateChanged(Bridge bridge, Device device, TellstickEvent event) {
// this can be ignored here
}
@Override
public void onDeviceRemoved(Bridge bridge, Device device) {
ThingUID thingUID = getThingUID(bridge, device);
if (thingUID != null) {
thingRemoved(thingUID);
} else {
logger.warn("Removed Tellstick! device is unsupported: type '{}' with id '{}'", device.getDeviceType(),
device.getId());
}
}
private ThingUID getThingUID(Bridge bridge, Device device) {
ThingUID thingUID = null;
switch (device.getDeviceType()) {
case SENSOR:
ThingTypeUID sensorThingId = findSensorType(device);
thingUID = new ThingUID(sensorThingId, bridge.getUID(), device.getUUId());
break;
case DEVICE:
if (device instanceof DimmableDevice) {
thingUID = new ThingUID(TellstickBindingConstants.DIMMER_THING_TYPE, bridge.getUID(),
device.getUUId());
} else if (device instanceof SwitchableDevice) {
thingUID = new ThingUID(TellstickBindingConstants.SWITCH_THING_TYPE, bridge.getUID(),
device.getUUId());
} else if (device instanceof TellstickNetDevice) {
if ((((TellstickNetDevice) device).getMethods() & JNA.CLibrary.TELLSTICK_DIM) > 0) {
thingUID = new ThingUID(TellstickBindingConstants.DIMMER_THING_TYPE, bridge.getUID(),
device.getUUId());
} else {
thingUID = new ThingUID(TellstickBindingConstants.SWITCH_THING_TYPE, bridge.getUID(),
device.getUUId());
}
}
break;
default:
break;
}
return thingUID;
}
private ThingTypeUID findSensorType(Device device) {
logger.debug("Device: {}", device);
ThingTypeUID sensorThingId;
if (device instanceof TellstickSensor) {
TellstickSensor sensor = (TellstickSensor) device;
logger.debug("Sensor: {}", device);
if (sensor.getData(DataType.WINDAVERAGE) != null || sensor.getData(DataType.WINDGUST) != null
|| sensor.getData(DataType.WINDDIRECTION) != null) {
sensorThingId = TellstickBindingConstants.WINDSENSOR_THING_TYPE;
} else if (sensor.getData(DataType.RAINTOTAL) != null || sensor.getData(DataType.RAINRATE) != null) {
sensorThingId = TellstickBindingConstants.RAINSENSOR_THING_TYPE;
} else {
sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE;
}
} else {
TellstickNetSensor sensor = (TellstickNetSensor) device;
if (sensor.isSensorOfType(LiveDataType.WINDAVERAGE) || sensor.isSensorOfType(LiveDataType.WINDDIRECTION)
|| sensor.isSensorOfType(LiveDataType.WINDGUST)) {
sensorThingId = TellstickBindingConstants.WINDSENSOR_THING_TYPE;
} else if (sensor.isSensorOfType(LiveDataType.RAINRATE) || sensor.isSensorOfType(LiveDataType.RAINTOTAL)) {
sensorThingId = TellstickBindingConstants.RAINSENSOR_THING_TYPE;
} else if (sensor.isSensorOfType(LiveDataType.WATT)) {
sensorThingId = TellstickBindingConstants.POWERSENSOR_THING_TYPE;
} else {
sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE;
}
}
return sensorThingId;
}
public void addBridgeHandler(TelldusBridgeHandler tellstickBridgeHandler) {
telldusBridgeHandlers.add(tellstickBridgeHandler);
tellstickBridgeHandler.registerDeviceStatusListener(this);
}
}

View File

@@ -0,0 +1,57 @@
/**
* 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.tellstick.internal.handler;
import org.openhab.core.thing.Bridge;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.TellstickEvent;
/**
* The {@link DeviceStatusListener} is notified when a device status has changed
* or a device has been removed or added.
*
* @author Jarle Hjortland - Initial contribution
*/
public interface DeviceStatusListener {
/**
* This method is called whenever the state of the given device has changed.
* The new state can be obtained by {@link FullLight#getState()}.
*
* @param bridge
* The Tellstick bridge the changed device is connected to.
* @param device
* The device which received the state update.
*/
public void onDeviceStateChanged(Bridge bridge, Device device, TellstickEvent deviceEvent);
/**
* This method us called whenever a device is removed.
*
* @param bridge
* The Tellstick bridge the removed device was connected to.
* @param device
* The device which is removed.
*/
public void onDeviceRemoved(Bridge bridge, Device device);
/**
* This method us called whenever a device is added.
*
* @param bridge
* The Tellstick bridge the added device was connected to.
* @param device
* The device which is added.
*/
public void onDeviceAdded(Bridge bridge, Device device);
}

View File

@@ -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.tellstick.internal.handler;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.types.Command;
import org.tellstick.device.iface.Device;
/**
* Interface for the telldus bridge modules
*
* @author Jarle Hjortland - Initial contribution
*/
public interface TelldusBridgeHandler {
/**
* TelldusDeviceController
* Add a status listener.
*
* @param deviceStatusListener
* @return
*/
boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener);
/**
* Remove a status listener.
*
* @param deviceStatusListener
* @return
*/
boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener);
/**
* Get a device from the bridgehandler.
*
* @param serialNumber
* @return
*/
Device getDevice(String serialNumber);
/**
* Get a sensor from the bridgehandler.
*
* @param serialNumber
* @return
*/
Device getSensor(String deviceUUId);
/**
* Tell the bridge to rescan for new devices.
*
*/
void rescanTelldusDevices();
/**
* Get the controller to communicate with devices.
*
* @return
*/
TelldusDeviceController getController();
/**
* Send a command to the controller.
*
* @param channelUID
* @param command
*/
void handleCommand(ChannelUID channelUID, Command command);
}

View File

@@ -0,0 +1,62 @@
/**
* 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.tellstick.internal.handler;
import java.math.BigDecimal;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.tellstick.device.TellstickException;
import org.tellstick.device.iface.Device;
/**
* Interface for telldus controllers. This is used to send and get status of devices from the controller.
*
* @author Jarle Hjortland - Initial contribution
*/
public interface TelldusDeviceController {
/**
* Send an event to the controller.
*
* @param device
* @param resendCount
* @param isdimmer
* @param command
* @throws TellstickException
*/
void handleSendEvent(Device device, int resendCount, boolean isdimmer, Command command) throws TellstickException;
/**
* Get the state of the given device.
*
* @param dev
* @return
*/
State calcState(Device dev);
/**
* Get the current dim state for a device.
*
* @param device
* @return
*/
BigDecimal calcDimValue(Device device);
/**
*
* Clean up the device controller before shutdown.
*
*/
void dispose();
}

View File

@@ -0,0 +1,377 @@
/**
* 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.tellstick.internal.handler;
import static org.openhab.binding.tellstick.internal.TellstickBindingConstants.*;
import java.math.BigDecimal;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import org.openhab.binding.tellstick.internal.TellstickBindingConstants;
import org.openhab.binding.tellstick.internal.live.xml.DataTypeValue;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensorEvent;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.thing.Bridge;
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.thing.ThingStatusInfo;
import org.openhab.core.thing.binding.BaseThingHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickException;
import org.tellstick.device.TellstickSensor;
import org.tellstick.device.TellstickSensorEvent;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.DimmableDevice;
import org.tellstick.device.iface.TellstickEvent;
import org.tellstick.enums.DataType;
import org.tellstick.enums.DeviceType;
/**
* Handler for telldus and tellstick devices. This sends the commands to the correct bridge.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusDevicesHandler extends BaseThingHandler implements DeviceStatusListener {
private Logger logger = LoggerFactory.getLogger(TelldusDevicesHandler.class);
private String deviceId;
private Boolean isDimmer = Boolean.FALSE;
private int resend = 1;
private TelldusBridgeHandler bridgeHandler = null;
private final ChannelUID stateChannel;
private final ChannelUID dimChannel;
private final ChannelUID humidityChannel;
private final ChannelUID tempChannel;
private final ChannelUID raintTotChannel;
private final ChannelUID rainRateChannel;
private final ChannelUID windAverageChannel;
private final ChannelUID windDirectionChannel;
private final ChannelUID windGuestChannel;
private final ChannelUID wattChannel;
private final ChannelUID ampereChannel;
private final ChannelUID luxChannel;
private final ChannelUID timestampChannel;
public TelldusDevicesHandler(Thing thing) {
super(thing);
stateChannel = new ChannelUID(getThing().getUID(), CHANNEL_STATE);
dimChannel = new ChannelUID(getThing().getUID(), CHANNEL_DIMMER);
humidityChannel = new ChannelUID(getThing().getUID(), CHANNEL_HUMIDITY);
tempChannel = new ChannelUID(getThing().getUID(), CHANNEL_TEMPERATURE);
raintTotChannel = new ChannelUID(getThing().getUID(), CHANNEL_RAINTOTAL);
rainRateChannel = new ChannelUID(getThing().getUID(), CHANNEL_RAINRATE);
windAverageChannel = new ChannelUID(getThing().getUID(), CHANNEL_WINDAVERAGE);
windDirectionChannel = new ChannelUID(getThing().getUID(), CHANNEL_WINDDIRECTION);
windGuestChannel = new ChannelUID(getThing().getUID(), CHANNEL_WINDGUST);
wattChannel = new ChannelUID(getThing().getUID(), CHANNEL_WATT);
ampereChannel = new ChannelUID(getThing().getUID(), CHANNEL_AMPERE);
timestampChannel = new ChannelUID(getThing().getUID(), CHANNEL_TIMESTAMP);
luxChannel = new ChannelUID(getThing().getUID(), CHANNEL_LUX);
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.debug("Handle event {} for {}", command, channelUID);
TelldusBridgeHandler bridgeHandler = getTellstickBridgeHandler();
if (bridgeHandler == null) {
logger.warn("Tellstick bridge handler not found. Cannot handle command without bridge.");
return;
}
Device dev = getDevice(bridgeHandler, deviceId);
if (dev == null) {
logger.warn("Device not found. Can't send command to device '{}'", deviceId);
return;
}
if (command instanceof RefreshType) {
getBridge().getHandler().handleCommand(channelUID, command);
refreshDevice(dev);
return;
}
if (channelUID.getId().equals(CHANNEL_DIMMER) || channelUID.getId().equals(CHANNEL_STATE)) {
try {
if (dev.getDeviceType() == DeviceType.DEVICE) {
getTellstickBridgeHandler().getController().handleSendEvent(dev, resend, isDimmer, command);
} else {
logger.warn("{} is not an updateable device. Read-only", dev);
}
} catch (TellstickException e) {
logger.debug("Failed to send command to tellstick", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
} catch (Exception e) {
logger.error("Failed to send command to tellstick", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
} else {
logger.warn("Setting of channel {} not possible. Read-only", channelUID);
}
}
private void refreshDevice(Device dev) {
if (deviceId != null && isSensor()) {
updateSensorStates(dev);
} else if (deviceId != null) {
updateDeviceState(dev);
}
}
@Override
public void initialize() {
Configuration config = getConfig();
logger.debug("Initialize TelldusDeviceHandler {}. class {}", config, config.getClass());
final Object configDeviceId = config.get(TellstickBindingConstants.DEVICE_ID);
if (configDeviceId != null) {
deviceId = configDeviceId.toString();
} else {
logger.debug("Initialized TellStick device missing serialNumber configuration... troubles ahead");
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR);
}
final Boolean isADimmer = (Boolean) config.get(TellstickBindingConstants.DEVICE_ISDIMMER);
if (isADimmer != null) {
this.isDimmer = isADimmer;
}
final BigDecimal repeatCount = (BigDecimal) config.get(TellstickBindingConstants.DEVICE_RESEND_COUNT);
if (repeatCount != null) {
resend = repeatCount.intValue();
}
if (getBridge() != null) {
bridgeStatusChanged(getBridge().getStatusInfo());
}
}
@Override
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
logger.debug("device: {} bridgeStatusChanged: {}", deviceId, bridgeStatusInfo);
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
try {
TelldusBridgeHandler tellHandler = (TelldusBridgeHandler) getBridge().getHandler();
logger.debug("Init bridge for {}, bridge:{}", deviceId, tellHandler);
if (tellHandler != null) {
this.bridgeHandler = tellHandler;
this.bridgeHandler.registerDeviceStatusListener(this);
Configuration config = editConfiguration();
Device dev = getDevice(tellHandler, deviceId);
if (dev != null) {
if (dev.getName() != null) {
config.put(TellstickBindingConstants.DEVICE_NAME, dev.getName());
}
if (dev.getProtocol() != null) {
config.put(TellstickBindingConstants.DEVICE_PROTOCOL, dev.getProtocol());
}
if (dev.getModel() != null) {
config.put(TellstickBindingConstants.DEVICE_MODEL, dev.getModel());
}
updateConfiguration(config);
updateStatus(ThingStatus.ONLINE);
} else {
logger.warn(
"Could not find {}, please make sure it is defined and that telldus service is running",
deviceId);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
}
} catch (Exception e) {
logger.error("Failed to init bridge for {}", deviceId, e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.HANDLER_INITIALIZING_ERROR);
}
} else {
updateStatus(ThingStatus.OFFLINE, bridgeStatusInfo.getStatusDetail());
}
}
private Device getDevice(TelldusBridgeHandler tellHandler, String deviceId) {
Device dev = null;
if (deviceId != null) {
if (isSensor()) {
dev = tellHandler.getSensor(deviceId);
} else {
dev = tellHandler.getDevice(deviceId);
updateDeviceState(dev);
}
}
return dev;
}
private boolean isSensor() {
return (getThing().getThingTypeUID().equals(TellstickBindingConstants.SENSOR_THING_TYPE)
|| getThing().getThingTypeUID().equals(TellstickBindingConstants.RAINSENSOR_THING_TYPE)
|| getThing().getThingTypeUID().equals(TellstickBindingConstants.WINDSENSOR_THING_TYPE)
|| getThing().getThingTypeUID().equals(TellstickBindingConstants.POWERSENSOR_THING_TYPE));
}
private void updateSensorStates(Device dev) {
if (dev instanceof TellstickSensor) {
updateStatus(ThingStatus.ONLINE);
for (DataType type : ((TellstickSensor) dev).getData().keySet()) {
updateSensorDataState(type, ((TellstickSensor) dev).getData(type));
}
} else if (dev instanceof TellstickNetSensor) {
if (((TellstickNetSensor) dev).getOnline()) {
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE);
}
for (DataTypeValue type : ((TellstickNetSensor) dev).getData()) {
updateSensorDataState(type);
}
}
}
private synchronized TelldusBridgeHandler getTellstickBridgeHandler() {
if (this.bridgeHandler == null) {
logger.debug("No available bridge handler found for {} bridge {} .", deviceId, getBridge());
}
return this.bridgeHandler;
}
@Override
public void onDeviceStateChanged(Bridge bridge, Device device, TellstickEvent event) {
logger.debug("Updating states of ({} {} ({}) id: {} or {}", device.getDeviceType(), device.getName(),
device.getUUId(), getThing().getUID(), deviceId);
if (device.getUUId().equals(deviceId)) {
if (event instanceof TellstickDeviceEvent) {
updateDeviceState(device);
} else if (event instanceof TellstickNetSensorEvent) {
TellstickNetSensorEvent sensorevent = (TellstickNetSensorEvent) event;
updateSensorDataState(sensorevent.getDataTypeValue());
} else if (event instanceof TellstickSensorEvent) {
TellstickSensorEvent sensorevent = (TellstickSensorEvent) event;
updateSensorDataState(sensorevent.getDataType(), sensorevent.getData());
} else {
logger.debug("Unhandled Device {}.", device.getDeviceType());
}
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(event.getTimestamp());
updateState(timestampChannel,
new DateTimeType(ZonedDateTime.ofInstant(cal.toInstant(), ZoneId.systemDefault())));
}
}
private void updateSensorDataState(DataType dataType, String data) {
switch (dataType) {
case HUMIDITY:
updateState(humidityChannel, new QuantityType<>(new BigDecimal(data), HUMIDITY_UNIT));
break;
case TEMPERATURE:
updateState(tempChannel, new QuantityType<>(new BigDecimal(data), SIUnits.CELSIUS));
break;
case RAINRATE:
updateState(rainRateChannel, new QuantityType<>(new BigDecimal(data), RAIN_UNIT));
break;
case RAINTOTAL:
updateState(raintTotChannel, new QuantityType<>(new BigDecimal(data), RAIN_UNIT));
break;
case WINDAVERAGE:
updateState(windAverageChannel, new QuantityType<>(new BigDecimal(data), WIND_SPEED_UNIT_MS));
break;
case WINDDIRECTION:
updateState(windDirectionChannel, new QuantityType<>(new BigDecimal(data), WIND_DIRECTION_UNIT));
break;
case WINDGUST:
updateState(windGuestChannel, new QuantityType<>(new BigDecimal(data), WIND_SPEED_UNIT_MS));
break;
default:
}
}
private void updateSensorDataState(DataTypeValue dataType) {
switch (dataType.getName()) {
case HUMIDITY:
updateState(humidityChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), HUMIDITY_UNIT));
break;
case TEMPERATURE:
updateState(tempChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), SIUnits.CELSIUS));
break;
case RAINRATE:
updateState(rainRateChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), RAIN_UNIT));
break;
case RAINTOTAL:
updateState(raintTotChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), RAIN_UNIT));
break;
case WINDAVERAGE:
updateState(windAverageChannel,
new QuantityType<>(new BigDecimal(dataType.getValue()), WIND_SPEED_UNIT_MS));
break;
case WINDDIRECTION:
updateState(windDirectionChannel,
new QuantityType<>(new BigDecimal(dataType.getValue()), WIND_DIRECTION_UNIT));
break;
case WINDGUST:
updateState(windGuestChannel,
new QuantityType<>(new BigDecimal(dataType.getValue()), WIND_SPEED_UNIT_MS));
break;
case WATT:
if (dataType.getUnit() != null && dataType.getUnit().equals("A")) {
updateState(ampereChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), ELECTRIC_UNIT));
} else {
updateState(wattChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), POWER_UNIT));
}
break;
case LUMINATION:
updateState(luxChannel, new QuantityType<>(new DecimalType(dataType.getValue()), LUX_UNIT));
break;
default:
}
}
private void updateDeviceState(Device device) {
if (device != null) {
logger.debug("Updating state of {} {} ({}) id: {}", device.getDeviceType(), device.getName(),
device.getUUId(), getThing().getUID());
TelldusBridgeHandler bridgeHandler = getTellstickBridgeHandler();
State st = null;
if (bridgeHandler != null && bridgeHandler.getController() != null) {
st = bridgeHandler.getController().calcState(device);
}
if (st != null && bridgeHandler != null) {
BigDecimal dimValue = bridgeHandler.getController().calcDimValue(device);
updateState(stateChannel, st);
if (device instanceof DimmableDevice) {
updateState(dimChannel, new PercentType(dimValue));
}
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
}
} else {
updateStatus(ThingStatus.REMOVED);
}
}
@Override
public void onDeviceRemoved(Bridge bridge, Device device) {
if (device.getUUId().equals(deviceId)) {
updateStatus(ThingStatus.REMOVED);
}
}
@Override
public void onDeviceAdded(Bridge bridge, Device device) {
}
}

View File

@@ -0,0 +1,323 @@
/**
* 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.tellstick.internal.live;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.openhab.binding.tellstick.internal.conf.TelldusLiveConfiguration;
import org.openhab.binding.tellstick.internal.handler.DeviceStatusListener;
import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler;
import org.openhab.binding.tellstick.internal.live.xml.DataTypeValue;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevices;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensorEvent;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensors;
import org.openhab.core.thing.Bridge;
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.thing.binding.BaseBridgeHandler;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickException;
import org.tellstick.device.iface.Device;
/**
* {@link TelldusLiveBridgeHandler} is the handler for Telldus Live service (Tellstick.NET and ZNET) and connects it
* to the framework. All {@link TelldusDevicesHandler}s use the
* {@link TelldusLiveDeviceController} to execute the actual commands.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusLiveBridgeHandler extends BaseBridgeHandler implements TelldusBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(TelldusLiveBridgeHandler.class);
private TellstickNetDevices deviceList = null;
private TellstickNetSensors sensorList = null;
private TelldusLiveDeviceController controller = new TelldusLiveDeviceController();
private List<DeviceStatusListener> deviceStatusListeners = new Vector<>();
private static final int REFRESH_DELAY = 10;
public TelldusLiveBridgeHandler(Bridge bridge) {
super(bridge);
}
private ScheduledFuture<?> pollingJob;
private ScheduledFuture<?> immediateRefreshJob;
@Override
public void dispose() {
logger.debug("Live Handler disposed.");
if (pollingJob != null) {
pollingJob.cancel(true);
}
if (this.controller != null) {
this.controller.dispose();
}
deviceList = null;
sensorList = null;
super.dispose();
}
@Override
public void initialize() {
logger.debug("Initializing TelldusLive bridge handler.");
TelldusLiveConfiguration configuration = getConfigAs(TelldusLiveConfiguration.class);
this.controller = new TelldusLiveDeviceController();
this.controller.connectHttpClient(configuration.publicKey, configuration.privateKey, configuration.token,
configuration.tokenSecret);
startAutomaticRefresh(configuration.refreshInterval);
refreshDeviceList();
updateStatus(ThingStatus.ONLINE);
}
private synchronized void startAutomaticRefresh(long refreshInterval) {
if (pollingJob != null && !pollingJob.isCancelled()) {
pollingJob.cancel(true);
}
pollingJob = scheduler.scheduleWithFixedDelay(this::refreshDeviceList, 0, refreshInterval,
TimeUnit.MILLISECONDS);
}
private void scheduleImmediateRefresh() {
// We schedule in 10 sec, to avoid multiple updates
logger.debug("Current remaining delay {}", pollingJob.getDelay(TimeUnit.SECONDS));
if (pollingJob.getDelay(TimeUnit.SECONDS) > REFRESH_DELAY) {
if (immediateRefreshJob == null || immediateRefreshJob.isDone()) {
immediateRefreshJob = scheduler.schedule(this::refreshDeviceList, REFRESH_DELAY, TimeUnit.SECONDS);
}
}
}
synchronized void refreshDeviceList() {
try {
updateDevices(deviceList);
updateSensors(sensorList);
updateStatus(ThingStatus.ONLINE);
} catch (TellstickException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
logger.error("Failed to update", e);
} catch (Exception e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
logger.error("Failed to update", e);
}
}
private synchronized void updateDevices(TellstickNetDevices previouslist) throws TellstickException {
TellstickNetDevices newList = controller.callRestMethod(TelldusLiveDeviceController.HTTP_TELLDUS_DEVICES,
TellstickNetDevices.class);
logger.debug("Device list {}", newList.getDevices());
if (newList.getDevices() != null) {
if (previouslist == null) {
logger.debug("updateDevices, Creating devices.");
for (TellstickNetDevice device : newList.getDevices()) {
device.setUpdated(true);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), device);
}
}
this.deviceList = newList;
} else {
logger.debug("updateDevices, Updating devices.");
for (TellstickNetDevice device : newList.getDevices()) {
int index = previouslist.getDevices().indexOf(device);
logger.debug("Device:{} found at {}", device, index);
if (index >= 0) {
TellstickNetDevice orgDevice = previouslist.getDevices().get(index);
if (device.getState() != orgDevice.getState()) {
orgDevice.setState(device.getState());
orgDevice.setStatevalue(device.getStatevalue());
orgDevice.setUpdated(true);
}
} else {
logger.debug("New Device - Adding:{}", device);
previouslist.getDevices().add(device);
device.setUpdated(true);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), device);
}
}
}
}
for (TellstickNetDevice device : deviceList.getDevices()) {
if (device.isUpdated()) {
logger.debug("Updated device:{}", device);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceStateChanged(getThing(), device,
new TellstickDeviceEvent(device, null, null, null, System.currentTimeMillis()));
}
device.setUpdated(false);
}
}
}
}
private synchronized void updateSensors(TellstickNetSensors previouslist) throws TellstickException {
TellstickNetSensors newList = controller.callRestMethod(TelldusLiveDeviceController.HTTP_TELLDUS_SENSORS,
TellstickNetSensors.class);
logger.debug("Updated sensors:{}", newList.getSensors());
if (newList.getSensors() != null) {
if (previouslist == null) {
logger.debug("First update of sensors");
this.sensorList = newList;
for (TellstickNetSensor sensor : sensorList.getSensors()) {
sensor.setUpdated(true);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
}
} else {
logger.debug("Update sensors, reset updated flag");
for (TellstickNetSensor sensor : previouslist.getSensors()) {
sensor.setUpdated(false);
}
logger.debug("Update sensors, reset updated flag1");
for (TellstickNetSensor sensor : newList.getSensors()) {
int index = this.sensorList.getSensors().indexOf(sensor);
if (index >= 0) {
TellstickNetSensor orgSensor = this.sensorList.getSensors().get(index);
logger.debug("Update sensor {}, prev update {}, new update {}", sensor.getId(),
orgSensor.getLastUpdated(), sensor.getLastUpdated());
if (sensor.getLastUpdated() > orgSensor.getLastUpdated()) {
logger.debug("Update for sensor:{}", sensor);
orgSensor.setData(sensor.getData());
orgSensor.setLastUpdated(sensor.getLastUpdated());
orgSensor.setUpdated(true);
sensor.setUpdated(true);
}
} else {
logger.debug("Adding sensor {}, new update {}", sensor.getId(), sensor.getLastUpdated());
this.sensorList.getSensors().add(sensor);
sensor.setUpdated(true);
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
}
}
}
for (TellstickNetSensor sensor : sensorList.getSensors()) {
if (sensor.getData() != null && sensor.isUpdated()) {
for (DeviceStatusListener listener : deviceStatusListeners) {
for (DataTypeValue type : sensor.getData()) {
listener.onDeviceStateChanged(getThing(), sensor,
new TellstickNetSensorEvent(sensor.getId(), type.getValue(), type,
sensor.getProtocol(), sensor.getModel(), System.currentTimeMillis()));
}
}
sensor.setUpdated(false);
}
}
}
}
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
if (command instanceof RefreshType) {
scheduleImmediateRefresh();
}
}
@Override
public void handleRemoval() {
super.handleRemoval();
}
@Override
public void handleUpdate(ChannelUID channelUID, State newState) {
super.handleUpdate(channelUID, newState);
}
@Override
public void thingUpdated(Thing thing) {
super.thingUpdated(thing);
}
@Override
public boolean registerDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
if (deviceStatusListener == null) {
throw new IllegalArgumentException("It's not allowed to pass a null deviceStatusListener.");
}
return deviceStatusListeners.add(deviceStatusListener);
}
@Override
public boolean unregisterDeviceStatusListener(DeviceStatusListener deviceStatusListener) {
return deviceStatusListeners.remove(deviceStatusListener);
}
private Device getDevice(String id, List<TellstickNetDevice> devices) {
for (Device device : devices) {
if (device.getId() == Integer.valueOf(id)) {
return device;
}
}
return null;
}
private Device getSensor(String id, List<TellstickNetSensor> sensors) {
for (Device sensor : sensors) {
if (sensor.getId() == Integer.valueOf(id)) {
return sensor;
}
}
return null;
}
@Override
public Device getDevice(String serialNumber) {
return getDevice(serialNumber, getDevices());
}
private List<TellstickNetDevice> getDevices() {
if (deviceList == null) {
refreshDeviceList();
}
return deviceList.getDevices();
}
@Override
public Device getSensor(String deviceUUId) {
Device result = null;
if (sensorList != null) {
result = getSensor(deviceUUId, sensorList.getSensors());
}
return result;
}
@Override
public void rescanTelldusDevices() {
this.deviceList = null;
this.sensorList = null;
refreshDeviceList();
}
@Override
public TelldusDeviceController getController() {
return controller;
}
}

View File

@@ -0,0 +1,328 @@
/**
* 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.tellstick.internal.live;
import java.math.BigDecimal;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.asynchttpclient.AsyncHttpClient;
import org.asynchttpclient.AsyncHttpClientConfig;
import org.asynchttpclient.DefaultAsyncHttpClient;
import org.asynchttpclient.DefaultAsyncHttpClientConfig;
import org.asynchttpclient.DefaultAsyncHttpClientConfig.Builder;
import org.asynchttpclient.Response;
import org.asynchttpclient.oauth.ConsumerKey;
import org.asynchttpclient.oauth.OAuthSignatureCalculator;
import org.asynchttpclient.oauth.RequestToken;
import org.openhab.binding.tellstick.internal.TelldusBindingException;
import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
import org.openhab.binding.tellstick.internal.live.xml.TelldusLiveResponse;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.types.Command;
import org.openhab.core.types.State;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tellstick.JNA;
import org.tellstick.device.TellstickDevice;
import org.tellstick.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickException;
import org.tellstick.device.TellstickSensorEvent;
import org.tellstick.device.iface.Device;
import org.tellstick.device.iface.DeviceChangeListener;
import org.tellstick.device.iface.SensorListener;
import org.tellstick.device.iface.SwitchableDevice;
/**
* {@link TelldusLiveDeviceController} is the communication with Telldus Live service (Tellstick.NET and ZNET)
* This controller uses XML based Rest API to communicate with Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusLiveDeviceController implements DeviceChangeListener, SensorListener, TelldusDeviceController {
private final Logger logger = LoggerFactory.getLogger(TelldusLiveDeviceController.class);
private long lastSend = 0;
public static final long DEFAULT_INTERVAL_BETWEEN_SEND = 250;
static final int REQUEST_TIMEOUT_MS = 5000;
private AsyncHttpClient client;
static final String HTTP_API_TELLDUS_COM_XML = "http://api.telldus.com/xml/";
static final String HTTP_TELLDUS_CLIENTS = HTTP_API_TELLDUS_COM_XML + "clients/list";
static final String HTTP_TELLDUS_DEVICES = HTTP_API_TELLDUS_COM_XML + "devices/list?supportedMethods=19";
static final String HTTP_TELLDUS_SENSORS = HTTP_API_TELLDUS_COM_XML
+ "sensors/list?includeValues=1&includeScale=1&includeUnit=1";
static final String HTTP_TELLDUS_SENSOR_INFO = HTTP_API_TELLDUS_COM_XML + "sensor/info";
static final String HTTP_TELLDUS_DEVICE_DIM = HTTP_API_TELLDUS_COM_XML + "device/dim?id=%d&level=%d";
static final String HTTP_TELLDUS_DEVICE_TURNOFF = HTTP_API_TELLDUS_COM_XML + "device/turnOff?id=%d";
static final String HTTP_TELLDUS_DEVICE_TURNON = HTTP_API_TELLDUS_COM_XML + "device/turnOn?id=%d";
private static final int MAX_RETRIES = 3;
public TelldusLiveDeviceController() {
}
@Override
public void dispose() {
try {
client.close();
} catch (Exception e) {
logger.error("Failed to close client", e);
}
}
void connectHttpClient(String publicKey, String privateKey, String token, String tokenSecret) {
ConsumerKey consumer = new ConsumerKey(publicKey, privateKey);
RequestToken user = new RequestToken(token, tokenSecret);
OAuthSignatureCalculator calc = new OAuthSignatureCalculator(consumer, user);
this.client = new DefaultAsyncHttpClient(createAsyncHttpClientConfig());
try {
this.client.setSignatureCalculator(calc);
Response response = client.prepareGet(HTTP_TELLDUS_CLIENTS).execute().get();
logger.debug("Response {} statusText {}", response.getResponseBody(), response.getStatusText());
} catch (InterruptedException | ExecutionException e) {
logger.error("Failed to connect", e);
}
}
private AsyncHttpClientConfig createAsyncHttpClientConfig() {
Builder builder = new DefaultAsyncHttpClientConfig.Builder();
builder.setConnectTimeout(REQUEST_TIMEOUT_MS);
return builder.build();
}
@Override
public void handleSendEvent(Device device, int resendCount, boolean isdimmer, Command command)
throws TellstickException {
logger.info("Send {} to {}", command, device);
if (device instanceof TellstickNetDevice) {
if (command == OnOffType.ON) {
turnOn(device);
} else if (command == OnOffType.OFF) {
turnOff(device);
} else if (command instanceof PercentType) {
dim(device, (PercentType) command);
} else if (command instanceof IncreaseDecreaseType) {
increaseDecrease(device, ((IncreaseDecreaseType) command));
}
} else if (device instanceof SwitchableDevice) {
if (command == OnOffType.ON) {
if (isdimmer) {
logger.debug("Turn off first in case it is allready on");
turnOff(device);
}
turnOn(device);
} else if (command == OnOffType.OFF) {
turnOff(device);
}
} else {
logger.warn("Cannot send to {}", device);
}
}
private void increaseDecrease(Device dev, IncreaseDecreaseType increaseDecreaseType) throws TellstickException {
String strValue = ((TellstickDevice) dev).getData();
double value = 0;
if (strValue != null) {
value = Double.valueOf(strValue);
}
int percent = (int) Math.round((value / 255) * 100);
if (IncreaseDecreaseType.INCREASE == increaseDecreaseType) {
percent = Math.min(percent + 10, 100);
} else if (IncreaseDecreaseType.DECREASE == increaseDecreaseType) {
percent = Math.max(percent - 10, 0);
}
dim(dev, new PercentType(percent));
}
private void dim(Device dev, PercentType command) throws TellstickException {
double value = command.doubleValue();
// 0 means OFF and 100 means ON
if (value == 0 && dev instanceof TellstickNetDevice) {
turnOff(dev);
} else if (value == 100 && dev instanceof TellstickNetDevice) {
turnOn(dev);
} else if (dev instanceof TellstickNetDevice
&& (((TellstickNetDevice) dev).getMethods() & JNA.CLibrary.TELLSTICK_DIM) > 0) {
long tdVal = Math.round((value / 100) * 255);
TelldusLiveResponse response = callRestMethod(String.format(HTTP_TELLDUS_DEVICE_DIM, dev.getId(), tdVal),
TelldusLiveResponse.class);
handleResponse((TellstickNetDevice) dev, response);
} else {
throw new TelldusBindingException("Cannot send DIM to " + dev);
}
}
private void turnOff(Device dev) throws TellstickException {
if (dev instanceof TellstickNetDevice) {
TelldusLiveResponse response = callRestMethod(String.format(HTTP_TELLDUS_DEVICE_TURNOFF, dev.getId()),
TelldusLiveResponse.class);
handleResponse((TellstickNetDevice) dev, response);
} else {
throw new TelldusBindingException("Cannot send OFF to " + dev);
}
}
private void handleResponse(TellstickNetDevice device, TelldusLiveResponse response) throws TellstickException {
if (response == null || (response.status == null && response.error == null)) {
throw new TelldusBindingException("No response " + response);
} else if (response.error != null) {
if (response.error.equals("The client for this device is currently offline")) {
device.setOnline(false);
device.setUpdated(true);
}
throw new TelldusBindingException("Error " + response.error);
} else if (!response.status.trim().equals("success")) {
throw new TelldusBindingException("Response " + response.status);
}
}
private void turnOn(Device dev) throws TellstickException {
if (dev instanceof TellstickNetDevice) {
TelldusLiveResponse response = callRestMethod(String.format(HTTP_TELLDUS_DEVICE_TURNON, dev.getId()),
TelldusLiveResponse.class);
handleResponse((TellstickNetDevice) dev, response);
} else {
throw new TelldusBindingException("Cannot send ON to " + dev);
}
}
@Override
public State calcState(Device dev) {
TellstickNetDevice device = (TellstickNetDevice) dev;
State st = null;
if (device.getOnline()) {
switch (device.getState()) {
case JNA.CLibrary.TELLSTICK_TURNON:
st = OnOffType.ON;
break;
case JNA.CLibrary.TELLSTICK_TURNOFF:
st = OnOffType.OFF;
break;
case JNA.CLibrary.TELLSTICK_DIM:
BigDecimal dimValue = new BigDecimal(device.getStatevalue());
if (dimValue.intValue() == 0) {
st = OnOffType.OFF;
} else if (dimValue.intValue() >= 255) {
st = OnOffType.ON;
} else {
st = OnOffType.ON;
}
break;
default:
logger.warn("Could not handle {} for {}", device.getState(), device);
}
}
return st;
}
@Override
public BigDecimal calcDimValue(Device device) {
BigDecimal dimValue = new BigDecimal(0);
switch (((TellstickNetDevice) device).getState()) {
case JNA.CLibrary.TELLSTICK_TURNON:
dimValue = new BigDecimal(100);
break;
case JNA.CLibrary.TELLSTICK_TURNOFF:
break;
case JNA.CLibrary.TELLSTICK_DIM:
dimValue = new BigDecimal(((TellstickNetDevice) device).getStatevalue());
dimValue = dimValue.multiply(new BigDecimal(100));
dimValue = dimValue.divide(new BigDecimal(255), 0, BigDecimal.ROUND_HALF_UP);
break;
default:
logger.warn("Could not handle {} for {}", (((TellstickNetDevice) device).getState()), device);
}
return dimValue;
}
public long getLastSend() {
return lastSend;
}
public void setLastSend(long currentTimeMillis) {
lastSend = currentTimeMillis;
}
@Override
public void onRequest(TellstickSensorEvent newDevices) {
setLastSend(newDevices.getTimestamp());
}
@Override
public void onRequest(TellstickDeviceEvent newDevices) {
setLastSend(newDevices.getTimestamp());
}
<T> T callRestMethod(String uri, Class<T> response) throws TelldusLiveException {
T resultObj = null;
try {
for (int i = 0; i < MAX_RETRIES; i++) {
try {
resultObj = innerCallRest(uri, response);
break;
} catch (TimeoutException e) {
logger.warn("TimeoutException error in get", e);
} catch (InterruptedException e) {
logger.warn("InterruptedException error in get", e);
}
}
} catch (JAXBException e) {
logger.warn("Encoding error in get", e);
logResponse(uri, e);
throw new TelldusLiveException(e);
} catch (XMLStreamException e) {
logger.warn("Communication error in get", e);
logResponse(uri, e);
throw new TelldusLiveException(e);
} catch (ExecutionException e) {
logger.warn("ExecutionException error in get", e);
throw new TelldusLiveException(e);
}
return resultObj;
}
private <T> T innerCallRest(String uri, Class<T> response) throws InterruptedException, ExecutionException,
TimeoutException, JAXBException, FactoryConfigurationError, XMLStreamException {
Future<Response> future = client.prepareGet(uri).execute();
Response resp = future.get(REQUEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
// TelldusLiveHandler.logger.info("Devices" + resp.getResponseBody());
JAXBContext jc = JAXBContext.newInstance(response);
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(resp.getResponseBodyAsStream());
// xsr = new PropertyRenamerDelegate(xsr);
@SuppressWarnings("unchecked")
T obj = (T) jc.createUnmarshaller().unmarshal(xsr);
if (logger.isTraceEnabled()) {
logger.trace("Request [{}] Response:{}", uri, resp.getResponseBody());
}
return obj;
}
private void logResponse(String uri, Exception e) {
if (e != null) {
logger.warn("Request [{}] Failure:{}", uri, e.getMessage());
}
}
}

View File

@@ -0,0 +1,36 @@
/**
* 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.tellstick.internal.live;
import org.tellstick.device.TellstickException;
/**
* {@link TelldusLiveException} is used when there is exception communicating with Telldus Live.
* This exception extends the Telldus Core exception.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TelldusLiveException extends TellstickException {
public TelldusLiveException(Exception source) {
super(null, 0);
this.initCause(source);
}
private static final long serialVersionUID = 3067179547449451158L;
@Override
public String getMessage() {
return getCause().getMessage();
}
}

View File

@@ -0,0 +1,76 @@
/**
* 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.tellstick.internal.live.xml;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlRootElement(name = "data")
public class DataTypeValue {
@XmlAttribute(name = "name")
@XmlJavaTypeAdapter(value = NameToDataType.class)
private LiveDataType dataType;
@XmlAttribute(name = "value")
private String data;
private String unit;
private Integer scale;
public LiveDataType getName() {
return dataType;
}
public void setName(LiveDataType dataType) {
this.dataType = dataType;
}
public String getValue() {
return data;
}
public void setValue(String data) {
this.data = data;
}
@XmlAttribute(name = "unit")
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@XmlAttribute(name = "scale")
public Integer getScale() {
return scale;
}
public void setScale(Integer scale) {
this.scale = scale;
}
@Override
public String toString() {
return "DataTypeValue [dataType=" + dataType + ", data=" + data + ", unit=" + unit + "]";
}
}

View File

@@ -0,0 +1,53 @@
/**
* 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.tellstick.internal.live.xml;
/**
* This enum is used to describe the value types in the Live API from telldus.
*
* @author Jarle Hjortland - Initial contribution
*/
public enum LiveDataType {
HUMIDITY("humidity"),
TEMPERATURE("temp"),
WINDAVERAGE("windaverage"),
WINDDIRECTION("winddirection"),
WINDGUST("windgust"),
RAINRATE("rainrate"),
RAINTOTAL("rainttotal"),
WATT("watt"),
LUMINATION("lum"),
UNKOWN("unkown");
private String name;
LiveDataType(String name) {
this.name = name;
}
public static LiveDataType fromName(String name) {
LiveDataType result = LiveDataType.UNKOWN;
for (LiveDataType m : LiveDataType.values()) {
if (m.name.equals(name)) {
result = m;
break;
}
}
return result;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,32 @@
/**
* 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.tellstick.internal.live.xml;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
public class NameToDataType extends XmlAdapter<String, LiveDataType> {
@Override
public LiveDataType unmarshal(String v) throws Exception {
return LiveDataType.fromName(v);
}
@Override
public String marshal(LiveDataType v) throws Exception {
return v.toString();
}
}

View File

@@ -0,0 +1,33 @@
/**
* 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.tellstick.internal.live.xml;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
public class NumberToBooleanMapper extends XmlAdapter<Integer, Boolean> {
@Override
public Boolean unmarshal(Integer v) throws Exception {
return v == 1 ? true : false;
}
@Override
public Integer marshal(Boolean v) throws Exception {
return v ? 1 : 0;
}
}

View File

@@ -0,0 +1,34 @@
/**
* 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.tellstick.internal.live.xml;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlRootElement(name = "device")
public class TelldusLiveResponse {
@XmlElement
public String status;
@XmlElement
public String error;
@Override
public String toString() {
return "TelldusLiveResponse [status=" + status + ", error=" + error + "]";
}
}

View File

@@ -0,0 +1,173 @@
/**
* 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.tellstick.internal.live.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.tellstick.device.iface.Device;
import org.tellstick.enums.DeviceType;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
public class TellstickNetDevice implements Device {
@XmlAttribute(name = "id")
int deviceId;
private String protocol;
private String model;
@XmlAttribute()
private String name;
@XmlAttribute()
@XmlJavaTypeAdapter(value = NumberToBooleanMapper.class)
private Boolean online;
@XmlAttribute
private int state;
@XmlAttribute
private String statevalue;
@XmlAttribute
private int methods;
private boolean updated;
public TellstickNetDevice() {
}
public TellstickNetDevice(int id) {
this.deviceId = id;
}
@Override
public int getId() {
return deviceId;
}
@Override
public String getUUId() {
return Integer.toString(deviceId);
}
@Override
public String getProtocol() {
return protocol;
}
@Override
public String getModel() {
return model;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.DEVICE;
}
@Override
public String getName() {
return name;
}
public void setId(int deviceId) {
this.deviceId = deviceId;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public void setModel(String model) {
this.model = model;
}
public void setName(String name) {
this.name = name;
}
public boolean getOnline() {
return online;
}
// @XmlJavaTypeAdapter(value = NumberToBooleanMapper.class)
public void setOnline(boolean online) {
this.online = online;
}
public void setUpdated(boolean b) {
this.updated = b;
}
public boolean isUpdated() {
return updated;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getStatevalue() {
return statevalue;
}
public void setStatevalue(String statevalue) {
this.statevalue = statevalue;
}
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + deviceId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TellstickNetDevice other = (TellstickNetDevice) obj;
if (deviceId != other.deviceId) {
return false;
}
return true;
}
public int getMethods() {
return methods;
}
public void setMethods(int methods) {
this.methods = methods;
}
@Override
public String toString() {
return "TellstickNetDevice [deviceId=" + deviceId + ", name=" + name + ", online=" + online + ", state=" + state
+ ", statevalue=" + statevalue + ", updated=" + updated + "]";
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.tellstick.internal.live.xml;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlRootElement(name = "devices")
public class TellstickNetDevices {
List<TellstickNetDevice> devices;
@XmlElement(name = "device")
public List<TellstickNetDevice> getDevices() {
return devices;
}
public void setDevices(List<TellstickNetDevice> devices) {
this.devices = devices;
}
}

View File

@@ -0,0 +1,189 @@
/**
* 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.tellstick.internal.live.xml;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.tellstick.device.iface.Device;
import org.tellstick.enums.DeviceType;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "sensor")
public class TellstickNetSensor implements Device {
@XmlAttribute(name = "id")
int deviceId;
@XmlAttribute()
private String protocol;
@XmlAttribute()
private String name;
@XmlAttribute()
@XmlJavaTypeAdapter(value = NumberToBooleanMapper.class)
private Boolean online;
@XmlElement(name = "data")
private List<DataTypeValue> data;
@XmlAttribute()
private Long lastUpdated;
private boolean updated;
@XmlAttribute()
private Long battery;
public TellstickNetSensor() {
}
public TellstickNetSensor(int id) {
this.deviceId = id;
}
@Override
public int getId() {
return deviceId;
}
@Override
public String getUUId() {
return Integer.toString(deviceId);
}
@Override
public String getProtocol() {
return protocol;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.SENSOR;
}
@Override
public String getName() {
return name;
}
public void setId(int deviceId) {
this.deviceId = deviceId;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
public void setName(String name) {
this.name = name;
}
public boolean getOnline() {
return online;
}
// @XmlJavaTypeAdapter(value = NumberToBooleanMapper.class)
public void setOnline(boolean online) {
this.online = online;
}
public List<DataTypeValue> getData() {
return data;
}
public void setData(List<DataTypeValue> data) {
this.data = data;
}
@Override
public String getModel() {
return null;
}
public Long getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(Long lastUpdated) {
this.lastUpdated = lastUpdated;
}
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = prime * result + deviceId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TellstickNetSensor other = (TellstickNetSensor) obj;
if (deviceId != other.deviceId) {
return false;
}
return true;
}
public void setUpdated(boolean b) {
this.updated = b;
}
public boolean isUpdated() {
return updated;
}
public boolean isSensorOfType(LiveDataType type) {
boolean res = false;
if (data != null) {
for (DataTypeValue val : data) {
if (val.getName() == type) {
res = true;
break;
}
}
}
return res;
}
public Long getBattery() {
return battery;
}
public void setBattery(Long battery) {
this.battery = battery;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("TellstickNetSensor [deviceId=").append(deviceId).append(", protocol=").append(protocol)
.append(", name=").append(name).append(", online=").append(online).append(", data=").append(data)
.append(", lastUpdated=").append(lastUpdated).append(", updated=").append(updated).append("]");
return builder.toString();
}
}

View File

@@ -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.tellstick.internal.live.xml;
import org.openhab.binding.tellstick.internal.TellstickRuntimeException;
import org.tellstick.device.TellstickSensorEvent;
import org.tellstick.device.iface.TellstickEvent;
import org.tellstick.enums.DataType;
/**
* This class is used for events for the telldus live sensors.
*
* @author Jarle Hjortland - Initial contribution
*/
public class TellstickNetSensorEvent extends TellstickSensorEvent implements TellstickEvent {
private DataTypeValue dataType;
public TellstickNetSensorEvent(int sensorId, String data, DataTypeValue dataValue, String protocol, String model,
long timeStamp) {
super(sensorId, data, null, protocol, model, timeStamp);
this.dataType = dataValue;
}
public DataTypeValue getDataTypeValue() {
return dataType;
}
@Override
public DataType getDataType() {
throw new TellstickRuntimeException("Should not call this method");
}
}

View File

@@ -0,0 +1,38 @@
/**
* 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.tellstick.internal.live.xml;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Class used to deserialize XML from Telldus Live.
*
* @author Jarle Hjortland - Initial contribution
*/
@XmlRootElement(name = "sensors")
public class TellstickNetSensors {
List<TellstickNetSensor> sensors;
@XmlElement(name = "sensor")
public List<TellstickNetSensor> getSensors() {
return sensors;
}
public void setSensors(List<TellstickNetSensor> devices) {
this.sensors = devices;
}
}

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<binding:binding id="tellstick" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
<name>Tellstick Binding</name>
<description>This is the binding for Telldus Tellstick Basic, Duo, .Net and Z-Net Lite.</description>
<author>Jarle Hjortland</author>
</binding:binding>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<config-description:config-descriptions
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0
https://openhab.org/schemas/config-description-1.0.0.xsd">
<config-description uri="thing-type:tellstick:sensor-config">
<parameter name="protocol" type="text">
<label>Protocol</label>
<description>The protocol used by a specific device.</description>
<required>false</required>
</parameter>
<parameter name="model" type="text">
<label>Model</label>
<description>The model used by a specific device.</description>
<required>false</required>
</parameter>
<parameter name="name" type="text">
<label>Name</label>
<description>The name of the device (manually entered)</description>
<required>false</required>
</parameter>
<parameter name="deviceId" type="text">
<label>DeviceID</label>
<description>This function returns the unique id of a device with a specific index.</description>
<required>true</required>
</parameter>
</config-description>
</config-description:config-descriptions>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tellstick"
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">
<bridge-type id="telldus-core">
<label>Telldus Core Gateway</label>
<description>This bridge represents the telldus center on a local computer.</description>
<config-description>
<parameter name="libraryPath" type="text" required="false">
<label>The Location of Telldus Core DLL/SO</label>
<description>The location of Telldus Core DLL/SO
</description>
<default>C:/Program Files/Telldus/;C:/Program Files (x86)/Telldus/</default>
</parameter>
<parameter name="resendInterval" type="integer" required="false">
<label>ResendInterval</label>
<description>The interval between resend.</description>
<default>100</default>
</parameter>
</config-description>
</bridge-type>
<bridge-type id="telldus-live">
<label>Telldus Live Gateway</label>
<description>This bridge represents the telldus live cloud service.</description>
<config-description>
<parameter name="privateKey" type="text" required="true">
<context>password</context>
<label>Private Key</label>
<description>The private key from telldus</description>
</parameter>
<parameter name="publicKey" type="text" required="true">
<context>credentials</context>
<label>Public Key</label>
<description>The public key from telldus</description>
</parameter>
<parameter name="token" type="text" required="true">
<context>credentials</context>
<label>Access Token</label>
<description>The openauth token.</description>
</parameter>
<parameter name="tokenSecret" type="text" required="true">
<context>password</context>
<label>Token Secret</label>
<description>The openauth token secret.</description>
</parameter>
<parameter name="refreshInterval" type="integer" required="false">
<label>Refresh Interval</label>
<description>The refresh interval in ms which is used to poll Telldus Live.
</description>
<default>60000</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tellstick"
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">
<!-- Tellstick Dimmer -->
<thing-type id="dimmer">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/>
</supported-bridge-type-refs>
<label>Dimmable Device</label>
<description>This is a Dimmable device</description>
<channels>
<channel id="dimmer" typeId="dimmer"/>
<channel id="state" typeId="state"/>
<channel id="timestamp" typeId="timestamp"/>
</channels>
<config-description>
<parameter name="protocol" type="text" required="false">
<label>Protocol</label>
<description>The protocol used by a specific device.</description>
<required>false</required>
</parameter>
<parameter name="name" type="text">
<label>Name</label>
<description>The name of the device</description>
<required>false</required>
</parameter>
<parameter name="deviceId" type="text">
<label>DeviceID</label>
<description>This is the unique id of a device.</description>
<required>true</required>
</parameter>
<parameter name="model" type="text">
<label>Model</label>
<description>The model used by a specific device.</description>
<required>false</required>
</parameter>
<parameter name="repeat" type="integer">
<label>Repeat</label>
<description>The number of times to resend.</description>
<required>false</required>
<default>2</default>
</parameter>
</config-description>
</thing-type>
<thing-type id="switch">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/>
</supported-bridge-type-refs>
<label>On/Off Device</label>
<description>This Thing defines a Switch Device</description>
<channels>
<channel id="state" typeId="state"/>
<channel id="timestamp" typeId="timestamp"/>
</channels>
<config-description>
<parameter name="protocol" type="text">
<label>Protocol</label>
<description>The protocol used by a specific device.</description>
<required>false</required>
</parameter>
<parameter name="name" type="text">
<label>Name</label>
<description>The name of the device</description>
<required>false</required>
</parameter>
<parameter name="deviceId" type="text">
<label>DeviceID</label>
<description>This is the unique id of a device.</description>
<required>true</required>
</parameter>
<parameter name="repeat" type="integer">
<label>Repeat</label>
<description>The number of times to resend.</description>
<required>false</required>
<default>2</default>
</parameter>
<parameter name="dimmer" type="boolean">
<label>Dimmer</label>
<description>Is this a dimmer without absolute setting (e.g. you press on to start dim and then on again to stop
it).</description>
<required>false</required>
<default>false</default>
</parameter>
</config-description>
</thing-type>
<channel-type id="dimmer">
<item-type>Dimmer</item-type>
<label>Dimmer Value</label>
<description>The channel to control the dimmer</description>
</channel-type>
<channel-type id="state">
<item-type>Switch</item-type>
<label>Switch</label>
<description>Turns the power on or off</description>
<category>Switch</category>
</channel-type>
<channel-type id="timestamp">
<item-type>DateTime</item-type>
<label>Last Device Update</label>
<description>Last device update</description>
</channel-type>
</thing:thing-descriptions>

View File

@@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<thing:thing-descriptions bindingId="tellstick"
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="sensor">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/>
</supported-bridge-type-refs>
<label>Sensor</label>
<description>This Thing defines a Sensor</description>
<channels>
<channel id="humidity" typeId="humidity"/>
<channel id="timestamp" typeId="timestamp"/>
<channel id="temperature" typeId="temperature"/>
<channel id="lux" typeId="lux"/>
</channels>
<config-description-ref uri="thing-type:tellstick:sensor-config"/>
</thing-type>
<thing-type id="rainsensor">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/>
</supported-bridge-type-refs>
<label>RainSensor</label>
<description>This Thing defines a Rain Sensor</description>
<channels>
<channel id="timestamp" typeId="timestamp"/>
<channel id="rainrate" typeId="rainrate"/>
<channel id="raintotal" typeId="raintotal"/>
</channels>
<config-description-ref uri="thing-type:tellstick:sensor-config"/>
</thing-type>
<thing-type id="powersensor">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-live"/>
</supported-bridge-type-refs>
<label>PowerSensor</label>
<description>This Thing defines a Power Sensor</description>
<channels>
<channel id="timestamp" typeId="timestamp"/>
<channel id="watt" typeId="watt"/>
<channel id="ampere" typeId="ampere"/>
</channels>
<config-description-ref uri="thing-type:tellstick:sensor-config"/>
</thing-type>
<thing-type id="windsensor">
<supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/>
</supported-bridge-type-refs>
<label>WindSensor</label>
<description>This Thing defines a Wind Sensor</description>
<channels>
<channel id="timestamp" typeId="timestamp"/>
<channel id="windgust" typeId="windgust"/>
<channel id="winddirection" typeId="winddirection"/>
<channel id="windaverage" typeId="windaverage"/>
</channels>
<config-description-ref uri="thing-type:tellstick:sensor-config"/>
</thing-type>
<channel-type id="temperature">
<item-type>Number:Temperature</item-type>
<label>Temperature</label>
<description>Actual measured room temperature</description>
<category>Temperature</category>
<state pattern="%.1f %unit%" readOnly="true">
</state>
</channel-type>
<channel-type id="humidity">
<item-type>Number:Dimensionless</item-type>
<label>Humidity</label>
<description>Actual measured room Humidity</description>
<category>Humidity</category>
<state pattern="%d %unit%" readOnly="true">
</state>
</channel-type>
<channel-type id="rainrate">
<item-type>Number:Length</item-type>
<label>Rainrate</label>
<description>The current rain rate</description>
<state pattern="%d %unit%" readOnly="true"/>
</channel-type>
<channel-type id="raintotal">
<item-type>Number:Length</item-type>
<label>Total Rain</label>
<description>Total rain</description>
<state pattern="%d %unit%" readOnly="true">
</state>
</channel-type>
<channel-type id="windgust">
<item-type>Number:Speed</item-type>
<label>Wind Gust</label>
<description>Current wind gust</description>
<state pattern="%.1f %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="windaverage">
<item-type>Number:Speed</item-type>
<label>Wind Average</label>
<description>Current average wind</description>
<state pattern="%.1f %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="winddirection">
<item-type>Number:Angle</item-type>
<label>Wind Direction</label>
<description>Current wind direction</description>
<category>Wind</category>
<state min="0" max="360" step="1" readOnly="true" pattern="%.1f %unit%"/>
</channel-type>
<channel-type id="watt">
<item-type>Number:Power</item-type>
<label>Watt</label>
<description>Current kWatt</description>
<state readOnly="true" pattern="%f %unit%">
</state>
</channel-type>
<channel-type id="lux">
<item-type>Number:Illuminance</item-type>
<label>Lux</label>
<description>Current lumination</description>
<state readOnly="true" pattern="%f %unit%"/>
</channel-type>
<channel-type id="ampere">
<item-type>Number:ElectricCurrent</item-type>
<label>Ampere</label>
<description>Current ampere</description>
<state pattern="%.1f %unit%" readOnly="true"></state>
</channel-type>
<channel-type id="timestamp">
<item-type>DateTime</item-type>
<label>Last Device Update</label>
<description>Last device update</description>
<state readOnly="true">
</state>
</channel-type>
</thing:thing-descriptions>