From 5c9da5687ce36b48f15338b134fef13b24950d56 Mon Sep 17 00:00:00 2001 From: Jacob Laursen Date: Mon, 3 Jan 2022 13:36:36 +0100 Subject: [PATCH] Support refresh command for signalStrength items. (#11944) Fixes #11942 Signed-off-by: Jacob Laursen --- .../org.openhab.binding.hdpowerview/README.md | 1 + .../internal/HDPowerViewWebTargets.java | 22 +++++++- .../internal/api/responses/Survey.java | 51 +++++++++++++++++++ .../handler/HDPowerViewShadeHandler.java | 28 ++++++++++ 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.java diff --git a/bundles/org.openhab.binding.hdpowerview/README.md b/bundles/org.openhab.binding.hdpowerview/README.md index 180bbc6120a08..df43456128b9c 100644 --- a/bundles/org.openhab.binding.hdpowerview/README.md +++ b/bundles/org.openhab.binding.hdpowerview/README.md @@ -166,6 +166,7 @@ For single shades the refresh takes the item's channel into consideration: | lowBattery | Battery | | batteryLevel | Battery | | batteryVoltage | Battery | +| signalStrength | Survey | ## Full Example diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java index 8225d02cdb44f..c890c4ec45ea5 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java @@ -33,6 +33,7 @@ import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents; import org.openhab.binding.hdpowerview.internal.api.responses.Shade; import org.openhab.binding.hdpowerview.internal.api.responses.Shades; +import org.openhab.binding.hdpowerview.internal.api.responses.Survey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,7 +47,7 @@ * * @author Andy Lintner - Initial contribution * @author Andrew Fiddian-Green - Added support for secondary rail positions - * @author Jacob Laursen - Add support for scene groups and automations + * @author Jacob Laursen - Added support for scene groups and automations */ @NonNullByDefault public class HDPowerViewWebTargets { @@ -325,6 +326,25 @@ private synchronized String invoke(HttpMethod method, String url, @Nullable Quer return gson.fromJson(json, Shade.class); } + /** + * Instructs the hub to do a hard refresh (discovery on the hubs RF network) on + * a specific shade's survey data, which will also refresh signal strength; + * fetches a JSON package that describes that survey, and wraps it in a Survey + * class instance + * + * @param shadeId id of the shade to be surveyed + * @return Survey class instance + * @throws JsonParseException if there is a JSON parsing error + * @throws HubProcessingException if there is any processing error + * @throws HubMaintenanceException if the hub is down for maintenance + */ + public @Nullable Survey getShadeSurvey(int shadeId) + throws JsonParseException, HubProcessingException, HubMaintenanceException { + String json = invoke(HttpMethod.GET, shades + Integer.toString(shadeId), + Query.of("survey", Boolean.toString(true)), null); + return gson.fromJson(json, Survey.class); + } + /** * Instructs the hub to do a hard refresh (discovery on the hubs RF network) on * a specific shade's battery level; fetches a JSON package that describes that shade, diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.java new file mode 100644 index 0000000000000..3c391b97bd883 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.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.hdpowerview.internal.api.responses; + +import java.util.List; +import java.util.StringJoiner; + +import com.google.gson.annotations.SerializedName; + +/** + * Survey data of a single Shade, as returned by an HD PowerView hub + * + * @author Jacob Laursen - Initial contribution + */ +public class Survey { + @SerializedName("shade_id") + public int shadeId; + @SerializedName("survey") + public List surveyData; + + public static class SurveyData { + @SerializedName("neighbor_id") + public int neighborId; + public int rssi; + + @Override + public String toString() { + return String.format("{neighbor id:%d, rssi:%d}", neighborId, rssi); + } + } + + @Override + public String toString() { + if (surveyData == null) { + return "{}"; + } + StringJoiner joiner = new StringJoiner(", "); + surveyData.forEach(data -> joiner.add(data.toString())); + return joiner.toString(); + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java index e996b58ce33d5..502e2c6ff648a 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java @@ -31,6 +31,7 @@ import org.openhab.binding.hdpowerview.internal.api.ShadePosition; import org.openhab.binding.hdpowerview.internal.api.responses.Shade; import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData; +import org.openhab.binding.hdpowerview.internal.api.responses.Survey; import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; @@ -62,6 +63,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { private enum RefreshKind { POSITION, + SURVEY, BATTERY_LEVEL } @@ -69,6 +71,7 @@ private enum RefreshKind { private static final int REFRESH_DELAY_SEC = 10; private @Nullable ScheduledFuture refreshPositionFuture = null; + private @Nullable ScheduledFuture refreshSignalFuture = null; private @Nullable ScheduledFuture refreshBatteryLevelFuture = null; public HDPowerViewShadeHandler(Thing thing) { @@ -118,6 +121,9 @@ public void handleCommand(ChannelUID channelUID, Command command) { case CHANNEL_SHADE_BATTERY_VOLTAGE: requestRefreshShadeBatteryLevel(); break; + case CHANNEL_SHADE_SIGNAL_STRENGTH: + requestRefreshShadeSurvey(); + break; } return; } @@ -300,6 +306,15 @@ protected synchronized void requestRefreshShadePosition() { } } + /** + * Request that the shade shall undergo a 'hard' refresh for querying its survey data + */ + protected synchronized void requestRefreshShadeSurvey() { + if (refreshSignalFuture == null) { + refreshSignalFuture = scheduler.schedule(this::doRefreshShadeSignal, REFRESH_DELAY_SEC, TimeUnit.SECONDS); + } + } + /** * Request that the shade shall undergo a 'hard' refresh for querying its battery level state */ @@ -315,6 +330,11 @@ private void doRefreshShadePosition() { refreshPositionFuture = null; } + private void doRefreshShadeSignal() { + this.doRefreshShade(RefreshKind.SURVEY); + refreshSignalFuture = null; + } + private void doRefreshShadeBatteryLevel() { this.doRefreshShade(RefreshKind.BATTERY_LEVEL); refreshBatteryLevelFuture = null; @@ -336,6 +356,14 @@ private void doRefreshShade(RefreshKind kind) { case POSITION: shade = webTargets.refreshShadePosition(shadeId); break; + case SURVEY: + Survey survey = webTargets.getShadeSurvey(shadeId); + if (survey != null && survey.surveyData != null) { + logger.debug("Survey response for shade {}: {}", survey.shadeId, survey.toString()); + } else { + logger.warn("No response from shade {} survey", shadeId); + } + return; case BATTERY_LEVEL: shade = webTargets.refreshShadeBatteryLevel(shadeId); break;