From 1dccf67909e1f538a263eafaf87ef0c55a102a5b Mon Sep 17 00:00:00 2001 From: J-N-K Date: Tue, 3 Nov 2020 23:23:57 +0100 Subject: [PATCH] [deconz] fix lastSeenPolling and compile warnings (#8918) Signed-off-by: Jan N. Klug --- bundles/org.openhab.binding.deconz/README.md | 2 +- .../discovery/ThingDiscoveryService.java | 10 +++---- .../handler/DeconzBaseThingHandler.java | 12 +++++---- .../internal/handler/GroupThingHandler.java | 8 +++--- .../internal/handler/LightThingHandler.java | 27 ++++++++++--------- .../handler/SensorBaseThingHandler.java | 24 +++++++++++------ .../handler/SensorThermostatThingHandler.java | 17 ++++++++---- .../internal/handler/SensorThingHandler.java | 4 --- .../deconz/internal/handler/ThingConfig.java | 2 +- .../main/resources/OH-INF/config/config.xml | 4 +-- 10 files changed, 64 insertions(+), 46 deletions(-) diff --git a/bundles/org.openhab.binding.deconz/README.md b/bundles/org.openhab.binding.deconz/README.md index 188da3cb0f6e6..d10d17bf8dd91 100644 --- a/bundles/org.openhab.binding.deconz/README.md +++ b/bundles/org.openhab.binding.deconz/README.md @@ -81,7 +81,7 @@ 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". +The default-value is `1440`, which means "once a day". `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. diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java index 5cfbfeb876b8f..d848feaf08e84 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/discovery/ThingDiscoveryService.java @@ -163,11 +163,11 @@ private void addLight(String lightId, LightMessage light) { properties.put(Thing.PROPERTY_VENDOR, light.manufacturername); properties.put(Thing.PROPERTY_MODEL_ID, light.modelid); - if (light.ctmax != null && light.ctmin != null) { - properties.put(PROPERTY_CT_MAX, - Integer.toString(Util.constrainToRange(light.ctmax, ZCL_CT_MIN, ZCL_CT_MAX))); - properties.put(PROPERTY_CT_MIN, - Integer.toString(Util.constrainToRange(light.ctmin, ZCL_CT_MIN, ZCL_CT_MAX))); + Integer ctmax = light.ctmax; + Integer ctmin = light.ctmin; + if (ctmax != null && ctmin != null) { + properties.put(PROPERTY_CT_MAX, Integer.toString(Util.constrainToRange(ctmax, ZCL_CT_MIN, ZCL_CT_MAX))); + properties.put(PROPERTY_CT_MIN, Integer.toString(Util.constrainToRange(ctmin, ZCL_CT_MIN, ZCL_CT_MAX))); } switch (lightType) { diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java index 8125b2cde97f3..9676e07e28fc0 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/DeconzBaseThingHandler.java @@ -19,6 +19,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.function.Consumer; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -119,7 +120,7 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { registerListener(); // get initial values - requestState(); + requestState(this::processStateResponse); } else { // if the bridge is not ONLINE, we assume communication is not possible, so we unregister the listener and // set the thing status to OFFLINE @@ -131,7 +132,7 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { protected abstract @Nullable T parseStateResponse(AsyncHttpClient.Result r); /** - * processes a newly received state response + * processes a newly received (initial) state response * * MUST set the thing status! * @@ -142,7 +143,7 @@ public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { /** * Perform a request to the REST API for retrieving the full light state with all data and configuration. */ - protected void requestState() { + protected void requestState(Consumer<@Nullable T> processor) { AsyncHttpClient asyncHttpClient = http; if (asyncHttpClient == null) { return; @@ -162,10 +163,11 @@ protected void requestState() { } stopInitializationJob(); - initializationJob = scheduler.schedule((Runnable) this::requestState, 10, TimeUnit.SECONDS); + initializationJob = scheduler.schedule(() -> requestState(this::processStateResponse), 10, + TimeUnit.SECONDS); return null; - }).thenAccept(this::processStateResponse); + }).thenAccept(processor); } /** diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/GroupThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/GroupThingHandler.java index 4d1acae522013..dad89c31a5138 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/GroupThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/GroupThingHandler.java @@ -91,8 +91,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { case CHANNEL_COLOR: if (command instanceof HSBType) { HSBType hsbCommand = (HSBType) command; - newGroupAction.bri = Util.fromPercentType(hsbCommand.getBrightness()); - if (newGroupAction.bri > 0) { + Integer bri = Util.fromPercentType(hsbCommand.getBrightness()); + newGroupAction.bri = bri; + if (bri > 0) { newGroupAction.hue = (int) (hsbCommand.getHue().doubleValue() * HUE_FACTOR); newGroupAction.sat = Util.fromPercentType(hsbCommand.getSaturation()); } @@ -118,7 +119,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { return; } - if (newGroupAction.bri != null && newGroupAction.bri > 0) { + Integer bri = newGroupAction.bri; + if (bri != null && bri > 0) { newGroupAction.on = true; } diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java index 6ba83ec2b7552..1e79bcaf4005f 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/LightThingHandler.java @@ -228,16 +228,17 @@ public void handleCommand(ChannelUID channelUID, Command command) { return; } - if (newLightState.on != null && !newLightState.on) { + Boolean newOn = newLightState.on; + if (newOn != null && !newOn) { // if light shall be off, no other commands are allowed, so reset the new light state newLightState.clear(); newLightState.on = false; } sendCommand(newLightState, command, channelUID, () -> { + Integer transitionTime = newLightState.transitiontime; lastCommandExpireTimestamp = System.currentTimeMillis() - + (newLightState.transitiontime != null ? newLightState.transitiontime - : DEFAULT_COMMAND_EXPIRY_TIME); + + (transitionTime != null ? transitionTime : DEFAULT_COMMAND_EXPIRY_TIME); lastCommand = newLightState; }); } @@ -248,16 +249,18 @@ public void handleCommand(ChannelUID channelUID, Command command) { return null; } else if (r.getResponseCode() == 200) { LightMessage lightMessage = gson.fromJson(r.getBody(), LightMessage.class); - if (lightMessage != null && needsPropertyUpdate) { + if (needsPropertyUpdate) { // if we did not receive an ctmin/ctmax, then we probably don't need it needsPropertyUpdate = false; - if (lightMessage.ctmin != null && lightMessage.ctmax != null) { + Integer ctmax = lightMessage.ctmax; + Integer ctmin = lightMessage.ctmin; + if (ctmin != null && ctmax != null) { Map properties = new HashMap<>(thing.getProperties()); properties.put(PROPERTY_CT_MAX, - Integer.toString(Util.constrainToRange(lightMessage.ctmax, ZCL_CT_MIN, ZCL_CT_MAX))); + Integer.toString(Util.constrainToRange(ctmax, ZCL_CT_MIN, ZCL_CT_MAX))); properties.put(PROPERTY_CT_MIN, - Integer.toString(Util.constrainToRange(lightMessage.ctmin, ZCL_CT_MIN, ZCL_CT_MAX))); + Integer.toString(Util.constrainToRange(ctmin, ZCL_CT_MIN, ZCL_CT_MAX))); updateProperties(properties); } } @@ -278,6 +281,8 @@ protected void processStateResponse(@Nullable LightMessage stateResponse) { private void valueUpdated(String channelId, LightState newState) { Integer bri = newState.bri; + Integer hue = newState.hue; + Integer sat = newState.sat; Boolean on = newState.on; switch (channelId) { @@ -292,15 +297,13 @@ private void valueUpdated(String channelId, LightState newState) { case CHANNEL_COLOR: if (on != null && on == false) { updateState(channelId, OnOffType.OFF); - } else if (bri != null && newState.colormode != null && newState.colormode.equals("xy")) { + } else if (bri != null && "xy".equals(newState.colormode)) { final double @Nullable [] xy = newState.xy; if (xy != null && xy.length == 2) { HSBType color = HSBType.fromXY((float) xy[0], (float) xy[1]); updateState(channelId, new HSBType(color.getHue(), color.getSaturation(), toPercentType(bri))); } - } else if (bri != null && newState.hue != null && newState.sat != null) { - final Integer hue = newState.hue; - final Integer sat = newState.sat; + } else if (bri != null && hue != null && sat != null) { updateState(channelId, new HSBType(new DecimalType(hue / HUE_FACTOR), toPercentType(sat), toPercentType(bri))); } @@ -340,7 +343,7 @@ public void messageReceived(String sensorID, DeconzBaseMessage message) { return; } lightStateCache = lightState; - if (lightState.reachable != null && lightState.reachable) { + if (Boolean.TRUE.equals(lightState.reachable)) { updateStatus(ThingStatus.ONLINE); thing.getChannels().stream().map(c -> c.getUID().getId()).forEach(c -> valueUpdated(c, lightState)); } else { diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorBaseThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorBaseThingHandler.java index 9f9ff4284f3f3..d21b60a9b5026 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorBaseThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorBaseThingHandler.java @@ -164,23 +164,31 @@ 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. + // Because "last seen" is never updated by the WebSocket API - if this is supported, then we have to + // manually poll it after the defined time String lastSeen = stateResponse.lastseen; if (lastSeen != null && config.lastSeenPolling > 0) { createChannel(CHANNEL_LAST_SEEN, ChannelKind.STATE); updateState(CHANNEL_LAST_SEEN, Util.convertTimestampToDateTime(lastSeen)); - // Because "last seen" is never updated by the WebSocket API - if this is supported, then we have to - // 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); - } + lastSeenPollingJob = scheduler.schedule(() -> requestState(this::processLastSeen), config.lastSeenPolling, + TimeUnit.MINUTES); + logger.trace("lastSeen polling enabled for thing {} with interval of {} minutes", thing.getUID(), + config.lastSeenPolling); } updateStatus(ThingStatus.ONLINE); } + private void processLastSeen(@Nullable SensorMessage stateResponse) { + if (stateResponse == null) { + return; + } + String lastSeen = stateResponse.lastseen; + if (lastSeen != null) { + updateState(CHANNEL_LAST_SEEN, Util.convertTimestampToDateTime(lastSeen)); + } + } + protected void createChannel(String channelId, ChannelKind kind) { ThingHandlerCallback callback = getCallback(); if (callback != null) { diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThermostatThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThermostatThingHandler.java index ee4ace7a8c36c..13862fd514792 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThermostatThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThermostatThingHandler.java @@ -22,6 +22,8 @@ import java.util.List; import java.util.Set; +import javax.measure.quantity.Temperature; + import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.deconz.internal.dto.SensorConfig; @@ -125,7 +127,8 @@ public void handleCommand(ChannelUID channelUID, Command command) { @Override protected void valueUpdated(ChannelUID channelUID, SensorConfig newConfig) { super.valueUpdated(channelUID, newConfig); - String mode = newConfig.mode != null ? newConfig.mode.name() : ThermostatMode.UNKNOWN.name(); + ThermostatMode thermostatMode = newConfig.mode; + String mode = thermostatMode != null ? thermostatMode.name() : ThermostatMode.UNKNOWN.name(); String channelID = channelUID.getId(); switch (channelID) { case CHANNEL_HEATSETPOINT: @@ -135,9 +138,7 @@ protected void valueUpdated(ChannelUID channelUID, SensorConfig newConfig) { updateQuantityTypeChannel(channelID, newConfig.offset, CELSIUS, 1.0 / 100); break; case CHANNEL_THERMOSTAT_MODE: - if (mode != null) { - updateState(channelUID, new StringType(mode)); - } + updateState(channelUID, new StringType(mode)); break; } } @@ -169,7 +170,13 @@ protected List getConfigChannels() { if (command instanceof DecimalType) { newTemperature = ((DecimalType) command).toBigDecimal(); } else if (command instanceof QuantityType) { - newTemperature = ((QuantityType) command).toUnit(CELSIUS).toBigDecimal(); + @SuppressWarnings("unchecked") + QuantityType temperatureCelsius = ((QuantityType) command).toUnit(CELSIUS); + if (temperatureCelsius != null) { + newTemperature = temperatureCelsius.toBigDecimal(); + } else { + return null; + } } else { return null; } diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThingHandler.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThingHandler.java index 21217ed21f1b4..a36e6663fa7e5 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThingHandler.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/SensorThingHandler.java @@ -34,8 +34,6 @@ import org.openhab.core.thing.type.ChannelKind; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.google.gson.Gson; @@ -65,8 +63,6 @@ public class SensorThingHandler extends SensorBaseThingHandler { private static final List CONFIG_CHANNELS = Arrays.asList(CHANNEL_BATTERY_LEVEL, CHANNEL_BATTERY_LOW, CHANNEL_TEMPERATURE); - private final Logger logger = LoggerFactory.getLogger(SensorThingHandler.class); - public SensorThingHandler(Thing thing, Gson gson) { super(thing, gson); } diff --git a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/ThingConfig.java b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/ThingConfig.java index 92d2915666f57..a43e07577901f 100644 --- a/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/ThingConfig.java +++ b/bundles/org.openhab.binding.deconz/src/main/java/org/openhab/binding/deconz/internal/handler/ThingConfig.java @@ -23,6 +23,6 @@ @NonNullByDefault public class ThingConfig { public String id = ""; - public int lastSeenPolling = 0; + public int lastSeenPolling = 1440; public @Nullable Double transitiontime; } diff --git a/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/config/config.xml b/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/config/config.xml index 0ab34e1c0d7c0..132f255a4b43e 100644 --- a/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/config/config.xml +++ b/bundles/org.openhab.binding.deconz/src/main/resources/OH-INF/config/config.xml @@ -42,8 +42,8 @@ Interval to poll the deCONZ Gateway for this sensor's "lastSeen" channel. Polling is disabled when set - to 0. - 0 + to 1440 (once per day). + 1440