From f7295bd00f18a1f8167086e3e974f12ed48059e9 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Sun, 28 Aug 2022 12:55:18 +0100 Subject: [PATCH] [hdpowerview] Battery channels visible only when required (#13324) * [hdpowerview] add batteryKind field * [hdpowerview] battery channels visible depending on batteryKind Signed-off-by: Andrew Fiddian-Green --- .../org.openhab.binding.hdpowerview/README.md | 8 ++- .../hdpowerview/internal/api/BatteryKind.java | 57 +++++++++++++++++++ .../internal/api/responses/Shades.java | 7 +++ .../handler/HDPowerViewShadeHandler.java | 14 ++++- .../hdpowerview/HDPowerViewJUnitTests.java | 15 +++++ .../openhab/binding/hdpowerview/shades.json | 2 +- 6 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/BatteryKind.java diff --git a/bundles/org.openhab.binding.hdpowerview/README.md b/bundles/org.openhab.binding.hdpowerview/README.md index e4ed9a98a..6ea024228 100644 --- a/bundles/org.openhab.binding.hdpowerview/README.md +++ b/bundles/org.openhab.binding.hdpowerview/README.md @@ -96,14 +96,16 @@ All of these channels appear in the binding, but only those which have a physica | vane | Dimmer | The degree of opening of the slats or vanes (if any). On some shade types, setting this to a non-zero value might first move the shade `position` fully down, since the slats or vanes can only have a defined state if the shade is in its down position. See [Interdependency between Channel positions](#Interdependency-between-Channel-positions). | | command | String | Send a command to the shade. Valid values are: `CALIBRATE`, `IDENTIFY` | | lowBattery | Switch | Indicates ON when the battery level of the shade is low, as determined by the hub's internal rules. | -| batteryLevel | Number | Battery level (10% = low, 50% = medium, 100% = high) -| batteryVoltage | Number:ElectricPotential | Battery voltage reported by the shade. | +| batteryLevel | Number | Battery level (10% = low, 50% = medium, 100% = high) | +| batteryVoltage | Number:ElectricPotential | Battery (resp. mains power supply) voltage reported by the shade. | | signalStrength | Number | Signal strength (0 for no or unknown signal, 1 for weak, 2 for average, 3 for good or 4 for excellent) | | hubRssi | Number:Power | Received Signal Strength Indicator for Hub | | repeaterRssi | Number:Power | Received Signal Strength Indicator for Repeater | Notes: -- The channels `position`, `secondary` and `vane` only exist if the shade physically supports such channels. +- The channels `position`, `secondary` and `vane` exist if the shade physically supports such channels. +- The shade's Power Option is set via the PowerView app with possible values 'Battery Wand', 'Rechargeable Battery Wand' or 'Hardwired Power Supply'. +The channels `lowBattery` and `batteryLevel` exist if you have _not_ selected 'Hardwired Power Supply' in the app. - The RSSI values will only be updated upon manual request by a `REFRESH` command (e.g. in a rule). ### Channels for Repeaters (Thing type `repeater`) diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/BatteryKind.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/BatteryKind.java new file mode 100644 index 000000000..229d0abce --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/BatteryKind.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2022 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; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * An enum for the type of power supply in a shade. + * + * @author Andrew Fiddian-Green - Initial contribution + */ +@NonNullByDefault +public enum BatteryKind { + ERROR_UNKNOWN(-1), + HARDWIRED_POWER_SUPPLY(1), + BATTERY_WAND(2), + RECHARGEABLE_BATTERY_WAND(3); + + private int batteryKind; + + private BatteryKind(int i) { + this.batteryKind = i; + } + + /** + * Determine the BatteryKind by parsing the given string value. + * + * @param value the string to parse, or null. + * @return the BatteryKind or ERROR_UNKNOWN in case of error. + */ + public static BatteryKind fromString(@Nullable String value) { + if (value != null) { + try { + int intValue = Integer.parseInt(value); + for (BatteryKind e : values()) { + if (e.batteryKind == intValue) { + return e; + } + } + } catch (NumberFormatException e) { + // fall through + } + } + return ERROR_UNKNOWN; + } +} diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shades.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shades.java index 9704773df..2746523b4 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shades.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shades.java @@ -17,6 +17,7 @@ import java.util.List; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.hdpowerview.internal.api.BatteryKind; import org.openhab.binding.hdpowerview.internal.api.Firmware; import org.openhab.binding.hdpowerview.internal.api.ShadePosition; @@ -55,9 +56,15 @@ public class Shades { public @Nullable Integer capabilities; public @Nullable Firmware firmware; public @Nullable Firmware motor; + // note: in old JSON batteryKind was a string but now it's a number; fortunately GSON string accepts either + public @Nullable String batteryKind; public String getName() { return new String(Base64.getDecoder().decode(name)); } + + public BatteryKind getBatteryKind() { + return BatteryKind.fromString(batteryKind); + } } } 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 fb0d76e64..53e77e042 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 @@ -29,6 +29,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants; import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets; +import org.openhab.binding.hdpowerview.internal.api.BatteryKind; import org.openhab.binding.hdpowerview.internal.api.CoordinateSystem; import org.openhab.binding.hdpowerview.internal.api.Firmware; import org.openhab.binding.hdpowerview.internal.api.ShadePosition; @@ -274,7 +275,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { logger.debug("Caching capabilities {} for shade {}", capabilities.getValue(), shade.id); this.capabilities = capabilities; - updateDynamicChannels(capabilities); + updateDynamicChannels(capabilities, shade); } private Capabilities getCapabilitiesOrDefault() { @@ -618,9 +619,12 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { } /** - * Remove previously statically created channels if the shade does not support them. + * Remove previously statically created channels if the shade does not support them or they are not relevant. + * + * @param capabilities the capabilities of the shade. + * @param shade the shade data. */ - private void updateDynamicChannels(Capabilities capabilities) { + private void updateDynamicChannels(Capabilities capabilities, ShadeData shade) { List removeList = new ArrayList<>(); removeListProcessChannel(removeList, CHANNEL_SHADE_POSITION, capabilities.supportsPrimary()); @@ -631,6 +635,10 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { removeListProcessChannel(removeList, CHANNEL_SHADE_VANE, capabilities.supportsTiltAnywhere() || capabilities.supportsTiltOnClosed()); + boolean batteryChannelsRequired = shade.getBatteryKind() != BatteryKind.HARDWIRED_POWER_SUPPLY; + removeListProcessChannel(removeList, CHANNEL_SHADE_BATTERY_LEVEL, batteryChannelsRequired); + removeListProcessChannel(removeList, CHANNEL_SHADE_LOW_BATTERY, batteryChannelsRequired); + if (!removeList.isEmpty()) { if (logger.isDebugEnabled()) { StringJoiner joiner = new StringJoiner(", "); diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java index 438055477..19cd35c7c 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java @@ -23,6 +23,7 @@ import java.util.Objects; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; +import org.openhab.binding.hdpowerview.internal.api.BatteryKind; import org.openhab.binding.hdpowerview.internal.api.ShadePosition; import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections; import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection; @@ -76,6 +77,20 @@ public class HDPowerViewJUnitTests { assertEquals("Shade 2", shade.getName()); } + /** + * Test the BatteryKind decoding. + */ + @Test + public void testBatteryKind() throws IOException { + Shades shades = getObjectFromJson("shades.json", Shades.class); + List shadeData = shades.shadeData; + assertNotNull(shadeData); + ShadeData shade = shadeData.get(0); + assertEquals(BatteryKind.HARDWIRED_POWER_SUPPLY, shade.getBatteryKind()); + shade = shadeData.get(1); + assertEquals(BatteryKind.ERROR_UNKNOWN, shade.getBatteryKind()); + } + /** * Test generic JSON scene response. */ diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json index 9f682952d..cfbf43508 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json @@ -26,7 +26,7 @@ "aid": 2, "signalStrength": 4, "capabilities": 0, - "batteryKind": "unassigned", + "batteryKind": 1, "positions": { "posKind1": 3, "position1": 32579