diff --git a/bundles/org.openhab.binding.tellstick/README.md b/bundles/org.openhab.binding.tellstick/README.md index 81f542e9f7833..72e2ba7e5e2a3 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 0000000000000..8d324d55a25b1 Binary files /dev/null and b/bundles/org.openhab.binding.tellstick/doc/znet.jpeg differ diff --git a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java index a8690ec827a66..1f62da26158ee 100644 --- a/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java +++ b/bundles/org.openhab.binding.tellstick/src/main/java/org/openhab/binding/tellstick/internal/TellstickBindingConstants.java @@ -14,10 +14,7 @@ import static org.openhab.core.library.unit.MetricPrefix.*; -import java.util.Collections; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; import javax.measure.Unit; import javax.measure.quantity.Angle; @@ -65,6 +62,7 @@ public class TellstickBindingConstants { public static final String DEVICE_ISDIMMER = "dimmer"; public static final String BRIDGE_TELLDUS_CORE = "telldus-core"; public static final String BRIDGE_TELLDUS_LIVE = "telldus-live"; + public static final String BRIDGE_TELLDUS_LOCAL = "telldus-local"; public static final String DEVICE_SENSOR = "sensor"; public static final String DEVICE_WINDSENSOR = "windsensor"; 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 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 TELLDUSLOCALBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, BRIDGE_TELLDUS_LOCAL); // List of all Channel ids public static final String CHANNEL_DIMMER = "dimmer"; 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_LUX = "lux"; - public static final Set 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 3897fcee9bd65..266e7c8bd3d3f 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 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 @@ * 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 @@ protected ThingHandler createHandler(Thing thing) { 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 32528e7c11593..e334c0b9fa9fc 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 @@ /** * 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 0000000000000..61e315ad0b9e7 --- /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 424e805fdc35a..59ab0403784ec 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.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 @@ private ThingUID getThingUID(Bridge bridge, Device device) { 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 @@ private ThingTypeUID findSensorType(Device device) { } 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 @@ private ThingTypeUID findSensorType(Device device) { } 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 b46412e426539..e1b57874cc7e5 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.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 void handleCommand(ChannelUID channelUID, Command command) { 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 void handleCommand(ChannelUID channelUID, Command command) { } 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 void initialize() { 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 void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { logger.debug("device: {} bridgeStatusChanged: {}", deviceId, bridgeStatusInfo); if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) { try { - TelldusBridgeHandler tellHandler = (TelldusBridgeHandler) getBridge().getHandler(); - logger.debug("Init bridge for {}, bridge:{}", deviceId, tellHandler); - if (tellHandler != null) { - this.bridgeHandler = tellHandler; - this.bridgeHandler.registerDeviceStatusListener(this); - Configuration config = editConfiguration(); - Device dev = getDevice(tellHandler, deviceId); - if (dev != null) { - if (dev.getName() != null) { - config.put(TellstickBindingConstants.DEVICE_NAME, dev.getName()); - } - if (dev.getProtocol() != null) { - config.put(TellstickBindingConstants.DEVICE_PROTOCOL, dev.getProtocol()); - } - if (dev.getModel() != null) { - config.put(TellstickBindingConstants.DEVICE_MODEL, dev.getModel()); - } - updateConfiguration(config); + 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 @@ private void updateSensorStates(Device dev) { 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 void onDeviceStateChanged(Bridge bridge, Device device, TellstickEvent ev } 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 @@ private void updateSensorDataState(DataTypeValue dataType) { } } + 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 67dd3f95c91c8..9340acf11340b 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 @@ 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 0000000000000..d1a7dd4a09b1f --- /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 0000000000000..425f76e29ae26 --- /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 0000000000000..f9da540621220 --- /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 0000000000000..63bab55c26e31 --- /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 0000000000000..9f6d7726bdebe --- /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 0000000000000..7289dcd999478 --- /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 0000000000000..275768de1388f --- /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 0000000000000..f8087fb928877 --- /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 0000000000000..39e6744e9e034 --- /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 0000000000000..ff6e64f9607e7 --- /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 da1ca16a0d627..11f8e2b091fc7 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 3e2fa9f1bc596..f51e8f2d9d7f3 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 4a598a43244ec..5e1820371b896 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 +