[tellstick] Fix for #9841, adding support for Tellstick local API. (#10020)

* Fix for #9841.

Signed-off-by: Jan Gustafsson <jannegpriv@gmail.com>
This commit is contained in:
Jan Gustafsson 2021-02-18 09:33:22 +01:00 committed by GitHub
parent 8a4b87e04e
commit 0853aa7cea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1317 additions and 68 deletions

View File

@ -12,6 +12,10 @@ The latest versions have also implemented Z-Wave as transmission protocol which
<img src="doc/tellstick_duo.jpg" alt="Tellstick Duo with device" width="300px"/> <img src="doc/tellstick_duo.jpg" alt="Tellstick Duo with device" width="300px"/>
</p> </p>
<p align="center">
<img src="doc/znet.jpeg" alt="Tellstick Znet lite v2" width="300px"/>
</p>
## Supported Things ## Supported Things
This binding supports the following thing types: This binding supports the following thing types:
@ -24,6 +28,7 @@ Additionally the binding have two types of bridge things which correspond to ava
* *Telldus Core Bridge* - Oldest API, used by USB devices. `telldus-core` * *Telldus Core Bridge* - Oldest API, used by USB devices. `telldus-core`
* *Telldus Live Bridge* - Telldus Cloud service, all devices with online access. `telldus-live` * *Telldus Live Bridge* - Telldus Cloud service, all devices with online access. `telldus-live`
* *Telldus Local Bridge* - Telldus Local API, Tellstick Net v2/Tellstick ZNet Lite v1/v2. `telldus-local`
***Switchbased sensors workaround*** ***Switchbased sensors workaround***
@ -32,11 +37,12 @@ Additionally the binding have two types of bridge things which correspond to ava
## Discovery ## Discovery
Devices which is added to *Telldus Core* and *Telldus Live* can be discovered by openHAB. Devices which is added to *Telldus Core*, *Telldus Live* and *Telldus Local* can be discovered by openHAB.
When you add this binding it will try to discover the *Telldus Core Bridge*. 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 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.
If you want to use the *Telldus Live* or *Telldus Local*, their bridges, *Telldus Live bridge* or *Tellstick Local*, needs to be added manually.
## Binding Configuration ## Binding Configuration
@ -54,13 +60,13 @@ Use the option `repeat` for that. Default resend count is 2.
### Bridges ### Bridges
Depending on your tellstick device type there is different ways of using this binding. Depending on your Tellstick device type there is different ways of using this binding.
The binding implements two different API: The binding implements three different APIs:
**1)** *Telldus Core* which is a local only interface supported by USB based device. <br> **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> **2)** *Telldus Live* which is a REST based cloud service maintained by Telldus.
**3)** *Telldus Local* which is a REST based local 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: Depending on your Tellstick model, different bridge-types are available:
@ -110,6 +116,36 @@ Optional:
- **refreshInterval:** How often we should contact *Telldus Live* to check for updates (in ms) - **refreshInterval:** How often we should contact *Telldus Live* to check for updates (in ms)
#### Telldus Local Bridge
To configure Telldus Local you need to know the local IP address of your Tellstick device and also request an access token.
Goto this page:
<https://tellstick-server.readthedocs.io/en/latest/api/authentication.html>
and follow steps 1), 2) and 3) to generate an access token.
In step 2) when you authenticate the application in your favorite browser, choose the options '1 year' and 'Auto renew access'.
Copy the 'token' returned in Step 3) and use that as accessToken in the local bridge config.
```
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImF1ZCI6IkV4YW1wbGUgYXBwIiwiZXhwIjoxNDUyOTUxNTYyfQ.eyJyZW5ldyI6dHJ1ZSwidHRsIjo4NjQwMH0.HeqoFM6-K5IuQa08Zr9HM9V2TKGRI9VxXlgdsutP7sg"
```
```
Bridge tellstick:telldus-local:3 "Tellstick Local ZWave" [ipAddress="x.y.z.w" , accesToken= "XYZ...W"]
```
Required:
- **ipAddress:** Local IP address of your Tellstick device
- **accessToken:** Access Token
Optional:
- **refreshInterval:** How often we should contact *Telldus Local* to check for updates (in ms)
## Channels ## Channels
Actuators (dimmer/switch) support the following channels: Actuators (dimmer/switch) support the following channels:
@ -194,6 +230,9 @@ Bridge tellstick:telldus-core:1 "Tellstick Duo" [resendInterval=200] {
Bridge tellstick:telldus-live:2 "Tellstick ZWave" [refreshInterval=10000, publicKey="XXXXXXXX", privateKey="YYYYYY", token= "ZZZZZZZZ", tokenSecret="UUUUUUUUUU"] { 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"] sensor OutsideSensor2 [protocol="fineoffset",model="temperaturehumidity",name="temperaturehumidity:120",deviceId="120_temperaturehumidity_fineoffset"]
} }
Bridge tellstick:telldus-local:3 "Tellstick Local ZWave" [ipAddress="192.168.50.17" , accesToken= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImF1ZCI6IkV4YW1wbGUgYXBwIiwiZXhwIjoxNDUyOTUxNTYyfQ.eyJyZW5ldyI6dHJ1ZSwidHRsIjo4NjQwMH0.HeqoFM6-K5IuQa08Zr9HM9V2TKGRI9VxXlgdsutP7sg"] {
sensor OutsideSensor3 [protocol="fineoffset",model="temperaturehumidity",name="temperaturehumidity:120",deviceId="120_temperaturehumidity_fineoffset"]
}
``` ```
### tellstick.items ### tellstick.items

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@ -14,10 +14,7 @@ package org.openhab.binding.tellstick.internal;
import static org.openhab.core.library.unit.MetricPrefix.*; import static org.openhab.core.library.unit.MetricPrefix.*;
import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.measure.Unit; import javax.measure.Unit;
import javax.measure.quantity.Angle; import javax.measure.quantity.Angle;
@ -65,6 +62,7 @@ public class TellstickBindingConstants {
public static final String DEVICE_ISDIMMER = "dimmer"; public static final String DEVICE_ISDIMMER = "dimmer";
public static final String BRIDGE_TELLDUS_CORE = "telldus-core"; public static final String BRIDGE_TELLDUS_CORE = "telldus-core";
public static final String BRIDGE_TELLDUS_LIVE = "telldus-live"; public static final String BRIDGE_TELLDUS_LIVE = "telldus-live";
public static final String BRIDGE_TELLDUS_LOCAL = "telldus-local";
public static final String DEVICE_SENSOR = "sensor"; public static final String DEVICE_SENSOR = "sensor";
public static final String DEVICE_WINDSENSOR = "windsensor"; public static final String DEVICE_WINDSENSOR = "windsensor";
public static final String DEVICE_RAINSENSOR = "rainsensor"; public static final String DEVICE_RAINSENSOR = "rainsensor";
@ -82,6 +80,7 @@ public class TellstickBindingConstants {
public static final ThingTypeUID TELLDUSBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_CORE); 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 TELLDUSCOREBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_CORE);
public static final ThingTypeUID TELLDUSLIVEBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_LIVE); public static final ThingTypeUID TELLDUSLIVEBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_LIVE);
public static final ThingTypeUID TELLDUSLOCALBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_LOCAL);
// List of all Channel ids // List of all Channel ids
public static final String CHANNEL_DIMMER = "dimmer"; public static final String CHANNEL_DIMMER = "dimmer";
public static final String CHANNEL_STATE = "state"; public static final String CHANNEL_STATE = "state";
@ -97,13 +96,11 @@ public class TellstickBindingConstants {
public static final String CHANNEL_AMPERE = "ampere"; public static final String CHANNEL_AMPERE = "ampere";
public static final String CHANNEL_LUX = "lux"; public static final String CHANNEL_LUX = "lux";
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections.unmodifiableSet( public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_THING_TYPES_UIDS = Set.of(TELLDUSCOREBRIDGE_THING_TYPE,
Stream.of(TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE).collect(Collectors.toSet())); TELLDUSLIVEBRIDGE_THING_TYPE);
public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Collections public static final Set<ThingTypeUID> SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(DIMMER_THING_TYPE,
.unmodifiableSet(Stream.of(DIMMER_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE);
WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE).collect(Collectors.toSet())); public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(DIMMER_THING_TYPE, SWITCH_THING_TYPE,
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.unmodifiableSet(Stream SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE,
.of(DIMMER_THING_TYPE, SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE, TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE, TELLDUSLOCALBRIDGE_THING_TYPE);
POWERSENSOR_THING_TYPE, TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE)
.collect(Collectors.toSet()));
} }

