From 0853aa7ceac14fceaddda43c1d87538d2e378b75 Mon Sep 17 00:00:00 2001 From: Jan Gustafsson Date: Thu, 18 Feb 2021 09:33:22 +0100 Subject: [PATCH] [tellstick] Fix for #9841, adding support for Tellstick local API. (#10020) * Fix for #9841. Signed-off-by: Jan Gustafsson --- .../org.openhab.binding.tellstick/README.md | 53 +++- .../doc/znet.jpeg | Bin 0 -> 9764 bytes .../internal/TellstickBindingConstants.java | 21 +- .../internal/TellstickHandlerFactory.java | 16 + .../conf/TelldusLiveConfiguration.java | 2 +- .../conf/TelldusLocalConfiguration.java | 25 ++ .../discovery/TellstickDiscoveryService.java | 24 +- .../handler/TelldusDevicesHandler.java | 122 ++++++-- .../internal/live/xml/LiveDataType.java | 10 +- .../local/TelldusLocalBridgeHandler.java | 290 ++++++++++++++++++ .../local/TelldusLocalDeviceController.java | 282 +++++++++++++++++ .../internal/local/TelldusLocalException.java | 46 +++ .../local/dto/LocalDataTypeValueDTO.java | 51 +++ .../local/dto/TelldusLocalResponseDTO.java | 40 +++ .../local/dto/TellstickLocalDeviceDTO.java | 115 +++++++ .../local/dto/TellstickLocalDevicesDTO.java | 36 +++ .../local/dto/TellstickLocalSensorDTO.java | 130 ++++++++ .../dto/TellstickLocalSensorEventDTO.java | 43 +++ .../local/dto/TellstickLocalSensorsDTO.java | 36 +++ .../main/resources/OH-INF/thing/bridge.xml | 31 +- .../main/resources/OH-INF/thing/devices.xml | 1 + .../main/resources/OH-INF/thing/sensor.xml | 11 +- 22 files changed, 1317 insertions(+), 68 deletions(-) create mode 100644 bundles/org.openhab.binding.tellstick/doc/znet.jpeg create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLocalConfiguration.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalBridgeHandler.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalDeviceController.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalException.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/LocalDataTypeValueDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TelldusLocalResponseDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDeviceDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDevicesDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorEventDTO.java create mode 100644 bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorsDTO.java diff --git a/bundles/org.openhab.binding.tellstick/README.md b/bundles/org.openhab.binding.tellstick/README.md index 81f542e9f78..72e2ba7e5e2 100644 --- a/bundles/org.openhab.binding.tellstick/README.md +++ b/bundles/org.openhab.binding.tellstick/README.md @@ -12,6 +12,10 @@ The latest versions have also implemented Z-Wave as transmission protocol which Tellstick Duo with device

+

+Tellstick Znet lite v2 +

