Skip to content

Commit

Permalink
[deconz] improve lastSeen channel, add reachable status, fixes (openh…
Browse files Browse the repository at this point in the history
…ab#8193)

- add missing debug messages and remove unnecessary debugging
- allow disabling of lastseen polling
- add reachable status to light things
- add documentation
- add last_seen channel only when available and enabled

Closes openhab#8193

Signed-off-by: Jan N. Klug <[email protected]>
  • Loading branch information
J-N-K authored and andrewfg committed Aug 31, 2020
1 parent f98a57e commit 90a62e1
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 36 deletions.
10 changes: 9 additions & 1 deletion bundles/org.openhab.binding.deconz/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ For this process the deCONZ bridge must be unlocked in the deCONZ software so th
All non-bridge things share the mandatory `id` parameter, an integer assigned to the device while pairing to deconz.
Auto-discovered things do not need to be configured.

All sensor-things have an additional `lastSeenPolling` parameter.
Due to limitations in the API of deCONZ, the `lastSeen` channel (available some sensors) is only available when using polling.
Allowed values are all positive integers, the unit is minutes.
The default-value is `0`, which means "no polling at all".


`dimmablelight`, `extendedcolorlight`, `colorlight` and `colortemperaturelight` have an additional optional parameter `transitiontime`.
The transition time is the time to move between two states and is configured in seconds.
The resolution provided is 1/10s.
Expand Down Expand Up @@ -142,6 +148,8 @@ The sensor devices support some of the following channels:
The specification of your sensor depends on the deCONZ capabilities.
Have a detailed look for [supported devices](https://github.com/dresden-elektronik/deconz-rest-plugin/wiki/Supported-Devices).

The `last_seen` channel is added when it is available AND the `lastSeenPolling` parameter of this sensor is used to enable polling.

Other devices support

| Channel Type ID | Item Type | Access Mode | Description | Thing types |
Expand Down Expand Up @@ -195,7 +203,7 @@ Bridge deconz:deconz:homeserver [ host="192.168.0.10", apikey="ABCDEFGHIJ" ] {
openclosesensor livingroom-window "Livingroom Window" [ id="5" ]
switch livingroom-hue-tap "Livingroom Hue Tap" [ id="6" ]
waterleakagesensor basement-water-leakage "Basement Water Leakage" [ id="7" ]
alarmsensor basement-alarm "Basement Alarm Sensor" [ id="8" ]
alarmsensor basement-alarm "Basement Alarm Sensor" [ id="8", lastSeenPolling=5 ]
dimmablelight livingroom-ceiling "Livingroom Ceiling" [ id="1" ]
}
```
Expand Down
4 changes: 3 additions & 1 deletion bundles/org.openhab.binding.deconz/pom.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,10 @@ public class SensorConfig {
public @Nullable Integer heatsetpoint;
public @Nullable ThermostatMode mode;
public @Nullable Integer offset;

@Override
public String toString() {
return "SensorConfig{" + "on=" + on + ", reachable=" + reachable + ", battery=" + battery + ", temperature="
+ temperature + ", heatsetpoint=" + heatsetpoint + ", mode=" + mode + ", offset=" + offset + '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public String toString() {
return "SensorMessage{" + "type='" + type + '\'' + ", config=" + config + ", state=" + state + ", e='" + e
+ '\'' + ", r='" + r + '\'' + ", t='" + t + '\'' + ", id='" + id + '\'' + ", manufacturername='"
+ manufacturername + '\'' + ", modelid='" + modelid + '\'' + ", name='" + name + '\'' + ", swversion='"
+ swversion + '\'' + ", ep='" + ep + '\'' + ", uniqueid='" + uniqueid + '\'' + '}';
+ swversion + '\'' + ", ep='" + ep + '\'' + ", lastseen='" + lastseen + '\'' + ", uniqueid='" + uniqueid
+ '\'' + '}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ public abstract class DeconzBaseThingHandler<T extends DeconzBaseMessage> extend
protected ThingConfig config = new ThingConfig();
protected DeconzBridgeConfig bridgeConfig = new DeconzBridgeConfig();
protected final Gson gson;
@Nullable
protected ScheduledFuture<?> scheduledFuture;
private @Nullable ScheduledFuture<?> initializationJob;
protected @Nullable WebSocketConnection connection;
protected @Nullable AsyncHttpClient http;

Expand All @@ -68,11 +67,11 @@ public DeconzBaseThingHandler(Thing thing, Gson gson) {
/**
* Stops the API request
*/
private void stopTimer() {
ScheduledFuture<?> future = scheduledFuture;
private void stopInitializationJob() {
ScheduledFuture<?> future = initializationJob;
if (future != null) {
future.cancel(true);
scheduledFuture = null;
initializationJob = null;
}
}

Expand Down Expand Up @@ -159,16 +158,16 @@ protected void requestState(String type) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
}

stopTimer();
scheduledFuture = scheduler.schedule((Runnable) this::requestState, 10, TimeUnit.SECONDS);
stopInitializationJob();
initializationJob = scheduler.schedule((Runnable) this::requestState, 10, TimeUnit.SECONDS);

return null;
}).thenAccept(this::processStateResponse);
}

@Override
public void dispose() {
stopTimer();
stopInitializationJob();
WebSocketConnection webSocketConnection = connection;
if (webSocketConnection != null) {
webSocketConnection.unregisterLightListener(config.id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@
import org.eclipse.smarthome.core.thing.ChannelUID;
import org.eclipse.smarthome.core.thing.Thing;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.ThingStatusDetail;
import org.eclipse.smarthome.core.thing.ThingTypeUID;
import org.eclipse.smarthome.core.types.Command;
import org.eclipse.smarthome.core.types.RefreshType;
import org.eclipse.smarthome.core.types.StateDescription;
import org.eclipse.smarthome.core.types.StateDescriptionFragmentBuilder;
import org.eclipse.smarthome.core.types.UnDefType;
import org.openhab.binding.deconz.internal.StateDescriptionProvider;
import org.openhab.binding.deconz.internal.Util;
import org.openhab.binding.deconz.internal.dto.DeconzBaseMessage;
Expand Down Expand Up @@ -294,8 +296,6 @@ public void handleCommand(ChannelUID channelUID, Command command) {
Integer.toString(Util.constrainToRange(lightMessage.ctmax, ZCL_CT_MIN, ZCL_CT_MAX)));
properties.put(PROPERTY_CT_MIN,
Integer.toString(Util.constrainToRange(lightMessage.ctmin, ZCL_CT_MIN, ZCL_CT_MAX)));

logger.warn("properties new {}", properties);
updateProperties(properties);
}
}
Expand All @@ -310,9 +310,8 @@ protected void processStateResponse(@Nullable LightMessage stateResponse) {
if (stateResponse == null) {
return;
}
messageReceived(config.id, stateResponse);

updateStatus(ThingStatus.ONLINE);
messageReceived(config.id, stateResponse);
}

private void valueUpdated(String channelId, LightState newState) {
Expand Down Expand Up @@ -379,7 +378,13 @@ public void messageReceived(String sensorID, DeconzBaseMessage message) {
return;
}
lightStateCache = lightState;
thing.getChannels().stream().map(c -> c.getUID().getId()).forEach(c -> valueUpdated(c, lightState));
if (lightState.reachable != null && lightState.reachable) {
updateStatus(ThingStatus.ONLINE);
thing.getChannels().stream().map(c -> c.getUID().getId()).forEach(c -> valueUpdated(c, lightState));
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.GONE, "Not reachable");
thing.getChannels().stream().map(c -> c.getUID()).forEach(c -> updateState(c, UnDefType.UNDEF));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import javax.measure.Unit;
Expand Down Expand Up @@ -78,6 +79,7 @@ public abstract class SensorBaseThingHandler extends DeconzBaseThingHandler<Sens
* Prevent a dispose/init cycle while this flag is set. Use for property updates
*/
private boolean ignoreConfigurationUpdate;
private @Nullable ScheduledFuture<?> lastSeenPollingJob;

public SensorBaseThingHandler(Thing thing, Gson gson) {
super(thing, gson);
Expand All @@ -104,6 +106,17 @@ protected void unregisterListener() {
}
}

@Override
public void dispose() {
ScheduledFuture<?> lastSeenPollingJob = this.lastSeenPollingJob;
if (lastSeenPollingJob != null) {
lastSeenPollingJob.cancel(true);
this.lastSeenPollingJob = null;
}

super.dispose();
}

@Override
public abstract void handleCommand(ChannelUID channelUID, Command command);

Expand Down Expand Up @@ -131,6 +144,7 @@ public void handleConfigurationUpdate(Map<String, Object> configurationParameter

@Override
protected void processStateResponse(@Nullable SensorMessage stateResponse) {
logger.trace("{} received {}", thing.getUID(), stateResponse);
if (stateResponse == null) {
return;
}
Expand Down Expand Up @@ -176,14 +190,20 @@ protected void processStateResponse(@Nullable SensorMessage stateResponse) {
// "Last seen" is the last "ping" from the device, whereas "last update" is the last status changed.
// For example, for a fire sensor, the device pings regularly, without necessarily updating channels.
// So to monitor a sensor is still alive, the "last seen" is necessary.
if (stateResponse.lastseen != null) {
if (stateResponse.lastseen != null && config.lastSeenPolling > 0) {
createChannel(CHANNEL_LAST_SEEN, ChannelKind.STATE);
updateState(CHANNEL_LAST_SEEN,
new DateTimeType(ZonedDateTime.ofInstant(
LocalDateTime.parse(stateResponse.lastseen, DateTimeFormatter.ISO_LOCAL_DATE_TIME),
ZoneOffset.UTC, ZoneId.systemDefault())));
// Because "last seen" is never updated by the WebSocket API - if this is supported, then we have to
// manually poll it time to time (every 5 minutes by default)
super.scheduledFuture = scheduler.schedule((Runnable) this::requestState, 5, TimeUnit.MINUTES);
// manually poll it after the defined time (default is off)
if (config.lastSeenPolling > 0) {
lastSeenPollingJob = scheduler.schedule((Runnable) this::requestState, config.lastSeenPolling,
TimeUnit.MINUTES);
logger.trace("lastSeen polling enabled for thing {} with interval of {} minutes", thing.getUID(),
config.lastSeenPolling);
}
}

updateStatus(ThingStatus.ONLINE);
Expand Down Expand Up @@ -259,6 +279,7 @@ protected void valueUpdated(String channelID, SensorState newState, boolean init

@Override
public void messageReceived(String sensorID, DeconzBaseMessage message) {
logger.trace("{} received {}", thing.getUID(), message);
if (message instanceof SensorMessage) {
SensorMessage sensorMessage = (SensorMessage) message;
SensorConfig sensorConfig = sensorMessage.config;
Expand All @@ -281,7 +302,6 @@ private void updateChannels(SensorConfig newConfig) {
}

protected void updateChannels(SensorState newState, boolean initializing) {
logger.trace("{} received {}", thing.getUID(), newState);
sensorState = newState;
thing.getChannels().forEach(channel -> valueUpdated(channel.getUID().getId(), newState, initializing));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@
@NonNullByDefault
public class ThingConfig {
public String id = "";
public int lastSeenPolling = 0;
public @Nullable Double transitiontime;
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
<label>Device ID</label>
<description>The deCONZ bridge assigns an integer number ID to each device.</description>
</parameter>
<parameter name="lastSeenPolling" type="integer" min="0" unit="min">
<label>LastSeen Poll Interval</label>
<description>Interval to poll the deCONZ Gateway for this sensor's "lastSeen" channel. Polling is disabled when set
to 0.</description>
<default>0</default>
</parameter>
</config-description>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
<channels>
<channel typeId="presence" id="presence"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -53,7 +52,6 @@
<channels>
<channel typeId="power" id="power"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -94,7 +92,6 @@
<channels>
<channel typeId="consumption" id="consumption"></channel>
<channel typeId="last_updated" id="last_updated"></channel>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -119,7 +116,6 @@
<channel typeId="buttonevent" id="buttonevent"/>
<channel typeId="button" id="button"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -180,7 +176,6 @@
<channel typeId="dark" id="dark"/>
<channel typeId="daylight" id="daylight"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -225,7 +220,6 @@
<channels>
<channel typeId="temperature" id="temperature"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -249,7 +243,6 @@
<channels>
<channel typeId="humidity" id="humidity"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -273,7 +266,6 @@
<channels>
<channel typeId="pressure" id="pressure"></channel>
<channel typeId="last_updated" id="last_updated"></channel>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -333,7 +325,6 @@
<channels>
<channel typeId="open" id="open"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -357,7 +348,6 @@
<channels>
<channel typeId="waterleakage" id="waterleakage"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -381,7 +371,6 @@
<channels>
<channel typeId="fire" id="fire"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -405,7 +394,6 @@
<channels>
<channel typeId="alarm" id="alarm"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -436,7 +424,6 @@
<channels>
<channel typeId="vibration" id="vibration"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -460,7 +447,6 @@
<channels>
<channel typeId="battery" id="battery_level"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand All @@ -483,7 +469,6 @@
<channels>
<channel typeId="carbonmonoxide" id="carbonmonoxide"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>

<representation-property>uid</representation-property>
Expand Down Expand Up @@ -511,7 +496,6 @@
<channel typeId="offset" id="offset"/>
<channel typeId="valve" id="valve"/>
<channel typeId="last_updated" id="last_updated"/>
<channel typeId="last_seen" id="last_seen"/>
</channels>
<representation-property>uid</representation-property>
<config-description-ref uri="thing-type:deconz:sensor"/>
Expand Down

0 comments on commit 90a62e1

Please sign in to comment.