View File

@ -16,19 +16,24 @@ import static org.openhab.binding.tellstick.internal.TellstickBindingConstants.*
import java.util.Hashtable; import java.util.Hashtable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.tellstick.internal.core.TelldusCoreBridgeHandler; import org.openhab.binding.tellstick.internal.core.TelldusCoreBridgeHandler;
import org.openhab.binding.tellstick.internal.discovery.TellstickDiscoveryService; import org.openhab.binding.tellstick.internal.discovery.TellstickDiscoveryService;
import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler; import org.openhab.binding.tellstick.internal.handler.TelldusBridgeHandler;
import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler; import org.openhab.binding.tellstick.internal.handler.TelldusDevicesHandler;
import org.openhab.binding.tellstick.internal.live.TelldusLiveBridgeHandler; import org.openhab.binding.tellstick.internal.live.TelldusLiveBridgeHandler;
import org.openhab.binding.tellstick.internal.local.TelldusLocalBridgeHandler;
import org.openhab.core.config.discovery.DiscoveryService; import org.openhab.core.config.discovery.DiscoveryService;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.ThingTypeUID;
import org.openhab.core.thing.binding.BaseThingHandlerFactory; import org.openhab.core.thing.binding.BaseThingHandlerFactory;
import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandler;
import org.openhab.core.thing.binding.ThingHandlerFactory; import org.openhab.core.thing.binding.ThingHandlerFactory;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -37,11 +42,18 @@ import org.slf4j.LoggerFactory;
* handlers. * handlers.
* *
* @author Jarle Hjortland - Initial contribution * @author Jarle Hjortland - Initial contribution
* @author Jan Gustafsson - Adding support for local API
*/ */
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.tellstick") @Component(service = ThingHandlerFactory.class, configurationPid = "binding.tellstick")
public class TellstickHandlerFactory extends BaseThingHandlerFactory { public class TellstickHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(TellstickHandlerFactory.class); private final Logger logger = LoggerFactory.getLogger(TellstickHandlerFactory.class);
private TellstickDiscoveryService discoveryService = null; private TellstickDiscoveryService discoveryService = null;
private final HttpClient httpClient;
@Activate
public TellstickHandlerFactory(@Reference HttpClientFactory httpClientFactory) {
this.httpClient = httpClientFactory.getCommonHttpClient();
}
@Override @Override
public boolean supportsThingType(ThingTypeUID thingTypeUID) { public boolean supportsThingType(ThingTypeUID thingTypeUID) {
@ -68,6 +80,10 @@ public class TellstickHandlerFactory extends BaseThingHandlerFactory {
TelldusLiveBridgeHandler handler = new TelldusLiveBridgeHandler((Bridge) thing); TelldusLiveBridgeHandler handler = new TelldusLiveBridgeHandler((Bridge) thing);
registerDeviceDiscoveryService(handler); registerDeviceDiscoveryService(handler);
return handler; return handler;
} else if (thing.getThingTypeUID().equals(TELLDUSLOCALBRIDGE_THING_TYPE)) {
TelldusLocalBridgeHandler handler = new TelldusLocalBridgeHandler((Bridge) thing, httpClient);
registerDeviceDiscoveryService(handler);
return handler;
} else if (supportsThingType(thing.getThingTypeUID())) { } else if (supportsThingType(thing.getThingTypeUID())) {
return new TelldusDevicesHandler(thing); return new TelldusDevicesHandler(thing);
} else { } else {

View File

@ -14,7 +14,7 @@ package org.openhab.binding.tellstick.internal.conf;
/** /**
* Configuration class for {@link TellstickBridge} bridge used to connect to the * Configuration class for {@link TellstickBridge} bridge used to connect to the
* Tellus Live service. * Telldus Live service.
* *
* @author Jarle Hjortland - Initial contribution * @author Jarle Hjortland - Initial contribution
*/ */

View File

@ -0,0 +1,25 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.conf;
/**
* Configuration class for {@link TellstickBridge} bridge used to connect to the
* Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TelldusLocalConfiguration {
public String ipAddress;
public String accessToken;
public long refreshInterval;
}

View File

@ -22,6 +22,8 @@ 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.LiveDataType;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice; import org.openhab.binding.tellstick.internal.live.xml.TellstickNetDevice;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor; import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensor;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalDeviceDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorDTO;
import org.openhab.core.config.discovery.AbstractDiscoveryService; import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResult;
import org.openhab.core.config.discovery.DiscoveryResultBuilder; import org.openhab.core.config.discovery.DiscoveryResultBuilder;
@ -141,6 +143,14 @@ public class TellstickDiscoveryService extends AbstractDiscoveryService implemen
thingUID = new ThingUID(TellstickBindingConstants.SWITCH_THING_TYPE, bridge.getUID(), thingUID = new ThingUID(TellstickBindingConstants.SWITCH_THING_TYPE, bridge.getUID(),
device.getUUId()); device.getUUId());
} }
} else if (device instanceof TellstickLocalDeviceDTO) {
if ((((TellstickLocalDeviceDTO) 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; break;
default: default:
@ -163,7 +173,7 @@ public class TellstickDiscoveryService extends AbstractDiscoveryService implemen
} else { } else {
sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE; sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE;
} }
} else { } else if (device instanceof TellstickNetSensor) {
TellstickNetSensor sensor = (TellstickNetSensor) device; TellstickNetSensor sensor = (TellstickNetSensor) device;
if (sensor.isSensorOfType(LiveDataType.WINDAVERAGE) || sensor.isSensorOfType(LiveDataType.WINDDIRECTION) if (sensor.isSensorOfType(LiveDataType.WINDAVERAGE) || sensor.isSensorOfType(LiveDataType.WINDDIRECTION)
|| sensor.isSensorOfType(LiveDataType.WINDGUST)) { || sensor.isSensorOfType(LiveDataType.WINDGUST)) {
@ -175,6 +185,18 @@ public class TellstickDiscoveryService extends AbstractDiscoveryService implemen
} else { } else {
sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE; sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE;
} }
} else {
TellstickLocalSensorDTO sensor = (TellstickLocalSensorDTO) 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; return sensorThingId;
} }

View File

@ -23,12 +23,16 @@ import org.openhab.binding.tellstick.internal.TellstickBindingConstants;
import org.openhab.binding.tellstick.internal.live.xml.DataTypeValue; 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.TellstickNetSensor;
import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensorEvent; import org.openhab.binding.tellstick.internal.live.xml.TellstickNetSensorEvent;
import org.openhab.binding.tellstick.internal.local.dto.LocalDataTypeValueDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorEventDTO;
import org.openhab.core.config.core.Configuration; import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DateTimeType;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.SIUnits;
import org.openhab.core.library.unit.Units;
import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Bridge;
import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
@ -109,9 +113,15 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
return; return;
} }
if (command instanceof RefreshType) { if (command instanceof RefreshType) {
getBridge().getHandler().handleCommand(channelUID, command); Bridge bridge = getBridge();
refreshDevice(dev); if (bridge != null) {
return; TelldusBridgeHandler localBridgeHandler = (TelldusBridgeHandler) bridge.getHandler();
if (localBridgeHandler != null) {
localBridgeHandler.handleCommand(channelUID, command);
refreshDevice(dev);
return;
}
}
} }
if (channelUID.getId().equals(CHANNEL_DIMMER) || channelUID.getId().equals(CHANNEL_STATE)) { if (channelUID.getId().equals(CHANNEL_DIMMER) || channelUID.getId().equals(CHANNEL_STATE)) {
try { try {
@ -123,9 +133,6 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
} catch (TellstickException e) { } catch (TellstickException e) {
logger.debug("Failed to send command to tellstick", e); logger.debug("Failed to send command to tellstick", e);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); 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 { } else {
logger.warn("Setting of channel {} not possible. Read-only", channelUID); logger.warn("Setting of channel {} not possible. Read-only", channelUID);
@ -159,8 +166,9 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
if (repeatCount != null) { if (repeatCount != null) {
resend = repeatCount.intValue(); resend = repeatCount.intValue();
} }
if (getBridge() != null) { Bridge bridge = getBridge();
bridgeStatusChanged(getBridge().getStatusInfo()); if (bridge != null) {
bridgeStatusChanged(bridge.getStatusInfo());
} }
} }
@ -169,31 +177,34 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
logger.debug("device: {} bridgeStatusChanged: {}", deviceId, bridgeStatusInfo); logger.debug("device: {} bridgeStatusChanged: {}", deviceId, bridgeStatusInfo);
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) { if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
try { try {
TelldusBridgeHandler tellHandler = (TelldusBridgeHandler) getBridge().getHandler(); Bridge localBridge = getBridge();
logger.debug("Init bridge for {}, bridge:{}", deviceId, tellHandler); if (localBridge != null) {
if (tellHandler != null) { TelldusBridgeHandler telldusBridgeHandler = (TelldusBridgeHandler) localBridge.getHandler();
this.bridgeHandler = tellHandler; logger.debug("Init bridge for {}, bridge:{}", deviceId, telldusBridgeHandler);
this.bridgeHandler.registerDeviceStatusListener(this); if (telldusBridgeHandler != null) {
Configuration config = editConfiguration(); this.bridgeHandler = telldusBridgeHandler;
Device dev = getDevice(tellHandler, deviceId); this.bridgeHandler.registerDeviceStatusListener(this);
if (dev != null) { Configuration config = editConfiguration();
if (dev.getName() != null) { Device dev = getDevice(telldusBridgeHandler, deviceId);
config.put(TellstickBindingConstants.DEVICE_NAME, dev.getName()); if (dev != null) {
} if (dev.getName() != null) {
if (dev.getProtocol() != null) { config.put(TellstickBindingConstants.DEVICE_NAME, dev.getName());
config.put(TellstickBindingConstants.DEVICE_PROTOCOL, dev.getProtocol()); }
} if (dev.getProtocol() != null) {
if (dev.getModel() != null) { config.put(TellstickBindingConstants.DEVICE_PROTOCOL, dev.getProtocol());
config.put(TellstickBindingConstants.DEVICE_MODEL, dev.getModel()); }
} if (dev.getModel() != null) {
updateConfiguration(config); config.put(TellstickBindingConstants.DEVICE_MODEL, dev.getModel());
}
updateConfiguration(config);
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
} else { } else {
logger.warn( logger.warn(
"Could not find {}, please make sure it is defined and that telldus service is running", "Could not find {}, please make sure it is defined and that telldus service is running",
deviceId); deviceId);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
} }
} }
} catch (Exception e) { } catch (Exception e) {
@ -240,6 +251,10 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
for (DataTypeValue type : ((TellstickNetSensor) dev).getData()) { for (DataTypeValue type : ((TellstickNetSensor) dev).getData()) {
updateSensorDataState(type); updateSensorDataState(type);
} }
} else if (dev instanceof TellstickLocalSensorDTO) {
for (LocalDataTypeValueDTO type : ((TellstickLocalSensorDTO) dev).getData()) {
updateSensorDataState(type);
}
} }
} }
@ -260,6 +275,9 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
} else if (event instanceof TellstickNetSensorEvent) { } else if (event instanceof TellstickNetSensorEvent) {
TellstickNetSensorEvent sensorevent = (TellstickNetSensorEvent) event; TellstickNetSensorEvent sensorevent = (TellstickNetSensorEvent) event;
updateSensorDataState(sensorevent.getDataTypeValue()); updateSensorDataState(sensorevent.getDataTypeValue());
} else if (event instanceof TellstickLocalSensorEventDTO) {
TellstickLocalSensorEventDTO sensorevent = (TellstickLocalSensorEventDTO) event;
updateSensorDataState(sensorevent.getDataTypeValue());
} else if (event instanceof TellstickSensorEvent) { } else if (event instanceof TellstickSensorEvent) {
TellstickSensorEvent sensorevent = (TellstickSensorEvent) event; TellstickSensorEvent sensorevent = (TellstickSensorEvent) event;
updateSensorDataState(sensorevent.getDataType(), sensorevent.getData()); updateSensorDataState(sensorevent.getDataType(), sensorevent.getData());
@ -340,6 +358,46 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta
} }
} }
private void updateSensorDataState(LocalDataTypeValueDTO 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.getScale() == 5) {
updateState(ampereChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), ELECTRIC_UNIT));
} else if (dataType.getScale() == 2) {
updateState(wattChannel, new QuantityType<>(new BigDecimal(dataType.getValue()), Units.WATT));
}
break;
case LUMINATION:
updateState(luxChannel, new QuantityType<>(new DecimalType(dataType.getValue()), LUX_UNIT));
break;
default:
}
}
private void updateDeviceState(Device device) { private void updateDeviceState(Device device) {
if (device != null) { if (device != null) {
logger.debug("Updating state of {} {} ({}) id: {}", device.getDeviceType(), device.getName(), logger.debug("Updating state of {} {} ({}) id: {}", device.getDeviceType(), device.getName(),

View File

@ -20,11 +20,11 @@ package org.openhab.binding.tellstick.internal.live.xml;
public enum LiveDataType { public enum LiveDataType {
HUMIDITY("humidity"), HUMIDITY("humidity"),
TEMPERATURE("temp"), TEMPERATURE("temp"),
WINDAVERAGE("windaverage"), WINDAVERAGE("wavg"),
WINDDIRECTION("winddirection"), WINDDIRECTION("wdir"),
WINDGUST("windgust"), WINDGUST("wgust"),
RAINRATE("rainrate"), RAINRATE("rrate"),
RAINTOTAL("rainttotal"), RAINTOTAL("rtot"),
WATT("watt"), WATT("watt"),
LUMINATION("lum"), LUMINATION("lum"),
UNKOWN("unkown"); UNKOWN("unkown");

View File

@ -0,0 +1,290 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.tellstick.internal.conf.TelldusLocalConfiguration;
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.local.dto.LocalDataTypeValueDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalDeviceDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalDevicesDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorEventDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalSensorsDTO;
import org.openhab.core.cache.ExpiringCache;
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.device.TellstickDeviceEvent;
import org.tellstick.device.TellstickException;
import org.tellstick.device.iface.Device;
/**
* {@link TelldusLocalBridgeHandler} is the handler for Telldus Local API (Tellstick ZNET v1/v2) and connects it
* to the framework. All {@link TelldusDevicesHandler}s use the
* {@link TelldusLocalDeviceController} to execute the actual commands.
*
* @author Jan Gustafsson- Initial contribution
*/
public class TelldusLocalBridgeHandler extends BaseBridgeHandler implements TelldusBridgeHandler {
private final Logger logger = LoggerFactory.getLogger(TelldusLocalBridgeHandler.class);
private TellstickLocalDevicesDTO deviceList = null;
private TellstickLocalSensorsDTO sensorList = null;
private TelldusLocalDeviceController controller = null;
private List<DeviceStatusListener> deviceStatusListeners = Collections.synchronizedList(new ArrayList<>());
private final HttpClient httpClient;
private ScheduledFuture<?> pollingJob;
/**
* Use cache for refresh command to not update again when call is made within 10 seconds of previous call.
*/
private final ExpiringCache<Boolean> refreshCache = new ExpiringCache<>(Duration.ofSeconds(10),
this::refreshDeviceList);
public TelldusLocalBridgeHandler(Bridge bridge, HttpClient httpClient) {
super(bridge);
this.httpClient = httpClient;
}
@Override
public void initialize() {
TelldusLocalConfiguration configuration = getConfigAs(TelldusLocalConfiguration.class);
this.controller = new TelldusLocalDeviceController(configuration, httpClient);
pollingJob = scheduler.scheduleWithFixedDelay(this::refreshDeviceList, 11, configuration.refreshInterval,
TimeUnit.MILLISECONDS);
updateStatus(ThingStatus.UNKNOWN);
}
@Override
public void dispose() {
if (pollingJob != null) {
pollingJob.cancel(true);
}
if (this.controller != null) {
this.controller.dispose();
}
deviceList = null;
sensorList = null;
super.dispose();
}
private boolean refreshDeviceList() {
try {
updateDevices(deviceList);
updateSensors(sensorList);
updateStatus(ThingStatus.ONLINE);
return true;
} catch (TellstickException | InterruptedException e) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}
return false;
}
private synchronized void updateDevices(TellstickLocalDevicesDTO previouslist)
throws TellstickException, InterruptedException {
TellstickLocalDevicesDTO newList = controller
.callRestMethod(TelldusLocalDeviceController.HTTP_LOCAL_API_DEVICES, TellstickLocalDevicesDTO.class);
logger.debug("Device list {}", newList.getDevices());
if (newList.getDevices() != null) {
if (previouslist == null) {
for (TellstickLocalDeviceDTO device : newList.getDevices()) {
device.setUpdated(true);
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), device);
}
}
}
this.deviceList = newList;
} else {
for (TellstickLocalDeviceDTO device : newList.getDevices()) {
int index = previouslist.getDevices().indexOf(device);
logger.debug("Device:{} found at {}", device, index);
if (index >= 0) {
TellstickLocalDeviceDTO 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);
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), device);
}
}
}
}
}
for (TellstickLocalDeviceDTO device : deviceList.getDevices()) {
if (device.isUpdated()) {
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceStateChanged(getThing(), device,
new TellstickDeviceEvent(device, null, null, null, System.currentTimeMillis()));
}
}
device.setUpdated(false);
}
}
}
}
private synchronized void updateSensors(TellstickLocalSensorsDTO previouslist)
throws TellstickException, InterruptedException {
TellstickLocalSensorsDTO newList = controller
.callRestMethod(TelldusLocalDeviceController.HTTP_LOCAL_API_SENSORS, TellstickLocalSensorsDTO.class);
logger.debug("Updated sensors:{}", newList.getSensors());
if (newList.getSensors() != null) {
if (previouslist == null) {
this.sensorList = newList;
for (TellstickLocalSensorDTO sensor : sensorList.getSensors()) {
sensor.setUpdated(true);
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
}
}
} else {
for (TellstickLocalSensorDTO sensor : previouslist.getSensors()) {
sensor.setUpdated(false);
}
for (TellstickLocalSensorDTO sensor : newList.getSensors()) {
int index = this.sensorList.getSensors().indexOf(sensor);
if (index >= 0) {
TellstickLocalSensorDTO orgSensor = this.sensorList.getSensors().get(index);
orgSensor.setData(sensor.getData());
orgSensor.setUpdated(true);
sensor.setUpdated(true);
} else {
this.sensorList.getSensors().add(sensor);
sensor.setUpdated(true);
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
listener.onDeviceAdded(getThing(), sensor);
}
}
}
}
}
for (TellstickLocalSensorDTO sensor : sensorList.getSensors()) {
if (sensor.getData() != null && sensor.isUpdated()) {
synchronized (deviceStatusListeners) {
for (DeviceStatusListener listener : deviceStatusListeners) {
for (LocalDataTypeValueDTO type : sensor.getData()) {
listener.onDeviceStateChanged(getThing(), sensor,
new TellstickLocalSensorEventDTO(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) {
refreshCache.getValue();
}
}
@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<TellstickLocalDeviceDTO> devices) {
for (Device device : devices) {
if (device.getId() == Integer.valueOf(id)) {
return device;
}
}
return null;
}
private Device getSensor(String id, List<TellstickLocalSensorDTO> 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<TellstickLocalDeviceDTO> 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,282 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local;
import java.math.BigDecimal;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpMethod;
import org.openhab.binding.tellstick.internal.TelldusBindingException;
import org.openhab.binding.tellstick.internal.conf.TelldusLocalConfiguration;
import org.openhab.binding.tellstick.internal.handler.TelldusDeviceController;
import org.openhab.binding.tellstick.internal.local.dto.TelldusLocalResponseDTO;
import org.openhab.binding.tellstick.internal.local.dto.TellstickLocalDeviceDTO;
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;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
/**
* {@link TelldusLocalDeviceController} handles the communication with Telldus Local API (Tellstick ZNET v1/v2)
* This controller uses JSON based Rest API to communicate with Telldus Local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TelldusLocalDeviceController implements DeviceChangeListener, SensorListener, TelldusDeviceController {
private final Logger logger = LoggerFactory.getLogger(TelldusLocalDeviceController.class);
private long lastSend = 0;
public static final long DEFAULT_INTERVAL_BETWEEN_SEND_SEC = 250;
static final int REQUEST_TIMEOUT_MS = 5000;
private final HttpClient httpClient;
private final Gson gson = new Gson();
private String localApiUrl;
private String authorizationHeader = "Bearer ";
static final String HTTP_LOCAL_API = "api/";
static final String HTTP_LOCAL_API_DEVICES = HTTP_LOCAL_API + "devices/list?supportedMethods=19&includeIgnored=0";
static final String HTTP_LOCAL_API_SENSORS = HTTP_LOCAL_API
+ "sensors/list?includeValues=1&includeScale=1&includeUnit=1&includeIgnored=0";
static final String HTTP_LOCAL_API_SENSOR_INFO = HTTP_LOCAL_API + "sensor/info";
static final String HTTP_LOCAL_API_DEVICE_DIM = HTTP_LOCAL_API + "device/dim?id=%d&level=%d";
static final String HTTP_LOCAL_API_DEVICE_TURNOFF = HTTP_LOCAL_API + "device/turnOff?id=%d";
static final String HTTP_LOCAL_DEVICE_TURNON = HTTP_LOCAL_API + "device/turnOn?id=%d";
private static final int MAX_RETRIES = 3;
public TelldusLocalDeviceController(TelldusLocalConfiguration configuration, HttpClient httpClient) {
this.httpClient = httpClient;
localApiUrl = "http://" + configuration.ipAddress + "/";
authorizationHeader = authorizationHeader + configuration.accessToken;
}
@Override
public void dispose() {
}
@Override
public void handleSendEvent(Device device, int resendCount, boolean isdimmer, Command command)
throws TellstickException {
logger.debug("Send {} to {}", command, device);
try {
if (device instanceof TellstickLocalDeviceDTO) {
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.trace("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);
}
} catch (InterruptedException e) {
logger.debug("OH is shut-down.");
}
}
private void increaseDecrease(Device dev, IncreaseDecreaseType increaseDecreaseType)
throws TellstickException, InterruptedException {
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, InterruptedException {
double value = command.doubleValue();
// 0 means OFF and 100 means ON
if (value == 0 && dev instanceof TellstickLocalDeviceDTO) {
turnOff(dev);
} else if (value == 100 && dev instanceof TellstickLocalDeviceDTO) {
turnOn(dev);
} else if (dev instanceof TellstickLocalDeviceDTO
&& (((TellstickLocalDeviceDTO) dev).getMethods() & JNA.CLibrary.TELLSTICK_DIM) > 0) {
long tdVal = Math.round((value / 100) * 255);
TelldusLocalResponseDTO response = callRestMethod(
String.format(HTTP_LOCAL_API_DEVICE_DIM, dev.getId(), tdVal), TelldusLocalResponseDTO.class);
handleResponse((TellstickLocalDeviceDTO) dev, response);
} else {
throw new TelldusBindingException("Cannot send DIM to " + dev);
}
}
private void turnOff(Device dev) throws TellstickException, InterruptedException {
if (dev instanceof TellstickLocalDeviceDTO) {
TelldusLocalResponseDTO response = callRestMethod(String.format(HTTP_LOCAL_API_DEVICE_TURNOFF, dev.getId()),
TelldusLocalResponseDTO.class);
handleResponse((TellstickLocalDeviceDTO) dev, response);
} else {
throw new TelldusBindingException("Cannot send OFF to " + dev);
}
}
private void handleResponse(TellstickLocalDeviceDTO device, TelldusLocalResponseDTO response)
throws TellstickException {
if (response == null || (response.getStatus() == null && response.getError() == null)) {
throw new TelldusBindingException("No response " + response);
} else if (response.getError() != null) {
device.setUpdated(true);
throw new TelldusBindingException("Error " + response.getError());
} else if (!response.getStatus().trim().equals("success")) {
throw new TelldusBindingException("Response " + response.getStatus());
}
}
private void turnOn(Device dev) throws TellstickException, InterruptedException {
if (dev instanceof TellstickLocalDeviceDTO) {
TelldusLocalResponseDTO response = callRestMethod(String.format(HTTP_LOCAL_DEVICE_TURNON, dev.getId()),
TelldusLocalResponseDTO.class);
handleResponse((TellstickLocalDeviceDTO) dev, response);
} else {
throw new TelldusBindingException("Cannot send ON to " + dev);
}
}
@Override
public State calcState(Device dev) {
TellstickLocalDeviceDTO device = (TellstickLocalDeviceDTO) dev;
State st = null;
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 = BigDecimal.ZERO;
switch (((TellstickLocalDeviceDTO) 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(((TellstickLocalDeviceDTO) 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 {}", (((TellstickLocalDeviceDTO) 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 TelldusLocalException, InterruptedException {
T resultObj = null;
try {
for (int i = 0; i < MAX_RETRIES; i++) {
try {
resultObj = innerCallRest(localApiUrl + uri, response);
break;
} catch (TimeoutException e) {
logger.warn("TimeoutException error in get");
}
}
} catch (JsonSyntaxException e) {
throw new TelldusLocalException(e);
} catch (ExecutionException e) {
throw new TelldusLocalException(e);
}
return resultObj;
}
private <T> T innerCallRest(String uri, Class<T> json)
throws ExecutionException, InterruptedException, TimeoutException, JsonSyntaxException {
logger.trace("HTTP GET: {}", uri);
Request request = httpClient.newRequest(uri).method(HttpMethod.GET);
request.header("Authorization", authorizationHeader);
ContentResponse response = request.send();
String content = response.getContentAsString();
logger.trace("API response: {}", content);
return gson.fromJson(content, json);
}
}

View File

@ -0,0 +1,46 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.tellstick.device.TellstickException;
/**
* {@link TelldusLocalException} is used when there is exception communicating with Telldus local API.
* This exception extends the Telldus Core exception.
*
* @author Jan Gustafsson - Initial contribution
*/
@NonNullByDefault
public class TelldusLocalException extends TellstickException {
public TelldusLocalException(Exception source) {
super(null, 0);
this.initCause(source);
}
private static final long serialVersionUID = 3067179547449454711L;
@Override
public @NonNull String getMessage() {
Throwable throwable = getCause();
if (throwable != null) {
String localMessage = throwable.getMessage();
if (localMessage != null) {
return localMessage;
}
}
return "";
}
}

View File

@ -0,0 +1,51 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
import org.openhab.binding.tellstick.internal.live.xml.LiveDataType;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class LocalDataTypeValueDTO {
private String name;
private int scale;
private String value;
public LiveDataType getName() {
return LiveDataType.fromName(name);
}
public void setName(String name) {
this.name = name;
}
public int getScale() {
return scale;
}
public void setScale(int scale) {
this.scale = scale;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,40 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TelldusLocalResponseDTO {
private String error;
private String status;
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

View File

@ -0,0 +1,115 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
import org.tellstick.device.iface.Device;
import org.tellstick.enums.DeviceType;
import com.google.gson.annotations.SerializedName;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TellstickLocalDeviceDTO implements Device {
@SerializedName("id")
private int deviceId;
private int methods;
private String name;
private int state;
private String statevalue;
private String type;
private String protocol;
private String model;
private boolean updated;
public void setUpdated(boolean b) {
this.updated = b;
}
public boolean isUpdated() {
return updated;
}
@Override
public int getId() {
return deviceId;
}
public void setId(int deviceId) {
this.deviceId = deviceId;
}
public int getMethods() {
return methods;
}
public void setMethods(int methods) {
this.methods = methods;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@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;
}
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;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
import java.util.List;
import com.google.gson.annotations.SerializedName;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TellstickLocalDevicesDTO {
@SerializedName("device")
private List<TellstickLocalDeviceDTO> devices = null;
public List<TellstickLocalDeviceDTO> getDevices() {
return devices;
}
public void setDevices(List<TellstickLocalDeviceDTO> devices) {
this.devices = devices;
}
}

View File

@ -0,0 +1,130 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
import java.util.List;
import org.openhab.binding.tellstick.internal.live.xml.LiveDataType;
import org.tellstick.device.iface.Device;
import org.tellstick.enums.DeviceType;
import com.google.gson.annotations.SerializedName;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TellstickLocalSensorDTO implements Device {
private int battery;
private boolean updated;
private List<LocalDataTypeValueDTO> data = null;
@SerializedName("id")
private int deviceId;
private String model;
private String name;
private String protocol;
private int sensorId;
public int getBattery() {
return battery;
}
public void setBattery(int battery) {
this.battery = battery;
}
public List<LocalDataTypeValueDTO> getData() {
return data;
}
public void setData(List<LocalDataTypeValueDTO> data) {
this.data = data;
}
@Override
public int getId() {
return deviceId;
}
public void setId(int id) {
this.deviceId = id;
}
@Override
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String getProtocol() {
return protocol;
}
public void setProtocol(String protocol) {
this.protocol = protocol;
}
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 (LocalDataTypeValueDTO val : data) {
if (val.getName() == type) {
res = true;
break;
}
}
}
return res;
}
@Override
public DeviceType getDeviceType() {
return DeviceType.SENSOR;
}
public int getSensorId() {
return sensorId;
}
public void setSensorId(int sensorId) {
this.sensorId = sensorId;
}
@Override
public String getUUId() {
return Integer.toString(deviceId);
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
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 Jan Gustafsson - Initial contribution
*/
public class TellstickLocalSensorEventDTO extends TellstickSensorEvent implements TellstickEvent {
private LocalDataTypeValueDTO dataType;
public TellstickLocalSensorEventDTO(int sensorId, String data, LocalDataTypeValueDTO dataValue, String protocol,
String model, long timeStamp) {
super(sensorId, data, null, protocol, model, timeStamp);
this.dataType = dataValue;
}
public LocalDataTypeValueDTO getDataTypeValue() {
return dataType;
}
@Override
public DataType getDataType() {
throw new TellstickRuntimeException("Should not call this method");
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.tellstick.internal.local.dto;
import java.util.List;
import com.google.gson.annotations.SerializedName;
/**
* Class used to deserialize JSON from Telldus local API.
*
* @author Jan Gustafsson - Initial contribution
*/
public class TellstickLocalSensorsDTO {
@SerializedName("sensor")
private List<TellstickLocalSensorDTO> sensors = null;
public List<TellstickLocalSensorDTO> getSensors() {
return sensors;
}
public void setSensors(List<TellstickLocalSensorDTO> sensors) {
this.sensors = sensors;
}
}

View File

@ -6,7 +6,7 @@
<bridge-type id="telldus-core"> <bridge-type id="telldus-core">
<label>Telldus Core Gateway</label> <label>Telldus Core Gateway</label>
<description>This bridge represents the telldus center on a local computer.</description> <description>This bridge represents the Telldus center on a local computer.</description>
<config-description> <config-description>
<parameter name="libraryPath" type="text" required="false"> <parameter name="libraryPath" type="text" required="false">
@ -25,7 +25,7 @@
</bridge-type> </bridge-type>
<bridge-type id="telldus-live"> <bridge-type id="telldus-live">
<label>Telldus Live Gateway</label> <label>Telldus Live Gateway</label>
<description>This bridge represents the telldus live cloud service.</description> <description>This bridge represents the Telldus live cloud service.</description>
<config-description> <config-description>
<parameter name="privateKey" type="text" required="true"> <parameter name="privateKey" type="text" required="true">
@ -34,12 +34,10 @@
<description>The private key from telldus</description> <description>The private key from telldus</description>
</parameter> </parameter>
<parameter name="publicKey" type="text" required="true"> <parameter name="publicKey" type="text" required="true">
<context>credentials</context>
<label>Public Key</label> <label>Public Key</label>
<description>The public key from telldus</description> <description>The public key from telldus</description>
</parameter> </parameter>
<parameter name="token" type="text" required="true"> <parameter name="token" type="text" required="true">
<context>credentials</context>
<label>Access Token</label> <label>Access Token</label>
<description>The openauth token.</description> <description>The openauth token.</description>
</parameter> </parameter>
@ -48,7 +46,7 @@
<label>Token Secret</label> <label>Token Secret</label>
<description>The openauth token secret.</description> <description>The openauth token secret.</description>
</parameter> </parameter>
<parameter name="refreshInterval" type="integer" required="false"> <parameter name="refreshInterval" type="integer" required="false" min="0" unit="ms">
<label>Refresh Interval</label> <label>Refresh Interval</label>
<description>The refresh interval in ms which is used to poll Telldus Live. <description>The refresh interval in ms which is used to poll Telldus Live.
</description> </description>
@ -57,4 +55,27 @@
</config-description> </config-description>
</bridge-type> </bridge-type>
<bridge-type id="telldus-local">
<label>Telldus Local API</label>
<description>This bridge represents the Telldus local API.</description>
<config-description>
<parameter name="ipAddress" type="text" required="true">
<label>Local IP Address</label>
<description>The local IP address of the Tellstick.</description>
<context>network-address</context>
</parameter>
<parameter name="accessToken" type="text" required="true">
<label>Access Token</label>
<description>The access token.</description>
</parameter>
<parameter name="refreshInterval" type="integer" required="false" min="0" unit="ms">
<label>Refresh Interval</label>
<description>The refresh interval in ms which is used to poll Telldus local API.
</description>
<default>60000</default>
</parameter>
</config-description>
</bridge-type>
</thing:thing-descriptions> </thing:thing-descriptions>

View File

@ -9,6 +9,7 @@
<supported-bridge-type-refs> <supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/> <bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/> <bridge-type-ref id="telldus-live"/>
<bridge-type-ref id="telldus-local"/>
</supported-bridge-type-refs> </supported-bridge-type-refs>
<label>Dimmable Device</label> <label>Dimmable Device</label>

View File

@ -8,6 +8,7 @@
<supported-bridge-type-refs> <supported-bridge-type-refs>
<bridge-type-ref id="telldus-core"/> <bridge-type-ref id="telldus-core"/>
<bridge-type-ref id="telldus-live"/> <bridge-type-ref id="telldus-live"/>
<bridge-type-ref id="telldus-local"/>
</supported-bridge-type-refs> </supported-bridge-type-refs>
<label>Sensor</label> <label>Sensor</label>
@ -91,14 +92,14 @@
<item-type>Number:Length</item-type> <item-type>Number:Length</item-type>
<label>Rainrate</label> <label>Rainrate</label>
<description>The current rain rate</description> <description>The current rain rate</description>
<state pattern="%d %unit%" readOnly="true"/> <state pattern="%.1f %unit%" readOnly="true"/>
</channel-type> </channel-type>
<channel-type id="raintotal"> <channel-type id="raintotal">
<item-type>Number:Length</item-type> <item-type>Number:Length</item-type>
<label>Total Rain</label> <label>Total Rain</label>
<description>Total rain</description> <description>Total rain</description>
<state pattern="%d %unit%" readOnly="true"> <state pattern="%.1f %unit%" readOnly="true">
</state> </state>
</channel-type> </channel-type>
@ -126,9 +127,9 @@
<channel-type id="watt"> <channel-type id="watt">
<item-type>Number:Power</item-type> <item-type>Number:Power</item-type>
<label>Watt</label> <label>Power</label>
<description>Current kWatt</description> <description>Current power</description>
<state readOnly="true" pattern="%f %unit%"> <state readOnly="true" pattern="%.1f %unit%">
</state> </state>
</channel-type> </channel-type>