+ ## Supported Things 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 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*** @@ -32,11 +37,12 @@ Additionally the binding have two types of bridge things which correspond to ava ## 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*. 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 @@ -54,13 +60,13 @@ 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: +Depending on your Tellstick device type there is different ways of using this binding. +The binding implements three different APIs: **1)** *Telldus Core* which is a local only interface supported by USB based device.
-**2)** *Telldus Live* which is a REST based cloud service maintained by Telldus.
+**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. +
-> Not implemented yet but supported by some new devices, contributions are welcome. [API documention.](https://api.telldus.net/localapi/api.html)
-> **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: @@ -110,6 +116,36 @@ Optional: - **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: + +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 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"] { 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 diff --git a/bundles/org.openhab.binding.tellstick/doc/znet.jpeg b/bundles/org.openhab.binding.tellstick/doc/znet.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..8d324d55a25b15d6e0a8b8f1cdb2f9ecf4104e11 GIT binary patch literal 9764 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 SUPPORTED_BRIDGE_THING_TYPES_UIDS = Collections.unmodifiableSet( - Stream.of(TELLDUSCOREBRIDGE_THING_TYPE, TELLDUSLIVEBRIDGE_THING_TYPE).collect(Collectors.toSet())); - public static final Set 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 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())); + public static final Set SUPPORTED_BRIDGE_THING_TYPES_UIDS = Set.of(TELLDUSCOREBRIDGE_THING_TYPE, + TELLDUSLIVEBRIDGE_THING_TYPE); + public static final Set SUPPORTED_DEVICE_THING_TYPES_UIDS = Set.of(DIMMER_THING_TYPE, + SWITCH_THING_TYPE, SENSOR_THING_TYPE, RAINSENSOR_THING_TYPE, WINDSENSOR_THING_TYPE, POWERSENSOR_THING_TYPE); + public static final Set SUPPORTED_THING_TYPES_UIDS = Set.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, TELLDUSLOCALBRIDGE_THING_TYPE); } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java index 3897fcee9bd..266e7c8bd3d 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickHandlerFactory.java @@ -16,19 +16,24 @@ import static org.openhab.binding.tellstick.internal.TellstickBindingConstants.* import java.util.Hashtable; +import org.eclipse.jetty.client.HttpClient; 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.binding.tellstick.internal.local.TelldusLocalBridgeHandler; 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.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.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,11 +42,18 @@ import org.slf4j.LoggerFactory; * handlers. * * @author Jarle Hjortland - Initial contribution + * @author Jan Gustafsson - Adding support for local API */ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.tellstick") public class TellstickHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(TellstickHandlerFactory.class); private TellstickDiscoveryService discoveryService = null; + private final HttpClient httpClient; + + @Activate + public TellstickHandlerFactory(@Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { @@ -68,6 +80,10 @@ public class TellstickHandlerFactory extends BaseThingHandlerFactory { TelldusLiveBridgeHandler handler = new TelldusLiveBridgeHandler((Bridge) thing); registerDeviceDiscoveryService(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())) { return new TelldusDevicesHandler(thing); } else { diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLiveConfiguration.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLiveConfiguration.java index 32528e7c115..e334c0b9fa9 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLiveConfiguration.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLiveConfiguration.java @@ -14,7 +14,7 @@ package org.openhab.binding.tellstick.internal.conf; /** * Configuration class for {@link TellstickBridge} bridge used to connect to the - * Tellus Live service. + * Telldus Live service. * * @author Jarle Hjortland - Initial contribution */ diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLocalConfiguration.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLocalConfiguration.java new file mode 100644 index 00000000000..61e315ad0b9 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/conf/TelldusLocalConfiguration.java @@ -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; +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java index 424e805fdc3..59ab0403784 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/discovery/TellstickDiscoveryService.java @@ -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.TellstickNetDevice; 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.DiscoveryResult; 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(), 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; default: @@ -163,7 +173,7 @@ public class TellstickDiscoveryService extends AbstractDiscoveryService implemen } else { sensorThingId = TellstickBindingConstants.SENSOR_THING_TYPE; } - } else { + } else if (device instanceof TellstickNetSensor) { TellstickNetSensor sensor = (TellstickNetSensor) device; if (sensor.isSensorOfType(LiveDataType.WINDAVERAGE) || sensor.isSensorOfType(LiveDataType.WINDDIRECTION) || sensor.isSensorOfType(LiveDataType.WINDGUST)) { @@ -175,6 +185,18 @@ public class TellstickDiscoveryService extends AbstractDiscoveryService implemen } else { 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; } diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java index b46412e4265..e1b57874cc7 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/handler/TelldusDevicesHandler.java @@ -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.TellstickNetSensor; 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.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.library.unit.Units; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -109,9 +113,15 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta return; } if (command instanceof RefreshType) { - getBridge().getHandler().handleCommand(channelUID, command); - refreshDevice(dev); - return; + Bridge bridge = getBridge(); + if (bridge != null) { + 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)) { try { @@ -123,9 +133,6 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta } 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); @@ -159,8 +166,9 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta if (repeatCount != null) { resend = repeatCount.intValue(); } - if (getBridge() != null) { - bridgeStatusChanged(getBridge().getStatusInfo()); + Bridge bridge = getBridge(); + if (bridge != null) { + bridgeStatusChanged(bridge.getStatusInfo()); } } @@ -169,31 +177,34 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta 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); + Bridge localBridge = getBridge(); + if (localBridge != null) { + TelldusBridgeHandler telldusBridgeHandler = (TelldusBridgeHandler) localBridge.getHandler(); + logger.debug("Init bridge for {}, bridge:{}", deviceId, telldusBridgeHandler); + if (telldusBridgeHandler != null) { + this.bridgeHandler = telldusBridgeHandler; + this.bridgeHandler.registerDeviceStatusListener(this); + Configuration config = editConfiguration(); + Device dev = getDevice(telldusBridgeHandler, 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); + 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) { @@ -240,6 +251,10 @@ public class TelldusDevicesHandler extends BaseThingHandler implements DeviceSta for (DataTypeValue type : ((TellstickNetSensor) dev).getData()) { 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) { TellstickNetSensorEvent sensorevent = (TellstickNetSensorEvent) event; updateSensorDataState(sensorevent.getDataTypeValue()); + } else if (event instanceof TellstickLocalSensorEventDTO) { + TellstickLocalSensorEventDTO sensorevent = (TellstickLocalSensorEventDTO) event; + updateSensorDataState(sensorevent.getDataTypeValue()); } else if (event instanceof TellstickSensorEvent) { TellstickSensorEvent sensorevent = (TellstickSensorEvent) event; 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) { if (device != null) { logger.debug("Updating state of {} {} ({}) id: {}", device.getDeviceType(), device.getName(), diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/LiveDataType.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/LiveDataType.java index 67dd3f95c91..9340acf1134 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/LiveDataType.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/live/xml/LiveDataType.java @@ -20,11 +20,11 @@ package org.openhab.binding.tellstick.internal.live.xml; public enum LiveDataType { HUMIDITY("humidity"), TEMPERATURE("temp"), - WINDAVERAGE("windaverage"), - WINDDIRECTION("winddirection"), - WINDGUST("windgust"), - RAINRATE("rainrate"), - RAINTOTAL("rainttotal"), + WINDAVERAGE("wavg"), + WINDDIRECTION("wdir"), + WINDGUST("wgust"), + RAINRATE("rrate"), + RAINTOTAL("rtot"), WATT("watt"), LUMINATION("lum"), UNKOWN("unkown"); diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalBridgeHandler.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalBridgeHandler.java new file mode 100644 index 00000000000..d1a7dd4a09b --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalBridgeHandler.java @@ -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 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 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 devices) { + for (Device device : devices) { + if (device.getId() == Integer.valueOf(id)) { + return device; + } + } + return null; + } + + private Device getSensor(String id, List 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 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; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalDeviceController.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalDeviceController.java new file mode 100644 index 00000000000..425f76e29ae --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalDeviceController.java @@ -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 callRestMethod(String uri, Class 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 innerCallRest(String uri, Class 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); + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalException.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalException.java new file mode 100644 index 00000000000..f9da5406212 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/TelldusLocalException.java @@ -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 ""; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/LocalDataTypeValueDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/LocalDataTypeValueDTO.java new file mode 100644 index 00000000000..63bab55c26e --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/LocalDataTypeValueDTO.java @@ -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; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TelldusLocalResponseDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TelldusLocalResponseDTO.java new file mode 100644 index 00000000000..9f6d7726bde --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TelldusLocalResponseDTO.java @@ -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; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDeviceDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDeviceDTO.java new file mode 100644 index 00000000000..7289dcd9994 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDeviceDTO.java @@ -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; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDevicesDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDevicesDTO.java new file mode 100644 index 00000000000..275768de138 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalDevicesDTO.java @@ -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 devices = null; + + public List getDevices() { + return devices; + } + + public void setDevices(List devices) { + this.devices = devices; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorDTO.java new file mode 100644 index 00000000000..f8087fb9288 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorDTO.java @@ -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 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 getData() { + return data; + } + + public void setData(List 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); + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorEventDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorEventDTO.java new file mode 100644 index 00000000000..39e6744e9e0 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorEventDTO.java @@ -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"); + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorsDTO.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorsDTO.java new file mode 100644 index 00000000000..ff6e64f9607 --- /dev/null +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/local/dto/TellstickLocalSensorsDTO.java @@ -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 sensors = null; + + public List getSensors() { + return sensors; + } + + public void setSensors(List sensors) { + this.sensors = sensors; + } +} diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/bridge.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/bridge.xml index da1ca16a0d6..11f8e2b091f 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/bridge.xml @@ -6,7 +6,7 @@ - This bridge represents the telldus center on a local computer. + This bridge represents the Telldus center on a local computer. @@ -25,7 +25,7 @@ - This bridge represents the telldus live cloud service. + This bridge represents the Telldus live cloud service. @@ -34,12 +34,10 @@ The private key from telldus - credentials The public key from telldus - credentials The openauth token. @@ -48,7 +46,7 @@ The openauth token secret. - + The refresh interval in ms which is used to poll Telldus Live. @@ -57,4 +55,27 @@ + + + This bridge represents the Telldus local API. + + + + + The local IP address of the Tellstick. + network-address + + + + The access token. + + + + The refresh interval in ms which is used to poll Telldus local API. + + 60000 + + + + diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/devices.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/devices.xml index 3e2fa9f1bc5..f51e8f2d9d7 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/devices.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/devices.xml @@ -9,6 +9,7 @@ + diff --git a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/sensor.xml b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/sensor.xml index 4a598a43244..5e1820371b8 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/sensor.xml +++ b/bundles/org.openhab.binding.tellstick/src/main/resources/OH-INF/thing/sensor.xml @@ -8,6 +8,7 @@ + @@ -91,14 +92,14 @@ Number:Length The current rain rate - + Number:Length Total rain - + @@ -126,9 +127,9 @@ Number:Power - - Current kWatt - + + Current power +