]> git.basschouten.com Git - openhab-addons.git/commitdiff
[hdpowerview] Restructure DTO classes (#13630)
authorJacob Laursen <jacob-github@vindvejr.dk>
Fri, 4 Nov 2022 17:24:39 +0000 (18:24 +0100)
committerGitHub <noreply@github.com>
Fri, 4 Nov 2022 17:24:39 +0000 (18:24 +0100)
* Extract nested DTO's to separate classes
* Rename api to dto
* Move test classes into internal
* Finish moving of files and fix namespaces

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
93 files changed:
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewWebTargets.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/BatteryKind.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Color.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/CoordinateSystem.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Firmware.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/HubFirmware.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePosition.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/SurveyData.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Times.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/UserData.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterBlinking.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterColor.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeCalibrate.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeJog.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMotion.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMove.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadePositions.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeStop.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/FirmwareVersion.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeater.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/RepeaterData.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeaters.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/SceneCollections.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/ScheduledEvents.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shade.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shades.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/UserDataResponse.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/builders/AutomationChannelBuilder.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/builders/SceneChannelBuilder.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/builders/SceneGroupChannelBuilder.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/console/HDPowerViewCommandExtension.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/BatteryKind.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/CoordinateSystem.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Firmware.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/HubFirmware.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Scene.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SceneCollection.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ScheduledEvent.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadeData.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SurveyData.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Times.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/UserData.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterBlinking.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterColor.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeCalibrate.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeJog.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMove.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadePositions.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeStop.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/FirmwareVersion.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeater.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/RepeaterData.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeaters.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/SceneCollections.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Scenes.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/ScheduledEvents.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shade.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shades.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Survey.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/UserDataResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewRepeaterHandler.java
bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/AutomationChannelBuilderTest.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/OnlineCommunicationTest.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneChannelBuilderTest.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneGroupChannelBuilderTest.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/ShadePositionTest.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/AutomationChannelBuilderTest.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/HDPowerViewJUnitTests.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/OnlineCommunicationTest.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneChannelBuilderTest.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneGroupChannelBuilderTest.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/ShadePositionTest.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedLocaleProvider.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedTranslationProvider.java [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedLocaleProvider.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedTranslationProvider.java [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/duette.json [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/duette.json [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/sceneCollections.json [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/scenes.json [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/shades.json [new file with mode: 0644]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/sceneCollections.json [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/scenes.json [deleted file]
bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json [deleted file]

index f8ba04c153391088eb89de2673b13599abee314a..aa3525e7d9d183d46f2a09ec6e0145071d2edb8e 100644 (file)
@@ -27,32 +27,32 @@ import org.eclipse.jetty.client.util.StringContentProvider;
 import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.http.HttpMethod;
 import org.eclipse.jetty.http.HttpStatus;
-import org.openhab.binding.hdpowerview.internal.api.Color;
-import org.openhab.binding.hdpowerview.internal.api.HubFirmware;
-import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
-import org.openhab.binding.hdpowerview.internal.api.SurveyData;
-import org.openhab.binding.hdpowerview.internal.api.UserData;
-import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterBlinking;
-import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterColor;
-import org.openhab.binding.hdpowerview.internal.api.requests.ShadeCalibrate;
-import org.openhab.binding.hdpowerview.internal.api.requests.ShadeJog;
-import org.openhab.binding.hdpowerview.internal.api.requests.ShadeMove;
-import org.openhab.binding.hdpowerview.internal.api.requests.ShadeStop;
-import org.openhab.binding.hdpowerview.internal.api.responses.FirmwareVersion;
-import org.openhab.binding.hdpowerview.internal.api.responses.Repeater;
-import org.openhab.binding.hdpowerview.internal.api.responses.RepeaterData;
-import org.openhab.binding.hdpowerview.internal.api.responses.Repeaters;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents.ScheduledEvent;
-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.Shades.ShadeData;
-import org.openhab.binding.hdpowerview.internal.api.responses.Survey;
-import org.openhab.binding.hdpowerview.internal.api.responses.UserDataResponse;
+import org.openhab.binding.hdpowerview.internal.dto.Color;
+import org.openhab.binding.hdpowerview.internal.dto.HubFirmware;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.ScheduledEvent;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+import org.openhab.binding.hdpowerview.internal.dto.SurveyData;
+import org.openhab.binding.hdpowerview.internal.dto.UserData;
+import org.openhab.binding.hdpowerview.internal.dto.requests.RepeaterBlinking;
+import org.openhab.binding.hdpowerview.internal.dto.requests.RepeaterColor;
+import org.openhab.binding.hdpowerview.internal.dto.requests.ShadeCalibrate;
+import org.openhab.binding.hdpowerview.internal.dto.requests.ShadeJog;
+import org.openhab.binding.hdpowerview.internal.dto.requests.ShadeMove;
+import org.openhab.binding.hdpowerview.internal.dto.requests.ShadeStop;
+import org.openhab.binding.hdpowerview.internal.dto.responses.FirmwareVersion;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Repeater;
+import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Repeaters;
+import org.openhab.binding.hdpowerview.internal.dto.responses.SceneCollections;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Scenes;
+import org.openhab.binding.hdpowerview.internal.dto.responses.ScheduledEvents;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shade;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shades;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Survey;
+import org.openhab.binding.hdpowerview.internal.dto.responses.UserDataResponse;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
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
deleted file mode 100644 (file)
index 229d0ab..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * 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/Color.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Color.java
deleted file mode 100644 (file)
index 39f1d0f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * 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.openhab.core.library.types.HSBType;
-
-/**
- * Color and brightness information for HD PowerView repeater
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Color {
-    public int brightness;
-    public int red;
-    public int green;
-    public int blue;
-
-    public Color(int brightness, HSBType hsbType) {
-        this.brightness = brightness;
-        int rgb = hsbType.getRGB();
-        java.awt.Color color = new java.awt.Color(rgb);
-        red = color.getRed();
-        green = color.getGreen();
-        blue = color.getBlue();
-    }
-
-    public Color(int brightness, java.awt.Color color) {
-        this.brightness = brightness;
-        red = color.getRed();
-        green = color.getGreen();
-        blue = color.getBlue();
-    }
-
-    public Color(int brightness, int red, int green, int blue) {
-        this.brightness = brightness;
-        this.red = red;
-        this.green = green;
-        this.blue = blue;
-    }
-
-    @Override
-    public String toString() {
-        return String.format("%d.%d.%d/%d%%", red, green, blue, brightness);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/CoordinateSystem.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/CoordinateSystem.java
deleted file mode 100644 (file)
index 236e468..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * 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;
-
-/**
- * Shade coordinate system (a.k.a. position kind), as returned by the HD PowerView hub.
- *
- * @param NONE a coordinate system that does not refer to any type of physical rail.
- * @param PRIMARY_POSITION primary rail, whose coordinate value 0 means shade is closed.
- * @param SECONDARY_POSITION secondary rail, whose coordinate value 0 means shade is open.
- * @param VANE_TILT_POSITION vane/tilt operator, whose coordinate system is for vanes.
- * @param ERROR_UNKNOWN unsupported coordinate system.
- *
- * @author Andy Lintner - Initial contribution of the original enum called
- *         ShadePositionKind
- *
- * @author Andrew Fiddian-Green - Rewritten as a new enum called
- *         CoordinateSystem to support secondary rail positions and be more
- *         explicit on coordinate directions and ranges
- */
-@NonNullByDefault
-public enum CoordinateSystem {
-    /*-
-     * Specifies the coordinate system used for the position of the shade. Top-down
-     * shades are in the same coordinate space as bottom-up shades. Shade position
-     * values for top-down shades would be reversed for bottom-up shades. For
-     * example, since 65535 is the open value for a bottom-up shade, it is the
-     * closed value for a top-down shade. The top-down/bottom-up shade is different
-     * in that instead of the top and bottom rail operating in one coordinate space
-     * like the top-down and the bottom-up, it operates in two where the top
-     * (middle) rail closed value is 0 and the bottom (primary) rail closed position
-     * is also 0 and fully open for both is 65535
-     *
-     * The position element can take on multiple states depending on the family of
-     * shade under control.
-     *
-     * The ranges of position integer values are
-     *      shades: 0..65535
-     *      vanes: 0..32767
-     *
-     * Shade fully up: (top-down: open, bottom-up: closed)
-     *      posKind: 1 {ZERO_IS_CLOSED}
-     *      position: 65535
-     *
-     * Shade and vane fully down: (top-down: closed, bottom-up: open)
-     *      posKind: 1 {ZERO_IS_CLOSED}
-     *      position1: 0
-     *
-     * ALTERNATE: Shade and vane fully down: (top-down: closed, bottom-up: open)
-     *      posKind: 3 {VANE_COORDS}
-     *      position: 0
-     *
-     * Shade fully down (closed) and vane fully up (open):
-     *      posKind: 3 {VANE_COORDS}
-     *      position: 32767
-     *
-     * Dual action, secondary top-down shade fully up (closed):
-     *      posKind: 2 {ZERO_IS_OPEN}
-     *      position: 0
-     *
-     * Dual action, secondary top-down shade fully down (open):
-     *      posKind: 2 {ZERO_IS_OPEN}
-     *      position: 65535
-     *
-     */
-    NONE,
-    PRIMARY_POSITION,
-    SECONDARY_POSITION,
-    VANE_TILT_POSITION,
-    ERROR_UNKNOWN;
-
-    public static final int MAX_SHADE = 65535;
-    public static final int MAX_VANE = 32767;
-
-    /**
-     * Converts an HD PowerView posKind integer value to a CoordinateSystem enum value.
-     *
-     * @param posKind input integer value.
-     * @return corresponding CoordinateSystem enum.
-     */
-    public static CoordinateSystem fromPosKind(int posKind) {
-        try {
-            return CoordinateSystem.values()[posKind];
-        } catch (ArrayIndexOutOfBoundsException e) {
-            return ERROR_UNKNOWN;
-        }
-    }
-
-    /**
-     * Check if the coordinate system matches the given posKind.
-     *
-     * @param posKind
-     * @return true if equal.
-     */
-    public boolean equals(@Nullable Integer posKind) {
-        return (posKind != null) && (posKind.intValue() == ordinal());
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Firmware.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Firmware.java
deleted file mode 100644 (file)
index fd627c8..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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;
-
-/**
- * Firmware version information for HD PowerView components
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Firmware {
-    @Nullable
-    public String name;
-    public int revision;
-    public int subRevision;
-    public int build;
-
-    @Override
-    public String toString() {
-        return String.format("%d.%d.%d", revision, subRevision, build);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/HubFirmware.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/HubFirmware.java
deleted file mode 100644 (file)
index 0a625b2..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * 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;
-
-/**
- * Firmware information for an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class HubFirmware {
-    @Nullable
-    public Firmware mainProcessor;
-    @Nullable
-    public Firmware radio;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePosition.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/ShadePosition.java
deleted file mode 100644 (file)
index 0eee7af..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/**
- * 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 static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
-import org.openhab.core.library.types.PercentType;
-import org.openhab.core.types.State;
-import org.openhab.core.types.UnDefType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The position of a single shade, as returned by the HD PowerView hub
- *
- * @author Andy Lintner - Initial contribution
- * @author Andrew Fiddian-Green - Added support for secondary rail positions
- */
-@NonNullByDefault
-public class ShadePosition {
-
-    private final transient Logger logger = LoggerFactory.getLogger(ShadePosition.class);
-
-    /**
-     * Primary actuator position.
-     */
-    private int posKind1;
-    private int position1;
-
-    /**
-     * Secondary actuator position.
-     *
-     * Here we have to use Integer objects rather than just int primitives because these are secondary optional position
-     * elements in the JSON payload, so the GSON de-serializer might leave them as null.
-     */
-    private @Nullable Integer posKind2 = null;
-    private @Nullable Integer position2 = null;
-
-    public ShadePosition() {
-    }
-
-    /**
-     * Get the shade's State for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
-     * @return the current state.
-     */
-    public State getState(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
-        State result = getPosition1(shadeCapabilities, posKindCoords);
-        if (result == UnDefType.UNDEF) {
-            result = getPosition2(shadeCapabilities, posKindCoords);
-        }
-        logger.trace("getState(): capabilities={}, coords={} => result={}", shadeCapabilities, posKindCoords, result);
-        return result;
-    }
-
-    /**
-     * Set the shade's position1 value for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
-     * @param percent the new position value.
-     */
-    private void setPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
-        switch (posKindCoords) {
-            case PRIMARY_POSITION:
-                /*
-                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
-                 */
-                if (shadeCapabilities.supportsPrimary() && shadeCapabilities.supportsSecondary()) {
-                    // on dual rail shades constrain percent to not move the lower rail above the upper
-                    State secondary = getState(shadeCapabilities, SECONDARY_POSITION);
-                    if (secondary instanceof PercentType) {
-                        int secPercent = ((PercentType) secondary).intValue();
-                        if (percent < secPercent) {
-                            percent = secPercent;
-                        }
-                    }
-                }
-                posKind1 = posKindCoords.ordinal();
-                position1 = MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE);
-                break;
-
-            case SECONDARY_POSITION:
-                /*
-                 * Secondary, blackout shade a 'Duolite' shade: => INVERTED
-                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
-                 */
-                posKind1 = posKindCoords.ordinal();
-                if (shadeCapabilities.supportsSecondaryOverlapped()) {
-                    position1 = MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE);
-                } else {
-                    position1 = (int) Math.round((double) percent / 100 * MAX_SHADE);
-                }
-                break;
-
-            case VANE_TILT_POSITION:
-                /*
-                 * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
-                 */
-                posKind1 = posKindCoords.ordinal();
-                int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
-                position1 = (int) Math.round((double) percent / 100 * max);
-                break;
-
-            default:
-                posKind1 = CoordinateSystem.NONE.ordinal();
-                position1 = 0;
-        }
-    }
-
-    /**
-     * Get the shade's position1 State for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
-     * @return the State (or UNDEF if not available).
-     */
-    private State getPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
-        switch (posKindCoords) {
-            case PRIMARY_POSITION:
-                /*
-                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
-                 */
-                if (posKindCoords.equals(posKind1)) {
-                    return new PercentType(100 - (int) Math.round((double) position1 / MAX_SHADE * 100));
-                }
-                if (VANE_TILT_POSITION.equals(posKind1) && shadeCapabilities.supportsTiltOnClosed()) {
-                    return PercentType.HUNDRED;
-                }
-                if (SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) {
-                    return PercentType.HUNDRED;
-                }
-                break;
-
-            case SECONDARY_POSITION:
-                /*
-                 * Secondary, blackout shade a 'Duolite' shade: => INVERTED
-                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
-                 */
-                if (posKindCoords.equals(posKind1)) {
-                    if (shadeCapabilities.supportsSecondaryOverlapped()) {
-                        return new PercentType(100 - (int) Math.round((double) position1 / MAX_SHADE * 100));
-                    }
-                    return new PercentType((int) Math.round((double) position1 / MAX_SHADE * 100));
-                }
-                if (!SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) {
-                    return PercentType.ZERO;
-                }
-                break;
-
-            case VANE_TILT_POSITION:
-                /*
-                 * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
-                 *
-                 * If the shades are not open, the vane position is undefined; if the the shades
-                 * are exactly open then the vanes are at zero; otherwise return the actual vane
-                 * position itself
-                 *
-                 * note: sometimes the hub may return a value of position1 > MAX_VANE (seems to
-                 * be a bug in the hub) so we avoid an out of range exception via the Math.min()
-                 * function below..
-                 */
-                if (posKindCoords.equals(posKind1)) {
-                    int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
-                    return new PercentType((int) Math.round((double) Math.min(position1, max) / max * 100));
-                }
-                if (PRIMARY_POSITION.equals(posKind1) && shadeCapabilities.supportsTiltOnClosed()) {
-                    return position1 != 0 ? UnDefType.UNDEF : PercentType.ZERO;
-                }
-                if (SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()
-                        && shadeCapabilities.supportsTiltOnClosed()) {
-                    return PercentType.HUNDRED;
-                }
-                break;
-
-            case ERROR_UNKNOWN:
-            case NONE:
-                // fall through, return UNDEF
-        }
-        return UnDefType.UNDEF;
-    }
-
-    /**
-     * Set the shade's position2 value for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
-     * @param percent the new position value.
-     */
-    private void setPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
-        switch (posKindCoords) {
-            case PRIMARY_POSITION:
-                /*
-                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
-                 */
-                posKind2 = posKindCoords.ordinal();
-                position2 = Integer.valueOf(MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE));
-                break;
-
-            case SECONDARY_POSITION:
-                /*
-                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
-                 */
-                if (shadeCapabilities.supportsPrimary() && shadeCapabilities.supportsSecondary()) {
-                    // on dual rail shades constrain percent to not move the upper rail below the lower
-                    State primary = getState(shadeCapabilities, PRIMARY_POSITION);
-                    if (primary instanceof PercentType) {
-                        int primaryPercent = ((PercentType) primary).intValue();
-                        if (percent > primaryPercent) {
-                            percent = primaryPercent;
-                        }
-                    }
-                }
-                posKind2 = posKindCoords.ordinal();
-                position2 = Integer.valueOf((int) Math.round((double) percent / 100 * MAX_SHADE));
-                break;
-
-            case VANE_TILT_POSITION:
-                posKind2 = posKindCoords.ordinal();
-                int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
-                position2 = Integer.valueOf((int) Math.round((double) percent / 100 * max));
-                break;
-
-            default:
-                posKind2 = null;
-                position2 = null;
-        }
-    }
-
-    /**
-     * Get the shade's position2 State for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
-     * @return the State (or UNDEF if not available).
-     */
-    private State getPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
-        Integer posKind2 = this.posKind2;
-        Integer position2 = this.position2;
-
-        if (position2 == null || posKind2 == null) {
-            return UnDefType.UNDEF;
-        }
-
-        switch (posKindCoords) {
-            case PRIMARY_POSITION:
-                /*
-                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
-                 */
-                if (posKindCoords.equals(posKind2)) {
-                    return new PercentType(100 - (int) Math.round(position2.doubleValue() / MAX_SHADE * 100));
-                }
-                break;
-
-            case SECONDARY_POSITION:
-                /*
-                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
-                 */
-                if (posKindCoords.equals(posKind2)) {
-                    return new PercentType((int) Math.round(position2.doubleValue() / MAX_SHADE * 100));
-                }
-                break;
-
-            /*
-             * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
-             */
-            case VANE_TILT_POSITION:
-                if (posKindCoords.equals(posKind2)) {
-                    int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
-                    return new PercentType((int) Math.round((double) Math.min(position2.intValue(), max) / max * 100));
-                }
-                break;
-
-            case ERROR_UNKNOWN:
-            case NONE:
-                // fall through, return UNDEF
-        }
-        return UnDefType.UNDEF;
-    }
-
-    /**
-     * Detect if the ShadePosition has a posKindN value indicating potential support for a secondary rail.
-     *
-     * @return true if the ShadePosition supports a secondary rail.
-     */
-    public boolean secondaryRailDetected() {
-        return SECONDARY_POSITION.equals(posKind1) || SECONDARY_POSITION.equals(posKind2);
-    }
-
-    /**
-     * Detect if the ShadePosition has both a posKindN value indicating potential support for tilt, AND a posKindN
-     * indicating support for a primary rail. i.e. it potentially supports tilt anywhere functionality.
-     *
-     * @return true if potential support for tilt anywhere functionality was detected.
-     */
-    public boolean tiltAnywhereDetected() {
-        return ((PRIMARY_POSITION.equals(posKind1)) && (VANE_TILT_POSITION.equals(posKind2))
-                || ((PRIMARY_POSITION.equals(posKind2) && (VANE_TILT_POSITION.equals(posKind1)))));
-    }
-
-    /**
-     * Set the shade's position for the given actuator class resp. coordinate system.
-     *
-     * @param shadeCapabilities the shade Thing capabilities.
-     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
-     * @param percent the new position value.
-     * @return this object.
-     */
-    public ShadePosition setPosition(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
-        logger.trace("setPosition(): capabilities={}, coords={}, percent={}", shadeCapabilities, posKindCoords,
-                percent);
-        // if necessary swap the order of position1 and position2
-        if (PRIMARY_POSITION.equals(posKind2) && !PRIMARY_POSITION.equals(posKind1)) {
-            final Integer posKind2Temp = posKind2;
-            final Integer position2Temp = position2;
-            posKind2 = Integer.valueOf(posKind1);
-            position2 = Integer.valueOf(position1);
-            posKind1 = posKind2Temp != null ? posKind2Temp.intValue() : NONE.ordinal();
-            position1 = position2Temp != null ? position2Temp.intValue() : 0;
-        }
-
-        // delete position2 if it has an invalid position kind
-        if (ERROR_UNKNOWN.equals(posKind2) || NONE.equals(posKind2)) {
-            posKind2 = null;
-            position2 = null;
-        }
-
-        // logic to set either position1 or position2
-        switch (posKindCoords) {
-            case PRIMARY_POSITION:
-                if (shadeCapabilities.supportsPrimary()) {
-                    setPosition1(shadeCapabilities, posKindCoords, percent);
-                }
-                break;
-
-            case SECONDARY_POSITION:
-                if (shadeCapabilities.supportsSecondary()) {
-                    if (shadeCapabilities.supportsPrimary()) {
-                        setPosition2(shadeCapabilities, posKindCoords, percent);
-                    } else {
-                        setPosition1(shadeCapabilities, posKindCoords, percent);
-                    }
-                } else if (shadeCapabilities.supportsSecondaryOverlapped()) {
-                    setPosition1(shadeCapabilities, posKindCoords, percent);
-                }
-                break;
-
-            case VANE_TILT_POSITION:
-                if (shadeCapabilities.supportsPrimary()) {
-                    if (shadeCapabilities.supportsTiltOnClosed()) {
-                        setPosition1(shadeCapabilities, posKindCoords, percent);
-                    } else if (shadeCapabilities.supportsTiltAnywhere()) {
-                        setPosition2(shadeCapabilities, posKindCoords, percent);
-                    }
-                } else if (shadeCapabilities.supportsTiltAnywhere()) {
-                    setPosition1(shadeCapabilities, posKindCoords, percent);
-                }
-                break;
-
-            case ERROR_UNKNOWN:
-            case NONE:
-                // fall through, do nothing
-        }
-        return this;
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/SurveyData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/SurveyData.java
deleted file mode 100644 (file)
index bfb5301..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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 com.google.gson.annotations.SerializedName;
-
-/**
- * Survey data of a single Shade, as returned by an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public 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);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Times.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/Times.java
deleted file mode 100644 (file)
index 0dbc911..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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;
-
-/**
- * Times as part of {@link UserData} for an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Times {
-    public @Nullable String timezone;
-    public int localSunriseTimeInMinutes;
-    public int localSunsetTimeInMinutes;
-    public int currentOffset;
-    public double longitude;
-    public double latitude;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/UserData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/UserData.java
deleted file mode 100644 (file)
index 70c33a9..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * 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 java.util.Base64;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * User data for an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class UserData {
-    public @Nullable String hubName;
-    public boolean localTimeDataSet;
-    public boolean enableScheduledEvents;
-    public boolean editingEnabled;
-    public boolean setupCompleted;
-    public @Nullable String gateway;
-    public @Nullable String dns;
-    public boolean staticIp;
-    @SerializedName("_id")
-    public @Nullable String id;
-    public @Nullable Color color;
-    public boolean autoBackup;
-    public @Nullable String ip;
-    public @Nullable String macAddress;
-    public @Nullable String mask;
-    public boolean wireless;
-    public @Nullable HubFirmware firmware;
-    public @Nullable String serialNumber;
-    public @Nullable String rfIDInt;
-    public @Nullable String rfID;
-    public int rfStatus;
-    public @Nullable Times times;
-    public @Nullable String brand;
-    public boolean rcUp;
-    public boolean remoteConnectEnabled;
-
-    public String getHubName() {
-        return hubName != null ? new String(Base64.getDecoder().decode(hubName)) : "";
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterBlinking.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterBlinking.java
deleted file mode 100644 (file)
index ea3886a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * State of a single Repeater for being updated by an HD PowerView Hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class RepeaterBlinking {
-    public Repeater repeater;
-
-    public class Repeater {
-        public int id;
-        public boolean blinkEnabled;
-
-        public Repeater(int id, boolean enable) {
-            this.id = id;
-            this.blinkEnabled = enable;
-        }
-    }
-
-    public RepeaterBlinking(int id, boolean enable) {
-        repeater = new Repeater(id, enable);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterColor.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/RepeaterColor.java
deleted file mode 100644 (file)
index 960e95f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hdpowerview.internal.api.Color;
-
-/**
- * Color state of a single Repeater for being updated by an HD PowerView Hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class RepeaterColor {
-    public Repeater repeater;
-
-    public class Repeater {
-        public int id;
-        public Color color;
-
-        public Repeater(int id, Color color) {
-            this.id = id;
-            this.color = color;
-        }
-    }
-
-    public RepeaterColor(int id, Color color) {
-        repeater = new Repeater(id, color);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeCalibrate.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeCalibrate.java
deleted file mode 100644 (file)
index e1ec80e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * A request to calibrate a shade
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class ShadeCalibrate {
-
-    public ShadeMotion shade;
-
-    public ShadeCalibrate() {
-        this.shade = new ShadeMotion(ShadeMotion.Type.CALIBRATE);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeJog.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeJog.java
deleted file mode 100644 (file)
index 71fb047..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * A request to jog a shade for identification
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class ShadeJog {
-
-    public ShadeMotion shade;
-
-    public ShadeJog() {
-        this.shade = new ShadeMotion(ShadeMotion.Type.JOG);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMotion.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMotion.java
deleted file mode 100644 (file)
index c6b16a0..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * A motion directive for a shade
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-class ShadeMotion {
-
-    public enum Type {
-        STOP("stop"),
-        JOG("jog"),
-        CALIBRATE("calibrate");
-
-        private String motion;
-
-        Type(String motion) {
-            this.motion = motion;
-        }
-
-        public String getMotion() {
-            return this.motion;
-        }
-    }
-
-    public String motion;
-
-    public ShadeMotion(Type motionType) {
-        this.motion = motionType.getMotion();
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMove.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeMove.java
deleted file mode 100644 (file)
index fe688f4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
-
-/**
- * A request to set the position of a shade
- *
- * @author Andy Lintner - Initial contribution
- */
-@NonNullByDefault
-public class ShadeMove {
-
-    public ShadePositions shade;
-
-    public ShadeMove(ShadePosition position) {
-        this.shade = new ShadePositions(position);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadePositions.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadePositions.java
deleted file mode 100644 (file)
index 1c544c0..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
-
-/**
- * The position of a shade to set
- *
- * @author Andy Lintner - Initial contribution
- */
-@NonNullByDefault
-class ShadePositions {
-
-    public ShadePosition positions;
-
-    public ShadePositions(ShadePosition position) {
-        this.positions = position;
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeStop.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/requests/ShadeStop.java
deleted file mode 100644 (file)
index ed7ab4c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.requests;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-
-/**
- * A request to stop the movement of a shade
- *
- * @author Andrew Fiddian-Green - Initial contribution
- */
-@NonNullByDefault
-public class ShadeStop {
-
-    public ShadeMotion shade;
-
-    public ShadeStop() {
-        this.shade = new ShadeMotion(ShadeMotion.Type.STOP);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/FirmwareVersion.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/FirmwareVersion.java
deleted file mode 100644 (file)
index d046f06..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * 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.responses;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.api.HubFirmware;
-
-/**
- * Firmware information for an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class FirmwareVersion {
-    @Nullable
-    public HubFirmware firmware;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeater.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeater.java
deleted file mode 100644 (file)
index 55ba666..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * 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.responses;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * State of a single Repeater, as returned by an HD PowerView Hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Repeater {
-    public @Nullable RepeaterData repeater;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/RepeaterData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/RepeaterData.java
deleted file mode 100644 (file)
index a083f91..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * 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.responses;
-
-import java.util.Base64;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.api.Color;
-import org.openhab.binding.hdpowerview.internal.api.Firmware;
-
-/**
- * Repeater data for a single Repeater, as returned by an HD PowerView Hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class RepeaterData {
-    public int id;
-    public @Nullable String name;
-    public int roomId;
-    public int groupId;
-    public boolean blinkEnabled;
-    public @Nullable Firmware firmware;
-    public @Nullable Color color;
-
-    public String getName() {
-        return new String(Base64.getDecoder().decode(name));
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeaters.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Repeaters.java
deleted file mode 100644 (file)
index 8b5f15b..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * 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.responses;
-
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * Repeaters connected to an HD PowerView Hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Repeaters {
-    public @Nullable List<RepeaterData> repeaterData;
-    public @Nullable List<Integer> repeaterIds;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/SceneCollections.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/SceneCollections.java
deleted file mode 100644 (file)
index bef9e94..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * 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.responses;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * State of all Scene Collections in an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class SceneCollections {
-
-    public @Nullable List<SceneCollection> sceneCollectionData;
-    public @Nullable List<Integer> sceneCollectionIds;
-
-    /*
-     * the following SuppressWarnings annotation is because the Eclipse compiler
-     * does NOT expect a NonNullByDefault annotation on the inner class, since it is
-     * implicitly inherited from the outer class, whereas the Maven compiler always
-     * requires an explicit NonNullByDefault annotation on all classes
-     */
-    @SuppressWarnings("null")
-    @NonNullByDefault
-    public static class SceneCollection implements Comparable<SceneCollection> {
-        public int id;
-        public @Nullable String name;
-        public int order;
-        public int colorId;
-        public int iconId;
-
-        @Override
-        public boolean equals(@Nullable Object o) {
-            if (o == this) {
-                return true;
-            }
-            if (!(o instanceof SceneCollection)) {
-                return false;
-            }
-            SceneCollection other = (SceneCollection) o;
-
-            return this.id == other.id && this.name.equals(other.name) && this.order == other.order
-                    && this.colorId == other.colorId && this.iconId == other.iconId;
-        }
-
-        @Override
-        public final int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + id;
-            result = prime * result + (name == null ? 0 : name.hashCode());
-            result = prime * result + order;
-            result = prime * result + colorId;
-            result = prime * result + iconId;
-
-            return result;
-        }
-
-        @Override
-        public int compareTo(SceneCollection other) {
-            return Integer.compare(order, other.order);
-        }
-
-        public String getName() {
-            return new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8);
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Scenes.java
deleted file mode 100644 (file)
index 5cb25a8..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * 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.responses;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * State of all Scenes in an HD PowerView hub
- *
- * @author Andy Lintner - Initial contribution
- */
-@NonNullByDefault
-public class Scenes {
-
-    public @Nullable List<Scene> sceneData;
-    public @Nullable List<Integer> sceneIds;
-
-    /*
-     * the following SuppressWarnings annotation is because the Eclipse compiler
-     * does NOT expect a NonNullByDefault annotation on the inner class, since it is
-     * implicitly inherited from the outer class, whereas the Maven compiler always
-     * requires an explicit NonNullByDefault annotation on all classes
-     */
-    @SuppressWarnings("null")
-    @NonNullByDefault
-    public static class Scene implements Comparable<Scene> {
-        public int id;
-        public @Nullable String name;
-        public int roomId;
-        public int order;
-        public int colorId;
-        public int iconId;
-
-        @Override
-        public boolean equals(@Nullable Object o) {
-            if (o == this) {
-                return true;
-            }
-            if (!(o instanceof Scene)) {
-                return false;
-            }
-            Scene other = (Scene) o;
-
-            return this.id == other.id && this.name.equals(other.name) && this.roomId == other.roomId
-                    && this.order == other.order && this.colorId == other.colorId && this.iconId == other.iconId;
-        }
-
-        @Override
-        public final int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + id;
-            result = prime * result + (name == null ? 0 : name.hashCode());
-            result = prime * result + roomId;
-            result = prime * result + order;
-            result = prime * result + colorId;
-            result = prime * result + iconId;
-
-            return result;
-        }
-
-        @Override
-        public int compareTo(Scene other) {
-            return Integer.compare(order, other.order);
-        }
-
-        public String getName() {
-            return new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8);
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/ScheduledEvents.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/ScheduledEvents.java
deleted file mode 100644 (file)
index e7ae6ac..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * 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.responses;
-
-import java.time.DayOfWeek;
-import java.util.EnumSet;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * State of all Scheduled Events in an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class ScheduledEvents {
-
-    public static final EnumSet<DayOfWeek> WEEKDAYS = EnumSet.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY,
-            DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY);
-
-    public static final EnumSet<DayOfWeek> WEEKENDS = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
-
-    public static final int SCHEDULED_EVENT_TYPE_TIME = 0;
-    public static final int SCHEDULED_EVENT_TYPE_SUNRISE = 1;
-    public static final int SCHEDULED_EVENT_TYPE_SUNSET = 2;
-
-    public @Nullable List<ScheduledEvent> scheduledEventData;
-    public @Nullable List<Integer> scheduledEventIds;
-
-    /*
-     * the following SuppressWarnings annotation is because the Eclipse compiler
-     * does NOT expect a NonNullByDefault annotation on the inner class, since it is
-     * implicitly inherited from the outer class, whereas the Maven compiler always
-     * requires an explicit NonNullByDefault annotation on all classes
-     */
-    @SuppressWarnings("null")
-    @NonNullByDefault
-    public static class ScheduledEvent {
-        public int id;
-        public boolean enabled;
-        public int sceneId;
-        public int sceneCollectionId;
-        public boolean daySunday;
-        public boolean dayMonday;
-        public boolean dayTuesday;
-        public boolean dayWednesday;
-        public boolean dayThursday;
-        public boolean dayFriday;
-        public boolean daySaturday;
-        public int eventType;
-        public int hour;
-        public int minute;
-
-        @Override
-        public boolean equals(@Nullable Object o) {
-            if (o == this) {
-                return true;
-            }
-            if (!(o instanceof ScheduledEvent)) {
-                return false;
-            }
-            ScheduledEvent other = (ScheduledEvent) o;
-
-            return this.id == other.id && this.enabled == other.enabled && this.sceneId == other.sceneId
-                    && this.sceneCollectionId == other.sceneCollectionId && this.daySunday == other.daySunday
-                    && this.dayMonday == other.dayMonday && this.dayTuesday == other.dayTuesday
-                    && this.dayWednesday == other.dayWednesday && this.dayThursday == other.dayThursday
-                    && this.dayFriday == other.dayFriday && this.daySaturday == other.daySaturday
-                    && this.eventType == other.eventType && this.hour == other.hour && this.minute == other.minute;
-        }
-
-        @Override
-        public final int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + id;
-            result = prime * result + (enabled ? 1 : 0);
-            result = prime * result + sceneId;
-            result = prime * result + sceneCollectionId;
-            result = prime * result + (daySunday ? 1 : 0);
-            result = prime * result + (dayMonday ? 1 : 0);
-            result = prime * result + (dayTuesday ? 1 : 0);
-            result = prime * result + (dayWednesday ? 1 : 0);
-            result = prime * result + (dayThursday ? 1 : 0);
-            result = prime * result + (dayFriday ? 1 : 0);
-            result = prime * result + (daySaturday ? 1 : 0);
-            result = prime * result + eventType;
-            result = prime * result + hour;
-            result = prime * result + minute;
-
-            return result;
-        }
-
-        public EnumSet<DayOfWeek> getDays() {
-            EnumSet<DayOfWeek> days = EnumSet.noneOf(DayOfWeek.class);
-            if (daySunday) {
-                days.add(DayOfWeek.SUNDAY);
-            }
-            if (dayMonday) {
-                days.add(DayOfWeek.MONDAY);
-            }
-            if (dayTuesday) {
-                days.add(DayOfWeek.TUESDAY);
-            }
-            if (dayWednesday) {
-                days.add(DayOfWeek.WEDNESDAY);
-            }
-            if (dayThursday) {
-                days.add(DayOfWeek.THURSDAY);
-            }
-            if (dayFriday) {
-                days.add(DayOfWeek.FRIDAY);
-            }
-            if (daySaturday) {
-                days.add(DayOfWeek.SATURDAY);
-            }
-            return days;
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shade.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Shade.java
deleted file mode 100644 (file)
index 69da937..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * 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.responses;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
-
-/**
- * State of a single Shade, as returned by an HD PowerView hub
- *
- * @author Andrew Fiddian-Green - Initial contribution
- */
-@NonNullByDefault
-public class Shade {
-
-    public @Nullable ShadeData shade;
-}
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
deleted file mode 100644 (file)
index 2746523..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * 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.responses;
-
-import java.util.Base64;
-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;
-
-/**
- * State of all Shades, as returned by an HD PowerView hub
- *
- * @author Andy Lintner - Initial contribution
- */
-@NonNullByDefault
-public class Shades {
-
-    public @Nullable List<ShadeData> shadeData;
-    public @Nullable List<Integer> shadeIds;
-
-    /*
-     * the following SuppressWarnings annotation is because the Eclipse compiler
-     * does NOT expect a NonNullByDefault annotation on the inner class, since it is
-     * implicitly inherited from the outer class, whereas the Maven compiler always
-     * requires an explicit NonNullByDefault annotation on all classes
-     */
-    @SuppressWarnings("null")
-    @NonNullByDefault
-    public static class ShadeData {
-        public int id;
-        public @Nullable String name;
-        public int roomId;
-        public int groupId;
-        public int order;
-        public int type;
-        public double batteryStrength;
-        public int batteryStatus;
-        public boolean batteryIsLow;
-        public @Nullable ShadePosition positions;
-        public @Nullable Boolean timedOut;
-        public int signalStrength;
-        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/api/responses/Survey.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/Survey.java
deleted file mode 100644 (file)
index 21709fe..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * 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.responses;
-
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.api.SurveyData;
-
-import com.google.gson.annotations.SerializedName;
-
-/**
- * Survey data of a single Shade, as returned by an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class Survey {
-    @SerializedName("shade_id")
-    public int shadeId;
-    @SerializedName("survey")
-    public @Nullable List<SurveyData> surveyData;
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/UserDataResponse.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/api/responses/UserDataResponse.java
deleted file mode 100644 (file)
index 3509ffd..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * 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.responses;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.binding.hdpowerview.internal.api.UserData;
-
-/**
- * Response with {@link UserData} for an HD PowerView hub
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class UserDataResponse {
-    public @Nullable UserData userData;
-}
index 10782b22b991c928560908712f4bde039d9e1870..214734694685c8238108a28e417ca5c40fdfe9da 100644 (file)
@@ -25,10 +25,9 @@ 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.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents.ScheduledEvent;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.ScheduledEvent;
 import org.openhab.core.library.CoreItemFactory;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelGroupUID;
@@ -193,10 +192,10 @@ public class AutomationChannelBuilder extends BaseChannelBuilder {
         String timeString, daysString;
 
         switch (scheduledEvent.eventType) {
-            case ScheduledEvents.SCHEDULED_EVENT_TYPE_TIME:
+            case ScheduledEvent.SCHEDULED_EVENT_TYPE_TIME:
                 timeString = LocalTime.of(scheduledEvent.hour, scheduledEvent.minute).toString();
                 break;
-            case ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE:
+            case ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE:
                 if (scheduledEvent.minute == 0) {
                     timeString = translationProvider.getText("dynamic-channel.automation.at-sunrise");
                 } else if (scheduledEvent.minute < 0) {
@@ -207,7 +206,7 @@ public class AutomationChannelBuilder extends BaseChannelBuilder {
                             getFormattedTimeOffset(scheduledEvent.minute));
                 }
                 break;
-            case ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNSET:
+            case ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNSET:
                 if (scheduledEvent.minute == 0) {
                     timeString = translationProvider.getText("dynamic-channel.automation.at-sunset");
                 } else if (scheduledEvent.minute < 0) {
@@ -225,9 +224,9 @@ public class AutomationChannelBuilder extends BaseChannelBuilder {
         EnumSet<DayOfWeek> days = scheduledEvent.getDays();
         if (EnumSet.allOf(DayOfWeek.class).equals(days)) {
             daysString = translationProvider.getText("dynamic-channel.automation.all-days");
-        } else if (ScheduledEvents.WEEKDAYS.equals(days)) {
+        } else if (ScheduledEvent.WEEKDAYS.equals(days)) {
             daysString = translationProvider.getText("dynamic-channel.automation.weekdays");
-        } else if (ScheduledEvents.WEEKENDS.equals(days)) {
+        } else if (ScheduledEvent.WEEKENDS.equals(days)) {
             daysString = translationProvider.getText("dynamic-channel.automation.weekends");
         } else {
             StringJoiner joiner = new StringJoiner(", ");
index 01c05137e9eced3e22c54c3345c9b1d3b6518023..213a60def07d5439c861cfaee65112434395946b 100644 (file)
@@ -18,7 +18,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.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
 import org.openhab.core.library.CoreItemFactory;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelGroupUID;
index 4cc4436ea2f32eda9abfea4eaa9a51ab5f745b60..d4dbd2cde6ce6817b82f1a45b35736007b38b5c7 100644 (file)
@@ -18,7 +18,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.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
 import org.openhab.core.library.CoreItemFactory;
 import org.openhab.core.thing.Channel;
 import org.openhab.core.thing.ChannelGroupUID;
index 4252f8d57bb2bdc2fa8ab5a11a47a2feb962e962..2e16968bab892becc06bde18231eaf3d53268bee 100644 (file)
@@ -19,8 +19,8 @@ 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.responses.RepeaterData;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
 import org.openhab.binding.hdpowerview.internal.handler.HDPowerViewHubHandler;
 import org.openhab.core.io.console.Console;
index 98d108befcfb15944c8d6951cf4cf7098c453a90..65bc262365fb6b993c6300542fda7c122e108a35 100644 (file)
@@ -21,13 +21,13 @@ 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.responses.RepeaterData;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewRepeaterConfiguration;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration;
 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shades;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/BatteryKind.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/BatteryKind.java
new file mode 100644 (file)
index 0000000..a3b79bf
--- /dev/null
@@ -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.dto;
+
+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/dto/Color.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Color.java
new file mode 100644 (file)
index 0000000..7179690
--- /dev/null
@@ -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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.library.types.HSBType;
+
+/**
+ * Color and brightness information for HD PowerView repeater
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Color {
+    public int brightness;
+    public int red;
+    public int green;
+    public int blue;
+
+    public Color(int brightness, HSBType hsbType) {
+        this.brightness = brightness;
+        int rgb = hsbType.getRGB();
+        java.awt.Color color = new java.awt.Color(rgb);
+        red = color.getRed();
+        green = color.getGreen();
+        blue = color.getBlue();
+    }
+
+    public Color(int brightness, java.awt.Color color) {
+        this.brightness = brightness;
+        red = color.getRed();
+        green = color.getGreen();
+        blue = color.getBlue();
+    }
+
+    public Color(int brightness, int red, int green, int blue) {
+        this.brightness = brightness;
+        this.red = red;
+        this.green = green;
+        this.blue = blue;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%d.%d.%d/%d%%", red, green, blue, brightness);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/CoordinateSystem.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/CoordinateSystem.java
new file mode 100644 (file)
index 0000000..47c4a1b
--- /dev/null
@@ -0,0 +1,111 @@
+/**
+ * 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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Shade coordinate system (a.k.a. position kind), as returned by the HD PowerView hub.
+ *
+ * @param NONE a coordinate system that does not refer to any type of physical rail.
+ * @param PRIMARY_POSITION primary rail, whose coordinate value 0 means shade is closed.
+ * @param SECONDARY_POSITION secondary rail, whose coordinate value 0 means shade is open.
+ * @param VANE_TILT_POSITION vane/tilt operator, whose coordinate system is for vanes.
+ * @param ERROR_UNKNOWN unsupported coordinate system.
+ *
+ * @author Andy Lintner - Initial contribution of the original enum called
+ *         ShadePositionKind
+ *
+ * @author Andrew Fiddian-Green - Rewritten as a new enum called
+ *         CoordinateSystem to support secondary rail positions and be more
+ *         explicit on coordinate directions and ranges
+ */
+@NonNullByDefault
+public enum CoordinateSystem {
+    /*-
+     * Specifies the coordinate system used for the position of the shade. Top-down
+     * shades are in the same coordinate space as bottom-up shades. Shade position
+     * values for top-down shades would be reversed for bottom-up shades. For
+     * example, since 65535 is the open value for a bottom-up shade, it is the
+     * closed value for a top-down shade. The top-down/bottom-up shade is different
+     * in that instead of the top and bottom rail operating in one coordinate space
+     * like the top-down and the bottom-up, it operates in two where the top
+     * (middle) rail closed value is 0 and the bottom (primary) rail closed position
+     * is also 0 and fully open for both is 65535
+     *
+     * The position element can take on multiple states depending on the family of
+     * shade under control.
+     *
+     * The ranges of position integer values are
+     *      shades: 0..65535
+     *      vanes: 0..32767
+     *
+     * Shade fully up: (top-down: open, bottom-up: closed)
+     *      posKind: 1 {ZERO_IS_CLOSED}
+     *      position: 65535
+     *
+     * Shade and vane fully down: (top-down: closed, bottom-up: open)
+     *      posKind: 1 {ZERO_IS_CLOSED}
+     *      position1: 0
+     *
+     * ALTERNATE: Shade and vane fully down: (top-down: closed, bottom-up: open)
+     *      posKind: 3 {VANE_COORDS}
+     *      position: 0
+     *
+     * Shade fully down (closed) and vane fully up (open):
+     *      posKind: 3 {VANE_COORDS}
+     *      position: 32767
+     *
+     * Dual action, secondary top-down shade fully up (closed):
+     *      posKind: 2 {ZERO_IS_OPEN}
+     *      position: 0
+     *
+     * Dual action, secondary top-down shade fully down (open):
+     *      posKind: 2 {ZERO_IS_OPEN}
+     *      position: 65535
+     *
+     */
+    NONE,
+    PRIMARY_POSITION,
+    SECONDARY_POSITION,
+    VANE_TILT_POSITION,
+    ERROR_UNKNOWN;
+
+    public static final int MAX_SHADE = 65535;
+    public static final int MAX_VANE = 32767;
+
+    /**
+     * Converts an HD PowerView posKind integer value to a CoordinateSystem enum value.
+     *
+     * @param posKind input integer value.
+     * @return corresponding CoordinateSystem enum.
+     */
+    public static CoordinateSystem fromPosKind(int posKind) {
+        try {
+            return CoordinateSystem.values()[posKind];
+        } catch (ArrayIndexOutOfBoundsException e) {
+            return ERROR_UNKNOWN;
+        }
+    }
+
+    /**
+     * Check if the coordinate system matches the given posKind.
+     *
+     * @param posKind
+     * @return true if equal.
+     */
+    public boolean equals(@Nullable Integer posKind) {
+        return (posKind != null) && (posKind.intValue() == ordinal());
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Firmware.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Firmware.java
new file mode 100644 (file)
index 0000000..c17d76e
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * 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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Firmware version information for HD PowerView components
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Firmware {
+    @Nullable
+    public String name;
+    public int revision;
+    public int subRevision;
+    public int build;
+
+    @Override
+    public String toString() {
+        return String.format("%d.%d.%d", revision, subRevision, build);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/HubFirmware.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/HubFirmware.java
new file mode 100644 (file)
index 0000000..5deb23b
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * 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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Firmware information for an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class HubFirmware {
+    @Nullable
+    public Firmware mainProcessor;
+    @Nullable
+    public Firmware radio;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Scene.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Scene.java
new file mode 100644 (file)
index 0000000..daf5601
--- /dev/null
@@ -0,0 +1,73 @@
+/**
+ * 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.dto;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * State of a single Scene, as returned by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Scene implements Comparable<Scene> {
+    public int id;
+    public @Nullable String name;
+    public int roomId;
+    public int order;
+    public int colorId;
+    public int iconId;
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof Scene)) {
+            return false;
+        }
+        Scene other = (Scene) o;
+
+        return this.id == other.id && Objects.equals(name, other.name) && this.roomId == other.roomId
+                && this.order == other.order && this.colorId == other.colorId && this.iconId == other.iconId;
+    }
+
+    @Override
+    public final int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        String name = this.name;
+        result = prime * result + id;
+        result = prime * result + (name == null ? 0 : name.hashCode());
+        result = prime * result + roomId;
+        result = prime * result + order;
+        result = prime * result + colorId;
+        result = prime * result + iconId;
+
+        return result;
+    }
+
+    @Override
+    public int compareTo(Scene other) {
+        return Integer.compare(order, other.order);
+    }
+
+    public String getName() {
+        return new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SceneCollection.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SceneCollection.java
new file mode 100644 (file)
index 0000000..35e4f3c
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ * 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.dto;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * State of a single Scene Collection, as returned by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class SceneCollection implements Comparable<SceneCollection> {
+    public int id;
+    public @Nullable String name;
+    public int order;
+    public int colorId;
+    public int iconId;
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof SceneCollection)) {
+            return false;
+        }
+        SceneCollection other = (SceneCollection) o;
+
+        return this.id == other.id && Objects.equals(name, other.name) && this.order == other.order
+                && this.colorId == other.colorId && this.iconId == other.iconId;
+    }
+
+    @Override
+    public final int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        String name = this.name;
+        result = prime * result + id;
+        result = prime * result + (name == null ? 0 : name.hashCode());
+        result = prime * result + order;
+        result = prime * result + colorId;
+        result = prime * result + iconId;
+
+        return result;
+    }
+
+    @Override
+    public int compareTo(SceneCollection other) {
+        return Integer.compare(order, other.order);
+    }
+
+    public String getName() {
+        return new String(Base64.getDecoder().decode(name), StandardCharsets.UTF_8);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ScheduledEvent.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ScheduledEvent.java
new file mode 100644 (file)
index 0000000..16c9de0
--- /dev/null
@@ -0,0 +1,117 @@
+/**
+ * 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.dto;
+
+import java.time.DayOfWeek;
+import java.util.EnumSet;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * State of a single Scheduled Event, as returned by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class ScheduledEvent {
+    public static final EnumSet<DayOfWeek> WEEKDAYS = EnumSet.of(DayOfWeek.MONDAY, DayOfWeek.TUESDAY,
+            DayOfWeek.WEDNESDAY, DayOfWeek.THURSDAY, DayOfWeek.FRIDAY);
+
+    public static final EnumSet<DayOfWeek> WEEKENDS = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
+
+    public static final int SCHEDULED_EVENT_TYPE_TIME = 0;
+    public static final int SCHEDULED_EVENT_TYPE_SUNRISE = 1;
+    public static final int SCHEDULED_EVENT_TYPE_SUNSET = 2;
+
+    public int id;
+    public boolean enabled;
+    public int sceneId;
+    public int sceneCollectionId;
+    public boolean daySunday;
+    public boolean dayMonday;
+    public boolean dayTuesday;
+    public boolean dayWednesday;
+    public boolean dayThursday;
+    public boolean dayFriday;
+    public boolean daySaturday;
+    public int eventType;
+    public int hour;
+    public int minute;
+
+    @Override
+    public boolean equals(@Nullable Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof ScheduledEvent)) {
+            return false;
+        }
+        ScheduledEvent other = (ScheduledEvent) o;
+
+        return this.id == other.id && this.enabled == other.enabled && this.sceneId == other.sceneId
+                && this.sceneCollectionId == other.sceneCollectionId && this.daySunday == other.daySunday
+                && this.dayMonday == other.dayMonday && this.dayTuesday == other.dayTuesday
+                && this.dayWednesday == other.dayWednesday && this.dayThursday == other.dayThursday
+                && this.dayFriday == other.dayFriday && this.daySaturday == other.daySaturday
+                && this.eventType == other.eventType && this.hour == other.hour && this.minute == other.minute;
+    }
+
+    @Override
+    public final int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + id;
+        result = prime * result + (enabled ? 1 : 0);
+        result = prime * result + sceneId;
+        result = prime * result + sceneCollectionId;
+        result = prime * result + (daySunday ? 1 : 0);
+        result = prime * result + (dayMonday ? 1 : 0);
+        result = prime * result + (dayTuesday ? 1 : 0);
+        result = prime * result + (dayWednesday ? 1 : 0);
+        result = prime * result + (dayThursday ? 1 : 0);
+        result = prime * result + (dayFriday ? 1 : 0);
+        result = prime * result + (daySaturday ? 1 : 0);
+        result = prime * result + eventType;
+        result = prime * result + hour;
+        result = prime * result + minute;
+
+        return result;
+    }
+
+    public EnumSet<DayOfWeek> getDays() {
+        EnumSet<DayOfWeek> days = EnumSet.noneOf(DayOfWeek.class);
+        if (daySunday) {
+            days.add(DayOfWeek.SUNDAY);
+        }
+        if (dayMonday) {
+            days.add(DayOfWeek.MONDAY);
+        }
+        if (dayTuesday) {
+            days.add(DayOfWeek.TUESDAY);
+        }
+        if (dayWednesday) {
+            days.add(DayOfWeek.WEDNESDAY);
+        }
+        if (dayThursday) {
+            days.add(DayOfWeek.THURSDAY);
+        }
+        if (dayFriday) {
+            days.add(DayOfWeek.FRIDAY);
+        }
+        if (daySaturday) {
+            days.add(DayOfWeek.SATURDAY);
+        }
+        return days;
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadeData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadeData.java
new file mode 100644 (file)
index 0000000..0334267
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * 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.dto;
+
+import java.util.Base64;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Shade data for a single Shade, as returned by an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class ShadeData {
+    public int id;
+    public @Nullable String name;
+    public int roomId;
+    public int groupId;
+    public int order;
+    public int type;
+    public double batteryStrength;
+    public int batteryStatus;
+    public boolean batteryIsLow;
+    public @Nullable ShadePosition positions;
+    public @Nullable Boolean timedOut;
+    public int signalStrength;
+    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/dto/ShadePosition.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/ShadePosition.java
new file mode 100644 (file)
index 0000000..d6bced8
--- /dev/null
@@ -0,0 +1,381 @@
+/**
+ * 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.dto;
+
+import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The position of a single shade, as returned by the HD PowerView hub
+ *
+ * @author Andy Lintner - Initial contribution
+ * @author Andrew Fiddian-Green - Added support for secondary rail positions
+ */
+@NonNullByDefault
+public class ShadePosition {
+
+    private final transient Logger logger = LoggerFactory.getLogger(ShadePosition.class);
+
+    /**
+     * Primary actuator position.
+     */
+    private int posKind1;
+    private int position1;
+
+    /**
+     * Secondary actuator position.
+     *
+     * Here we have to use Integer objects rather than just int primitives because these are secondary optional position
+     * elements in the JSON payload, so the GSON de-serializer might leave them as null.
+     */
+    private @Nullable Integer posKind2 = null;
+    private @Nullable Integer position2 = null;
+
+    public ShadePosition() {
+    }
+
+    /**
+     * Get the shade's State for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
+     * @return the current state.
+     */
+    public State getState(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
+        State result = getPosition1(shadeCapabilities, posKindCoords);
+        if (result == UnDefType.UNDEF) {
+            result = getPosition2(shadeCapabilities, posKindCoords);
+        }
+        logger.trace("getState(): capabilities={}, coords={} => result={}", shadeCapabilities, posKindCoords, result);
+        return result;
+    }
+
+    /**
+     * Set the shade's position1 value for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
+     * @param percent the new position value.
+     */
+    private void setPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
+        switch (posKindCoords) {
+            case PRIMARY_POSITION:
+                /*
+                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
+                 */
+                if (shadeCapabilities.supportsPrimary() && shadeCapabilities.supportsSecondary()) {
+                    // on dual rail shades constrain percent to not move the lower rail above the upper
+                    State secondary = getState(shadeCapabilities, SECONDARY_POSITION);
+                    if (secondary instanceof PercentType) {
+                        int secPercent = ((PercentType) secondary).intValue();
+                        if (percent < secPercent) {
+                            percent = secPercent;
+                        }
+                    }
+                }
+                posKind1 = posKindCoords.ordinal();
+                position1 = MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE);
+                break;
+
+            case SECONDARY_POSITION:
+                /*
+                 * Secondary, blackout shade a 'Duolite' shade: => INVERTED
+                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
+                 */
+                posKind1 = posKindCoords.ordinal();
+                if (shadeCapabilities.supportsSecondaryOverlapped()) {
+                    position1 = MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE);
+                } else {
+                    position1 = (int) Math.round((double) percent / 100 * MAX_SHADE);
+                }
+                break;
+
+            case VANE_TILT_POSITION:
+                /*
+                 * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
+                 */
+                posKind1 = posKindCoords.ordinal();
+                int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
+                position1 = (int) Math.round((double) percent / 100 * max);
+                break;
+
+            default:
+                posKind1 = CoordinateSystem.NONE.ordinal();
+                position1 = 0;
+        }
+    }
+
+    /**
+     * Get the shade's position1 State for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
+     * @return the State (or UNDEF if not available).
+     */
+    private State getPosition1(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
+        switch (posKindCoords) {
+            case PRIMARY_POSITION:
+                /*
+                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
+                 */
+                if (posKindCoords.equals(posKind1)) {
+                    return new PercentType(100 - (int) Math.round((double) position1 / MAX_SHADE * 100));
+                }
+                if (VANE_TILT_POSITION.equals(posKind1) && shadeCapabilities.supportsTiltOnClosed()) {
+                    return PercentType.HUNDRED;
+                }
+                if (SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) {
+                    return PercentType.HUNDRED;
+                }
+                break;
+
+            case SECONDARY_POSITION:
+                /*
+                 * Secondary, blackout shade a 'Duolite' shade: => INVERTED
+                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
+                 */
+                if (posKindCoords.equals(posKind1)) {
+                    if (shadeCapabilities.supportsSecondaryOverlapped()) {
+                        return new PercentType(100 - (int) Math.round((double) position1 / MAX_SHADE * 100));
+                    }
+                    return new PercentType((int) Math.round((double) position1 / MAX_SHADE * 100));
+                }
+                if (!SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) {
+                    return PercentType.ZERO;
+                }
+                break;
+
+            case VANE_TILT_POSITION:
+                /*
+                 * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
+                 *
+                 * If the shades are not open, the vane position is undefined; if the the shades
+                 * are exactly open then the vanes are at zero; otherwise return the actual vane
+                 * position itself
+                 *
+                 * note: sometimes the hub may return a value of position1 > MAX_VANE (seems to
+                 * be a bug in the hub) so we avoid an out of range exception via the Math.min()
+                 * function below..
+                 */
+                if (posKindCoords.equals(posKind1)) {
+                    int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
+                    return new PercentType((int) Math.round((double) Math.min(position1, max) / max * 100));
+                }
+                if (PRIMARY_POSITION.equals(posKind1) && shadeCapabilities.supportsTiltOnClosed()) {
+                    return position1 != 0 ? UnDefType.UNDEF : PercentType.ZERO;
+                }
+                if (SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()
+                        && shadeCapabilities.supportsTiltOnClosed()) {
+                    return PercentType.HUNDRED;
+                }
+                break;
+
+            case ERROR_UNKNOWN:
+            case NONE:
+                // fall through, return UNDEF
+        }
+        return UnDefType.UNDEF;
+    }
+
+    /**
+     * Set the shade's position2 value for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
+     * @param percent the new position value.
+     */
+    private void setPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
+        switch (posKindCoords) {
+            case PRIMARY_POSITION:
+                /*
+                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
+                 */
+                posKind2 = posKindCoords.ordinal();
+                position2 = Integer.valueOf(MAX_SHADE - (int) Math.round((double) percent / 100 * MAX_SHADE));
+                break;
+
+            case SECONDARY_POSITION:
+                /*
+                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
+                 */
+                if (shadeCapabilities.supportsPrimary() && shadeCapabilities.supportsSecondary()) {
+                    // on dual rail shades constrain percent to not move the upper rail below the lower
+                    State primary = getState(shadeCapabilities, PRIMARY_POSITION);
+                    if (primary instanceof PercentType) {
+                        int primaryPercent = ((PercentType) primary).intValue();
+                        if (percent > primaryPercent) {
+                            percent = primaryPercent;
+                        }
+                    }
+                }
+                posKind2 = posKindCoords.ordinal();
+                position2 = Integer.valueOf((int) Math.round((double) percent / 100 * MAX_SHADE));
+                break;
+
+            case VANE_TILT_POSITION:
+                posKind2 = posKindCoords.ordinal();
+                int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
+                position2 = Integer.valueOf((int) Math.round((double) percent / 100 * max));
+                break;
+
+            default:
+                posKind2 = null;
+                position2 = null;
+        }
+    }
+
+    /**
+     * Get the shade's position2 State for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be returned.
+     * @return the State (or UNDEF if not available).
+     */
+    private State getPosition2(Capabilities shadeCapabilities, CoordinateSystem posKindCoords) {
+        Integer posKind2 = this.posKind2;
+        Integer position2 = this.position2;
+
+        if (position2 == null || posKind2 == null) {
+            return UnDefType.UNDEF;
+        }
+
+        switch (posKindCoords) {
+            case PRIMARY_POSITION:
+                /*
+                 * Primary rail of a bottom-up shade, or lower rail of a dual action shade: => INVERTED
+                 */
+                if (posKindCoords.equals(posKind2)) {
+                    return new PercentType(100 - (int) Math.round(position2.doubleValue() / MAX_SHADE * 100));
+                }
+                break;
+
+            case SECONDARY_POSITION:
+                /*
+                 * Secondary, upper rail of a dual action shade: => NOT INVERTED
+                 */
+                if (posKindCoords.equals(posKind2)) {
+                    return new PercentType((int) Math.round(position2.doubleValue() / MAX_SHADE * 100));
+                }
+                break;
+
+            /*
+             * Vane angle of the primary rail of a bottom-up single action shade: => NOT INVERTED
+             */
+            case VANE_TILT_POSITION:
+                if (posKindCoords.equals(posKind2)) {
+                    int max = shadeCapabilities.supportsTilt180() ? MAX_SHADE : MAX_VANE;
+                    return new PercentType((int) Math.round((double) Math.min(position2.intValue(), max) / max * 100));
+                }
+                break;
+
+            case ERROR_UNKNOWN:
+            case NONE:
+                // fall through, return UNDEF
+        }
+        return UnDefType.UNDEF;
+    }
+
+    /**
+     * Detect if the ShadePosition has a posKindN value indicating potential support for a secondary rail.
+     *
+     * @return true if the ShadePosition supports a secondary rail.
+     */
+    public boolean secondaryRailDetected() {
+        return SECONDARY_POSITION.equals(posKind1) || SECONDARY_POSITION.equals(posKind2);
+    }
+
+    /**
+     * Detect if the ShadePosition has both a posKindN value indicating potential support for tilt, AND a posKindN
+     * indicating support for a primary rail. i.e. it potentially supports tilt anywhere functionality.
+     *
+     * @return true if potential support for tilt anywhere functionality was detected.
+     */
+    public boolean tiltAnywhereDetected() {
+        return ((PRIMARY_POSITION.equals(posKind1)) && (VANE_TILT_POSITION.equals(posKind2))
+                || ((PRIMARY_POSITION.equals(posKind2) && (VANE_TILT_POSITION.equals(posKind1)))));
+    }
+
+    /**
+     * Set the shade's position for the given actuator class resp. coordinate system.
+     *
+     * @param shadeCapabilities the shade Thing capabilities.
+     * @param posKindCoords the actuator class (coordinate system) whose state is to be changed.
+     * @param percent the new position value.
+     * @return this object.
+     */
+    public ShadePosition setPosition(Capabilities shadeCapabilities, CoordinateSystem posKindCoords, int percent) {
+        logger.trace("setPosition(): capabilities={}, coords={}, percent={}", shadeCapabilities, posKindCoords,
+                percent);
+        // if necessary swap the order of position1 and position2
+        if (PRIMARY_POSITION.equals(posKind2) && !PRIMARY_POSITION.equals(posKind1)) {
+            final Integer posKind2Temp = posKind2;
+            final Integer position2Temp = position2;
+            posKind2 = Integer.valueOf(posKind1);
+            position2 = Integer.valueOf(position1);
+            posKind1 = posKind2Temp != null ? posKind2Temp.intValue() : NONE.ordinal();
+            position1 = position2Temp != null ? position2Temp.intValue() : 0;
+        }
+
+        // delete position2 if it has an invalid position kind
+        if (ERROR_UNKNOWN.equals(posKind2) || NONE.equals(posKind2)) {
+            posKind2 = null;
+            position2 = null;
+        }
+
+        // logic to set either position1 or position2
+        switch (posKindCoords) {
+            case PRIMARY_POSITION:
+                if (shadeCapabilities.supportsPrimary()) {
+                    setPosition1(shadeCapabilities, posKindCoords, percent);
+                }
+                break;
+
+            case SECONDARY_POSITION:
+                if (shadeCapabilities.supportsSecondary()) {
+                    if (shadeCapabilities.supportsPrimary()) {
+                        setPosition2(shadeCapabilities, posKindCoords, percent);
+                    } else {
+                        setPosition1(shadeCapabilities, posKindCoords, percent);
+                    }
+                } else if (shadeCapabilities.supportsSecondaryOverlapped()) {
+                    setPosition1(shadeCapabilities, posKindCoords, percent);
+                }
+                break;
+
+            case VANE_TILT_POSITION:
+                if (shadeCapabilities.supportsPrimary()) {
+                    if (shadeCapabilities.supportsTiltOnClosed()) {
+                        setPosition1(shadeCapabilities, posKindCoords, percent);
+                    } else if (shadeCapabilities.supportsTiltAnywhere()) {
+                        setPosition2(shadeCapabilities, posKindCoords, percent);
+                    }
+                } else if (shadeCapabilities.supportsTiltAnywhere()) {
+                    setPosition1(shadeCapabilities, posKindCoords, percent);
+                }
+                break;
+
+            case ERROR_UNKNOWN:
+            case NONE:
+                // fall through, do nothing
+        }
+        return this;
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SurveyData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/SurveyData.java
new file mode 100644 (file)
index 0000000..7f3da5f
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * 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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Survey data of a single Shade, as returned by an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public 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);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Times.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/Times.java
new file mode 100644 (file)
index 0000000..33a9bc9
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * 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.dto;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Times as part of {@link UserData} for an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Times {
+    public @Nullable String timezone;
+    public int localSunriseTimeInMinutes;
+    public int localSunsetTimeInMinutes;
+    public int currentOffset;
+    public double longitude;
+    public double latitude;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/UserData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/UserData.java
new file mode 100644 (file)
index 0000000..fd36992
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * 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.dto;
+
+import java.util.Base64;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * User data for an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class UserData {
+    public @Nullable String hubName;
+    public boolean localTimeDataSet;
+    public boolean enableScheduledEvents;
+    public boolean editingEnabled;
+    public boolean setupCompleted;
+    public @Nullable String gateway;
+    public @Nullable String dns;
+    public boolean staticIp;
+    @SerializedName("_id")
+    public @Nullable String id;
+    public @Nullable Color color;
+    public boolean autoBackup;
+    public @Nullable String ip;
+    public @Nullable String macAddress;
+    public @Nullable String mask;
+    public boolean wireless;
+    public @Nullable HubFirmware firmware;
+    public @Nullable String serialNumber;
+    public @Nullable String rfIDInt;
+    public @Nullable String rfID;
+    public int rfStatus;
+    public @Nullable Times times;
+    public @Nullable String brand;
+    public boolean rcUp;
+    public boolean remoteConnectEnabled;
+
+    public String getHubName() {
+        return hubName != null ? new String(Base64.getDecoder().decode(hubName)) : "";
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterBlinking.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterBlinking.java
new file mode 100644 (file)
index 0000000..e50a308
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * State of a single Repeater for being updated by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class RepeaterBlinking {
+    public Repeater repeater;
+
+    public class Repeater {
+        public int id;
+        public boolean blinkEnabled;
+
+        public Repeater(int id, boolean enable) {
+            this.id = id;
+            this.blinkEnabled = enable;
+        }
+    }
+
+    public RepeaterBlinking(int id, boolean enable) {
+        repeater = new Repeater(id, enable);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterColor.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/RepeaterColor.java
new file mode 100644 (file)
index 0000000..fc317e7
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.hdpowerview.internal.dto.Color;
+
+/**
+ * Color state of a single Repeater for being updated by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class RepeaterColor {
+    public Repeater repeater;
+
+    public class Repeater {
+        public int id;
+        public Color color;
+
+        public Repeater(int id, Color color) {
+            this.id = id;
+            this.color = color;
+        }
+    }
+
+    public RepeaterColor(int id, Color color) {
+        repeater = new Repeater(id, color);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeCalibrate.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeCalibrate.java
new file mode 100644 (file)
index 0000000..0d1d50e
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A request to calibrate a shade
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class ShadeCalibrate {
+
+    public ShadeMotion shade;
+
+    public ShadeCalibrate() {
+        this.shade = new ShadeMotion(ShadeMotion.Type.CALIBRATE);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeJog.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeJog.java
new file mode 100644 (file)
index 0000000..b1317a7
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A request to jog a shade for identification
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class ShadeJog {
+
+    public ShadeMotion shade;
+
+    public ShadeJog() {
+        this.shade = new ShadeMotion(ShadeMotion.Type.JOG);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMotion.java
new file mode 100644 (file)
index 0000000..f5aeb57
--- /dev/null
@@ -0,0 +1,46 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A motion directive for a shade
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+class ShadeMotion {
+
+    public enum Type {
+        STOP("stop"),
+        JOG("jog"),
+        CALIBRATE("calibrate");
+
+        private String motion;
+
+        Type(String motion) {
+            this.motion = motion;
+        }
+
+        public String getMotion() {
+            return this.motion;
+        }
+    }
+
+    public String motion;
+
+    public ShadeMotion(Type motionType) {
+        this.motion = motionType.getMotion();
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMove.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeMove.java
new file mode 100644 (file)
index 0000000..4f87fdf
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+
+/**
+ * A request to set the position of a shade
+ *
+ * @author Andy Lintner - Initial contribution
+ */
+@NonNullByDefault
+public class ShadeMove {
+
+    public ShadePositions shade;
+
+    public ShadeMove(ShadePosition position) {
+        this.shade = new ShadePositions(position);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadePositions.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadePositions.java
new file mode 100644 (file)
index 0000000..fd98950
--- /dev/null
@@ -0,0 +1,31 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+
+/**
+ * The position of a shade to set
+ *
+ * @author Andy Lintner - Initial contribution
+ */
+@NonNullByDefault
+class ShadePositions {
+
+    public ShadePosition positions;
+
+    public ShadePositions(ShadePosition position) {
+        this.positions = position;
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeStop.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/requests/ShadeStop.java
new file mode 100644 (file)
index 0000000..34f47f0
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.requests;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * A request to stop the movement of a shade
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+public class ShadeStop {
+
+    public ShadeMotion shade;
+
+    public ShadeStop() {
+        this.shade = new ShadeMotion(ShadeMotion.Type.STOP);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/FirmwareVersion.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/FirmwareVersion.java
new file mode 100644 (file)
index 0000000..34b9f20
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * 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.dto.responses;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.HubFirmware;
+
+/**
+ * Firmware information for an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class FirmwareVersion {
+    @Nullable
+    public HubFirmware firmware;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeater.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeater.java
new file mode 100644 (file)
index 0000000..d743626
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * 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.dto.responses;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * State of a single Repeater, as returned by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Repeater {
+    public @Nullable RepeaterData repeater;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/RepeaterData.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/RepeaterData.java
new file mode 100644 (file)
index 0000000..1b78963
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * 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.dto.responses;
+
+import java.util.Base64;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.Color;
+import org.openhab.binding.hdpowerview.internal.dto.Firmware;
+
+/**
+ * Repeater data for a single Repeater, as returned by an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class RepeaterData {
+    public int id;
+    public @Nullable String name;
+    public int roomId;
+    public int groupId;
+    public boolean blinkEnabled;
+    public @Nullable Firmware firmware;
+    public @Nullable Color color;
+
+    public String getName() {
+        return new String(Base64.getDecoder().decode(name));
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeaters.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Repeaters.java
new file mode 100644 (file)
index 0000000..e1aa699
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+/**
+ * Repeaters connected to an HD PowerView Hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Repeaters {
+    public @Nullable List<RepeaterData> repeaterData;
+    public @Nullable List<Integer> repeaterIds;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/SceneCollections.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/SceneCollections.java
new file mode 100644 (file)
index 0000000..582178b
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+
+/**
+ * State of all Scene Collections in an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class SceneCollections {
+    public @Nullable List<SceneCollection> sceneCollectionData;
+    public @Nullable List<Integer> sceneCollectionIds;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Scenes.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Scenes.java
new file mode 100644 (file)
index 0000000..7458d6f
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+
+/**
+ * State of all Scenes in an HD PowerView hub
+ *
+ * @author Andy Lintner - Initial contribution
+ */
+@NonNullByDefault
+public class Scenes {
+    public @Nullable List<Scene> sceneData;
+    public @Nullable List<Integer> sceneIds;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/ScheduledEvents.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/ScheduledEvents.java
new file mode 100644 (file)
index 0000000..4b4a8b4
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.ScheduledEvent;
+
+/**
+ * State of all Scheduled Events in an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class ScheduledEvents {
+    public @Nullable List<ScheduledEvent> scheduledEventData;
+    public @Nullable List<Integer> scheduledEventIds;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shade.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shade.java
new file mode 100644 (file)
index 0000000..29b0794
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * 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.dto.responses;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+
+/**
+ * State of a single Shade, as returned by an HD PowerView hub
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+public class Shade {
+    public @Nullable ShadeData shade;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shades.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Shades.java
new file mode 100644 (file)
index 0000000..ab17714
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+
+/**
+ * State of all Shades, as returned by an HD PowerView hub
+ *
+ * @author Andy Lintner - Initial contribution
+ */
+@NonNullByDefault
+public class Shades {
+    public @Nullable List<ShadeData> shadeData;
+    public @Nullable List<Integer> shadeIds;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Survey.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/Survey.java
new file mode 100644 (file)
index 0000000..e55a1f9
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * 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.dto.responses;
+
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.SurveyData;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * Survey data of a single Shade, as returned by an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class Survey {
+    @SerializedName("shade_id")
+    public int shadeId;
+    @SerializedName("survey")
+    public @Nullable List<SurveyData> surveyData;
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/UserDataResponse.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/dto/responses/UserDataResponse.java
new file mode 100644 (file)
index 0000000..15c4cbe
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * 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.dto.responses;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.binding.hdpowerview.internal.dto.UserData;
+
+/**
+ * Response with {@link UserData} for an HD PowerView hub
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class UserDataResponse {
+    public @Nullable UserData userData;
+}
index b3991f3aad3bd19212d43017ec91ac1a3b0f7f37..7cfe8778f04213b5c3da185f69b62af996dd2775 100644 (file)
@@ -30,22 +30,22 @@ import org.eclipse.jetty.client.HttpClient;
 import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
 import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider;
 import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets;
-import org.openhab.binding.hdpowerview.internal.api.Firmware;
-import org.openhab.binding.hdpowerview.internal.api.HubFirmware;
-import org.openhab.binding.hdpowerview.internal.api.UserData;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents.ScheduledEvent;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
 import org.openhab.binding.hdpowerview.internal.builders.AutomationChannelBuilder;
 import org.openhab.binding.hdpowerview.internal.builders.SceneChannelBuilder;
 import org.openhab.binding.hdpowerview.internal.builders.SceneGroupChannelBuilder;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewHubConfiguration;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration;
+import org.openhab.binding.hdpowerview.internal.dto.Firmware;
+import org.openhab.binding.hdpowerview.internal.dto.HubFirmware;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.ScheduledEvent;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.UserData;
+import org.openhab.binding.hdpowerview.internal.dto.responses.SceneCollections;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Scenes;
+import org.openhab.binding.hdpowerview.internal.dto.responses.ScheduledEvents;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shades;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
index 037c85184d167bbeea5caed218940a5b705ac51f..c8080fa2c354b4fa68c95380da7f3a5d3e319ea0 100644 (file)
@@ -20,10 +20,10 @@ import java.util.concurrent.TimeUnit;
 import org.eclipse.jdt.annotation.NonNullByDefault;
 import org.eclipse.jdt.annotation.Nullable;
 import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets;
-import org.openhab.binding.hdpowerview.internal.api.Color;
-import org.openhab.binding.hdpowerview.internal.api.Firmware;
-import org.openhab.binding.hdpowerview.internal.api.responses.RepeaterData;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewRepeaterConfiguration;
+import org.openhab.binding.hdpowerview.internal.dto.Color;
+import org.openhab.binding.hdpowerview.internal.dto.Firmware;
+import org.openhab.binding.hdpowerview.internal.dto.responses.RepeaterData;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
index 53e77e0425cdb4b717c921f4e32341e4bc35a370..f787ad0902caaf62864f64187f91b005d5cb69d2 100644 (file)
@@ -13,7 +13,7 @@
 package org.openhab.binding.hdpowerview.internal.handler;
 
 import static org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants.*;
-import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
+import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -29,15 +29,15 @@ 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;
-import org.openhab.binding.hdpowerview.internal.api.SurveyData;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
 import org.openhab.binding.hdpowerview.internal.config.HDPowerViewShadeConfiguration;
 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.binding.hdpowerview.internal.dto.BatteryKind;
+import org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem;
+import org.openhab.binding.hdpowerview.internal.dto.Firmware;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+import org.openhab.binding.hdpowerview.internal.dto.SurveyData;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
 import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/AutomationChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/AutomationChannelBuilderTest.java
deleted file mode 100644 (file)
index ba6cb99..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents;
-import org.openhab.binding.hdpowerview.internal.api.responses.ScheduledEvents.ScheduledEvent;
-import org.openhab.binding.hdpowerview.internal.builders.AutomationChannelBuilder;
-import org.openhab.binding.hdpowerview.providers.MockedLocaleProvider;
-import org.openhab.binding.hdpowerview.providers.MockedTranslationProvider;
-import org.openhab.core.thing.Channel;
-import org.openhab.core.thing.ChannelGroupUID;
-import org.openhab.core.thing.ThingUID;
-import org.osgi.framework.Bundle;
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-
-/**
- * Unit tests for {@link AutomationChannelBuilder}.
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class AutomationChannelBuilderTest {
-
-    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
-            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, AutomationChannelBuilderTest.class.getSimpleName()),
-            HDPowerViewBindingConstants.CHANNELTYPE_AUTOMATION_ENABLED);
-
-    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
-            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
-
-    private AutomationChannelBuilder builder = AutomationChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-    private List<Scene> scenes = new ArrayList<>();
-    private List<SceneCollection> sceneCollections = new ArrayList<>();
-
-    @BeforeEach
-    private void setUp() {
-        final Logger logger = (Logger) LoggerFactory.getLogger(AutomationChannelBuilder.class);
-        logger.setLevel(Level.OFF);
-        builder = AutomationChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-
-        Scene scene = new Scene();
-        scene.id = 1;
-        scene.name = Base64.getEncoder().encodeToString(("TestScene").getBytes());
-        scenes = new ArrayList<>(List.of(scene));
-
-        SceneCollection sceneCollection = new SceneCollection();
-        sceneCollection.id = 2;
-        sceneCollection.name = Base64.getEncoder().encodeToString(("TestSceneCollection").getBytes());
-        sceneCollections = new ArrayList<>(List.of(sceneCollection));
-    }
-
-    @Test
-    public void sceneSunriseWeekends() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        scheduledEvent.daySaturday = true;
-        scheduledEvent.daySunday = true;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, At sunrise, Weekends", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneSunsetWeekdays() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNSET);
-        scheduledEvent.dayMonday = true;
-        scheduledEvent.dayTuesday = true;
-        scheduledEvent.dayWednesday = true;
-        scheduledEvent.dayThursday = true;
-        scheduledEvent.dayFriday = true;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, At sunset, Weekdays", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneTimeAllDays() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_TIME);
-        scheduledEvent.dayMonday = true;
-        scheduledEvent.dayTuesday = true;
-        scheduledEvent.dayWednesday = true;
-        scheduledEvent.dayThursday = true;
-        scheduledEvent.dayFriday = true;
-        scheduledEvent.daySaturday = true;
-        scheduledEvent.daySunday = true;
-        scheduledEvent.hour = 6;
-        scheduledEvent.minute = 30;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, 06:30, All days", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneMinutesBeforeSunriseMondayTuesday() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        scheduledEvent.dayMonday = true;
-        scheduledEvent.dayTuesday = true;
-        scheduledEvent.minute = -15;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, 15m before sunrise, Mon, Tue", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneHoursMinutesAfterSunriseMonday() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        scheduledEvent.dayMonday = true;
-        scheduledEvent.minute = 61;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, 1hr 1m after sunrise, Mon", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneMinutesBeforeSunsetWednesdayThursdayFriday() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNSET);
-        scheduledEvent.dayWednesday = true;
-        scheduledEvent.dayThursday = true;
-        scheduledEvent.dayFriday = true;
-        scheduledEvent.minute = -59;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, 59m before sunset, Wed, Thu, Fri", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneHourAfterSunsetFridaySaturdaySunday() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNSET);
-        scheduledEvent.dayFriday = true;
-        scheduledEvent.daySaturday = true;
-        scheduledEvent.daySunday = true;
-        scheduledEvent.minute = 60;
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene, 1hr after sunset, Fri, Sat, Sun", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void sceneCollection() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithSceneCollection(
-                ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).withScheduledEvents(scheduledEvents)
-                .build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestSceneCollection, At sunrise, ", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void suppliedListIsUsed() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> existingChannels = new ArrayList<>(0);
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents)
-                .withChannels(existingChannels).build();
-
-        assertEquals(existingChannels, channels);
-    }
-
-    @Test
-    public void emptyListWhenNoScheduledEvents() {
-        List<Channel> channels = builder.build();
-
-        assertEquals(0, channels.size());
-    }
-
-    @Test
-    public void emptyListWhenNoScenesOrSceneCollections() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(0, channels.size());
-    }
-
-    @Test
-    public void emptyListWhenNoSceneForScheduledEvent() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithSceneCollection(
-                ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(0, channels.size());
-    }
-
-    @Test
-    public void emptyListWhenNoSceneCollectionForScheduledEvent() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).withScheduledEvents(scheduledEvents)
-                .build();
-
-        assertEquals(0, channels.size());
-    }
-
-    @Test
-    public void groupAndIdAreCorrect() {
-        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvents.SCHEDULED_EVENT_TYPE_SUNRISE);
-        scheduledEvent.id = 42;
-        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
-        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
-
-        assertEquals(1, channels.size());
-        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
-        assertEquals(Integer.toString(scheduledEvent.id), channels.get(0).getUID().getIdWithoutGroup());
-    }
-
-    private ScheduledEvent createScheduledEventWithScene(int eventType) {
-        ScheduledEvent scheduledEvent = new ScheduledEvent();
-        scheduledEvent.id = 1;
-        scheduledEvent.sceneId = scenes.get(0).id;
-        scheduledEvent.eventType = eventType;
-        return scheduledEvent;
-    }
-
-    private ScheduledEvent createScheduledEventWithSceneCollection(int eventType) {
-        ScheduledEvent scheduledEvent = new ScheduledEvent();
-        scheduledEvent.id = 1;
-        scheduledEvent.sceneCollectionId = sceneCollections.get(0).id;
-        scheduledEvent.eventType = eventType;
-        return scheduledEvent;
-    }
-}
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
deleted file mode 100644 (file)
index 19cd35c..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-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;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
-import org.openhab.core.library.types.PercentType;
-import org.openhab.core.types.State;
-import org.openhab.core.types.UnDefType;
-
-import com.google.gson.Gson;
-
-/**
- * Unit tests for HD PowerView binding.
- *
- * @author Andrew Fiddian-Green - Initial contribution
- * @author Jacob Laursen - Add support for scene groups
- */
-@NonNullByDefault
-public class HDPowerViewJUnitTests {
-
-    private Gson gson = new Gson();
-
-    private <T> T getObjectFromJson(String filename, Class<T> clazz) throws IOException {
-        try (InputStream inputStream = HDPowerViewJUnitTests.class.getResourceAsStream(filename)) {
-            if (inputStream == null) {
-                throw new IOException("inputstream is null");
-            }
-            byte[] bytes = inputStream.readAllBytes();
-            if (bytes == null) {
-                throw new IOException("Resulting byte-array empty");
-            }
-            String json = new String(bytes, StandardCharsets.UTF_8);
-            return Objects.requireNonNull(gson.fromJson(json, clazz));
-        }
-    }
-
-    /**
-     * Test generic JSON shades response.
-     */
-    @Test
-    public void shadeNameIsDecoded() throws IOException {
-        Shades shades = getObjectFromJson("shades.json", Shades.class);
-        List<ShadeData> shadeData = shades.shadeData;
-        assertNotNull(shadeData);
-        assertEquals(3, shadeData.size());
-        ShadeData shade = shadeData.get(0);
-        assertEquals("Shade 2", shade.getName());
-    }
-
-    /**
-     * Test the BatteryKind decoding.
-     */
-    @Test
-    public void testBatteryKind() throws IOException {
-        Shades shades = getObjectFromJson("shades.json", Shades.class);
-        List<ShadeData> 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.
-     */
-    @Test
-    public void sceneNameIsDecoded() throws IOException {
-        Scenes scenes = getObjectFromJson("scenes.json", Scenes.class);
-        List<Scene> sceneData = scenes.sceneData;
-        assertNotNull(sceneData);
-        assertEquals(4, sceneData.size());
-        Scene scene = sceneData.get(0);
-        assertEquals("Door Open", scene.getName());
-    }
-
-    /**
-     * Test generic JSON scene collection response.
-     */
-    @Test
-    public void sceneCollectionNameIsDecoded() throws IOException {
-        SceneCollections sceneCollections = getObjectFromJson("sceneCollections.json", SceneCollections.class);
-
-        List<SceneCollection> sceneCollectionData = sceneCollections.sceneCollectionData;
-        assertNotNull(sceneCollectionData);
-        assertEquals(1, sceneCollectionData.size());
-
-        SceneCollection sceneCollection = sceneCollectionData.get(0);
-        assertEquals("Børn op", sceneCollection.getName());
-    }
-
-    /**
-     * Test the JSON parsing for a duette top down bottom up shade.
-     */
-    @Test
-    public void duetteTopDownBottomUpShadeIsParsedCorrectly() throws IOException {
-        Shades shades = getObjectFromJson("duette.json", Shades.class);
-        List<ShadeData> shadesData = shades.shadeData;
-        assertNotNull(shadesData);
-
-        assertEquals(1, shadesData.size());
-        ShadeData shadeData = shadesData.get(0);
-        assertNotNull(shadeData);
-
-        assertEquals("Gardin 1", shadeData.getName());
-        assertEquals(63778, shadeData.id);
-
-        ShadePosition shadePos = shadeData.positions;
-        assertNotNull(shadePos);
-
-        Integer capabilitiesValue = shadeData.capabilities;
-        assertNotNull(capabilitiesValue);
-        assertEquals(7, capabilitiesValue.intValue());
-        ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
-        Capabilities capabilities = db.getCapabilities(capabilitiesValue);
-
-        State pos = shadePos.getState(capabilities, PRIMARY_POSITION);
-        assertEquals(PercentType.class, pos.getClass());
-        assertEquals(59, ((PercentType) pos).intValue());
-
-        pos = shadePos.getState(capabilities, SECONDARY_POSITION);
-        assertEquals(PercentType.class, pos.getClass());
-        assertEquals(35, ((PercentType) pos).intValue());
-
-        pos = shadePos.getState(capabilities, VANE_TILT_POSITION);
-        assertEquals(UnDefType.class, pos.getClass());
-
-        assertEquals(3, shadeData.batteryStatus);
-
-        assertEquals(4, shadeData.signalStrength);
-
-        assertEquals(8, shadeData.type);
-
-        assertTrue(db.isTypeInDatabase(shadeData.type));
-        assertTrue(db.isCapabilitiesInDatabase(capabilitiesValue.intValue()));
-
-        assertEquals(db.getType(shadeData.type).getCapabilities(), capabilitiesValue.intValue());
-
-        assertTrue(db.getCapabilities(capabilitiesValue.intValue()).supportsSecondary());
-        assertNotEquals(db.getType(shadeData.type).getCapabilities(), capabilitiesValue.intValue() + 1);
-
-        // ==== when changing position1, position2 value is not changed (vice-versa) ====
-        ShadePosition shadePosition = shadeData.positions;
-        assertNotNull(shadePosition);
-        // ==== position2 ====
-        State position2Old = shadePosition.getState(capabilities, SECONDARY_POSITION);
-        shadePosition.setPosition(capabilities, PRIMARY_POSITION, 99);
-        State position2New = shadePosition.getState(capabilities, SECONDARY_POSITION);
-        assertEquals(PercentType.class, position2Old.getClass());
-        assertEquals(PercentType.class, position2New.getClass());
-        assertEquals(((PercentType) position2Old).intValue(), ((PercentType) position2New).intValue());
-
-        // ==== position2 ====
-        State position1Old = shadePosition.getState(capabilities, PRIMARY_POSITION);
-        shadePosition.setPosition(capabilities, SECONDARY_POSITION, 99);
-        State position1New = shadePosition.getState(capabilities, PRIMARY_POSITION);
-        assertEquals(PercentType.class, position1Old.getClass());
-        assertEquals(PercentType.class, position1New.getClass());
-        assertEquals(((PercentType) position1Old).intValue(), ((PercentType) position1New).intValue());
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/OnlineCommunicationTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/OnlineCommunicationTest.java
deleted file mode 100644 (file)
index b8670bb..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
-
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jetty.client.HttpClient;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets;
-import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades;
-import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
-import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
-import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
-import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
-import org.openhab.core.library.types.PercentType;
-import org.openhab.core.types.State;
-
-/**
- * Unit tests for HD PowerView binding.
- *
- * @author Andrew Fiddian-Green - Initial contribution
- */
-@NonNullByDefault
-public class OnlineCommunicationTest {
-
-    private static final Pattern VALID_IP_V4_ADDRESS = Pattern
-            .compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b");
-
-    /**
-     * Run a series of ONLINE tests on the communication with a hub.
-     *
-     * @param hubIPAddress must be a valid hub IP address to run the
-     *            tests on; or an INVALID IP address to
-     *            suppress the tests
-     * @param allowShadeMovementCommands set to true if you accept that the tests
-     *            shall physically move the shades
-     */
-    @Test
-    public void testOnlineCommunication() {
-        /*
-         * NOTE: in order to actually run these tests you must have a hub physically
-         * available, and its IP address must be correctly configured in the
-         * "hubIPAddress" string constant e.g. "192.168.1.123"
-         */
-        String hubIPAddress = "192.168.1.xxx";
-
-        /*
-         * NOTE: set allowShadeMovementCommands = true if you accept physically moving
-         * the shades during these tests
-         */
-        boolean allowShadeMovementCommands = false;
-
-        if (VALID_IP_V4_ADDRESS.matcher(hubIPAddress).matches()) {
-            // ==== initialize stuff ====
-            HttpClient client = new HttpClient();
-            assertNotNull(client);
-
-            // ==== start the client ====
-            try {
-                client.start();
-                assertTrue(client.isStarted());
-            } catch (Exception e) {
-                fail(e.getMessage());
-            }
-
-            HDPowerViewWebTargets webTargets = new HDPowerViewWebTargets(client, hubIPAddress);
-            assertNotNull(webTargets);
-
-            int shadeId = 0;
-            ShadePosition shadePos = null;
-            Shades shadesX = null;
-
-            // ==== get all shades ====
-            try {
-                shadesX = webTargets.getShades();
-                assertNotNull(shadesX);
-                List<ShadeData> shadesData = shadesX.shadeData;
-                assertNotNull(shadesData);
-
-                assertTrue(!shadesData.isEmpty());
-                ShadeData shadeData;
-                shadeData = shadesData.get(0);
-                assertNotNull(shadeData);
-                assertTrue(shadeData.getName().length() > 0);
-                shadePos = shadeData.positions;
-                assertNotNull(shadePos);
-                ShadeData shadeZero = shadesData.get(0);
-                assertNotNull(shadeZero);
-                shadeId = shadeZero.id;
-                assertNotEquals(0, shadeId);
-
-                for (ShadeData shadexData : shadesData) {
-                    String shadeName = shadexData.getName();
-                    assertNotNull(shadeName);
-                }
-            } catch (HubException e) {
-                fail(e.getMessage());
-            }
-
-            // ==== get all scenes ====
-            int sceneId = 0;
-            try {
-                Scenes scenes = webTargets.getScenes();
-                assertNotNull(scenes);
-
-                List<Scene> scenesData = scenes.sceneData;
-                assertNotNull(scenesData);
-
-                assertTrue(!scenesData.isEmpty());
-                Scene sceneZero = scenesData.get(0);
-                assertNotNull(sceneZero);
-                sceneId = sceneZero.id;
-                assertTrue(sceneId > 0);
-
-                for (Scene scene : scenesData) {
-                    String sceneName = scene.getName();
-                    assertNotNull(sceneName);
-                }
-            } catch (HubException e) {
-                fail(e.getMessage());
-            }
-
-            // ==== refresh a specific shade ====
-            ShadeData shadeData = null;
-            try {
-                assertNotEquals(0, shadeId);
-                shadeData = webTargets.refreshShadePosition(shadeId);
-            } catch (HubException e) {
-                fail(e.getMessage());
-            }
-
-            // ==== move a specific shade ====
-            try {
-                assertNotEquals(0, shadeId);
-
-                if (shadeData != null) {
-                    ShadePosition positions = shadeData.positions;
-                    assertNotNull(positions);
-                    Integer capabilitiesValue = shadeData.capabilities;
-                    assertNotNull(capabilitiesValue);
-
-                    Capabilities capabilities = new ShadeCapabilitiesDatabase()
-                            .getCapabilities(capabilitiesValue.intValue());
-
-                    State pos = positions.getState(capabilities, PRIMARY_POSITION);
-                    assertEquals(PercentType.class, pos.getClass());
-
-                    int position = ((PercentType) pos).intValue();
-                    position = position + ((position <= 10) ? 5 : -5);
-
-                    ShadePosition targetPosition = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION,
-                            position);
-                    assertNotNull(targetPosition);
-
-                    if (allowShadeMovementCommands) {
-                        webTargets.moveShade(shadeId, targetPosition);
-
-                        ShadeData newData = webTargets.getShade(shadeId);
-                        ShadePosition actualPosition = newData.positions;
-                        assertNotNull(actualPosition);
-                        assertEquals(targetPosition.getState(capabilities, PRIMARY_POSITION),
-                                actualPosition.getState(capabilities, PRIMARY_POSITION));
-                    }
-                }
-            } catch (HubException e) {
-                fail(e.getMessage());
-            }
-
-            // ==== activate a specific scene ====
-            if (allowShadeMovementCommands) {
-                try {
-                    assertNotNull(sceneId);
-                    webTargets.activateScene(sceneId);
-                } catch (HubProcessingException | HubMaintenanceException e) {
-                    fail(e.getMessage());
-                }
-            }
-
-            // ==== test stop command ====
-            if (allowShadeMovementCommands) {
-                try {
-                    assertNotNull(sceneId);
-                    webTargets.stopShade(shadeId);
-                } catch (HubException e) {
-                    fail(e.getMessage());
-                }
-            }
-
-            // ==== stop the client ====
-            if (client.isRunning()) {
-                try {
-                    client.stop();
-                } catch (Exception e) {
-                    fail(e.getMessage());
-                }
-            }
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneChannelBuilderTest.java
deleted file mode 100644 (file)
index eca2a1f..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.Scenes.Scene;
-import org.openhab.binding.hdpowerview.internal.builders.SceneChannelBuilder;
-import org.openhab.binding.hdpowerview.providers.MockedLocaleProvider;
-import org.openhab.binding.hdpowerview.providers.MockedTranslationProvider;
-import org.openhab.core.thing.Channel;
-import org.openhab.core.thing.ChannelGroupUID;
-import org.openhab.core.thing.ThingUID;
-import org.openhab.core.thing.type.AutoUpdatePolicy;
-import org.osgi.framework.Bundle;
-
-/**
- * Unit tests for {@link SceneChannelBuilder}.
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class SceneChannelBuilderTest {
-
-    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
-            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneChannelBuilderTest.class.getSimpleName()),
-            HDPowerViewBindingConstants.CHANNELTYPE_SCENE_ACTIVATE);
-
-    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
-            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
-
-    private SceneChannelBuilder builder = SceneChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-
-    @BeforeEach
-    private void setUp() {
-        builder = SceneChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-    }
-
-    @Test
-    public void labelIsCorrect() {
-        List<Scene> scenes = createScenes();
-        List<Channel> channels = builder.withScenes(scenes).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestScene", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void descriptionIsCorrect() {
-        List<Scene> scenes = createScenes();
-        List<Channel> channels = builder.withScenes(scenes).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("Activates the scene 'TestScene'", channels.get(0).getDescription());
-    }
-
-    @Test
-    public void groupAndIdAreCorrect() {
-        List<Scene> scenes = createScenes();
-        List<Channel> channels = builder.withScenes(scenes).build();
-
-        assertEquals(1, channels.size());
-        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
-        assertEquals(Integer.toString(scenes.get(0).id), channels.get(0).getUID().getIdWithoutGroup());
-    }
-
-    @Test
-    public void autoUpdatePolicyIsCorrect() {
-        List<Scene> scenes = createScenes();
-        List<Channel> channels = builder.withScenes(scenes).build();
-
-        assertEquals(1, channels.size());
-        assertEquals(AutoUpdatePolicy.VETO, channels.get(0).getAutoUpdatePolicy());
-    }
-
-    @Test
-    public void suppliedListIsUsed() {
-        List<Scene> scenes = createScenes();
-        List<Channel> existingChannels = new ArrayList<>(0);
-        List<Channel> channels = builder.withScenes(scenes).withChannels(existingChannels).build();
-
-        assertEquals(existingChannels, channels);
-    }
-
-    @Test
-    public void emptyListWhenNoScenes() {
-        List<Channel> channels = builder.build();
-
-        assertEquals(0, channels.size());
-    }
-
-    private List<Scene> createScenes() {
-        Scene scene = new Scene();
-        scene.id = 1;
-        scene.name = Base64.getEncoder().encodeToString(("TestScene").getBytes());
-        return new ArrayList<>(List.of(scene));
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneGroupChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/SceneGroupChannelBuilderTest.java
deleted file mode 100644 (file)
index e2dc8b1..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.Mockito.mock;
-
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.List;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
-import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider;
-import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
-import org.openhab.binding.hdpowerview.internal.builders.SceneGroupChannelBuilder;
-import org.openhab.binding.hdpowerview.providers.MockedLocaleProvider;
-import org.openhab.binding.hdpowerview.providers.MockedTranslationProvider;
-import org.openhab.core.thing.Channel;
-import org.openhab.core.thing.ChannelGroupUID;
-import org.openhab.core.thing.ThingUID;
-import org.openhab.core.thing.type.AutoUpdatePolicy;
-import org.osgi.framework.Bundle;
-
-/**
- * Unit tests for {@link SceneGroupChannelBuilder}.
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class SceneGroupChannelBuilderTest {
-
-    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
-            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneGroupChannelBuilderTest.class.getSimpleName()),
-            HDPowerViewBindingConstants.CHANNELTYPE_SCENE_GROUP_ACTIVATE);
-
-    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
-            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
-
-    private SceneGroupChannelBuilder builder = SceneGroupChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-
-    @BeforeEach
-    private void setUp() {
-        builder = SceneGroupChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
-    }
-
-    @Test
-    public void labelIsCorrect() {
-        List<SceneCollection> sceneCollections = createSceneCollections();
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("TestSceneCollection", channels.get(0).getLabel());
-    }
-
-    @Test
-    public void descriptionIsCorrect() {
-        List<SceneCollection> sceneCollections = createSceneCollections();
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
-
-        assertEquals(1, channels.size());
-        assertEquals("Activates the scene group 'TestSceneCollection'", channels.get(0).getDescription());
-    }
-
-    @Test
-    public void groupAndIdAreCorrect() {
-        List<SceneCollection> sceneCollections = createSceneCollections();
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
-
-        assertEquals(1, channels.size());
-        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
-        assertEquals(Integer.toString(sceneCollections.get(0).id), channels.get(0).getUID().getIdWithoutGroup());
-    }
-
-    @Test
-    public void autoUpdatePolicyIsCorrect() {
-        List<SceneCollection> sceneCollections = createSceneCollections();
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
-
-        assertEquals(1, channels.size());
-        assertEquals(AutoUpdatePolicy.VETO, channels.get(0).getAutoUpdatePolicy());
-    }
-
-    @Test
-    public void suppliedListIsUsed() {
-        List<SceneCollection> sceneCollections = createSceneCollections();
-        List<Channel> existingChannels = new ArrayList<>(0);
-        List<Channel> channels = builder.withSceneCollections(sceneCollections).withChannels(existingChannels).build();
-
-        assertEquals(existingChannels, channels);
-    }
-
-    @Test
-    public void emptyListWhenNoSceneCollections() {
-        List<Channel> channels = builder.build();
-
-        assertEquals(0, channels.size());
-    }
-
-    private List<SceneCollection> createSceneCollections() {
-        SceneCollection sceneCollection = new SceneCollection();
-        sceneCollection.id = 1;
-        sceneCollection.name = Base64.getEncoder().encodeToString(("TestSceneCollection").getBytes());
-        return new ArrayList<>(List.of(sceneCollection));
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/ShadePositionTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/ShadePositionTest.java
deleted file mode 100644 (file)
index 50dcd0e..0000000
+++ /dev/null
@@ -1,461 +0,0 @@
-/**
- * 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;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
-import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
-import org.openhab.core.library.types.PercentType;
-import org.openhab.core.types.State;
-import org.openhab.core.types.UnDefType;
-
-/**
- * Unit tests for Shade Position setting and getting.
- *
- * @author Andrew Fiddian-Green - Initial contribution
- */
-@NonNullByDefault
-public class ShadePositionTest {
-
-    private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
-
-    /**
-     * General tests of the database of known types.
-     */
-    @Test
-    public void testKnownTypesDatabase() {
-        assertTrue(db.isTypeInDatabase(4));
-        assertTrue(db.isCapabilitiesInDatabase(0));
-        assertTrue(db.isCapabilitiesInDatabase(10));
-
-        assertTrue(db.getCapabilities(0).supportsPrimary());
-        assertTrue(db.getCapabilities(1).supportsTiltOnClosed());
-        assertTrue(db.getCapabilities(2).supportsTilt180());
-        assertTrue(db.getCapabilities(2).supportsTiltAnywhere());
-        assertTrue(db.getCapabilities(4).supportsTilt180());
-        assertTrue(db.getCapabilities(4).supportsTiltAnywhere());
-        assertTrue(db.getCapabilities(5).supportsTilt180());
-        assertFalse(db.getCapabilities(5).supportsPrimary());
-        assertTrue(db.getCapabilities(6).isPrimaryInverted());
-        assertTrue(db.getCapabilities(7).supportsSecondary());
-        assertTrue(db.getCapabilities(8).supportsSecondaryOverlapped());
-        assertTrue(db.getCapabilities(9).supportsSecondaryOverlapped());
-        assertTrue(db.getCapabilities(9).supportsTiltOnClosed());
-
-        assertEquals(db.getType(4).getCapabilities(), 0);
-        assertEquals(db.getType(-1).getCapabilities(), -1);
-
-        assertFalse(db.isTypeInDatabase(99));
-        assertFalse(db.isCapabilitiesInDatabase(99));
-
-        assertFalse(db.getCapabilities(0).isPrimaryInverted());
-        assertFalse(db.getCapabilities(-1).isPrimaryInverted());
-        assertFalse(db.getCapabilities(99).isPrimaryInverted());
-
-        assertFalse(db.getCapabilities(0).supportsSecondary());
-        assertFalse(db.getCapabilities(-1).supportsSecondary());
-        assertFalse(db.getCapabilities(99).supportsSecondary());
-    }
-
-    /**
-     * Helper method; test if shade position is a PercentType and that its value is correct.
-     *
-     * @param position the shade position
-     * @param value the test value to compare with
-     */
-    private void assertShadePosition(State position, int value) {
-        assertEquals(PercentType.class, position.getClass());
-        assertEquals(value, ((PercentType) position).intValue());
-    }
-
-    /**
-     * Test parsing of Capabilities 1 ShadePosition (shade fully up).
-     *
-     */
-    @Test
-    public void testCaps1ShadePositionParsingFullyUp() {
-        Capabilities capabilities = db.getCapabilities(1);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 1)).
-     *
-     */
-    @Test
-    public void testCaps1ShadePositionParsingShadeFullyDown1() {
-        Capabilities capabilities = db.getCapabilities(1);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
-    }
-
-    /**
-     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2)).
-     *
-     */
-    @Test
-    public void testCaps1ShadePositionParsingShadeFullyDown2() {
-        Capabilities capabilities = db.getCapabilities(1);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
-    }
-
-    /**
-     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2) and vane fully open).
-     *
-     */
-    @Test
-    public void testCaps1ShadePositionParsingShadeFullyDownVaneOpen() {
-        Capabilities capabilities = db.getCapabilities(1);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
-    }
-
-    /**
-     * On dual rail shades, it should not be possible to drive the upper rail below the lower rail, or vice-versa. So
-     * the binding code applies constraints on setting such positions. This test checks that the constraint code is
-     * working.
-     */
-    @Test
-    public void testDualRailConstraints() {
-        Capabilities capabilities = db.getCapabilities(7);
-        ShadePosition test = new ShadePosition();
-
-        // ==== OK !! primary at bottom, secondary at top ====
-        test.setPosition(capabilities, PRIMARY_POSITION, 100).setPosition(capabilities, SECONDARY_POSITION, 0);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== OK !! primary at middle, secondary at top ====
-        test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 0);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== OK !! primary at middle, secondary at middle ====
-        test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 50);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== IMPOSSIBLE !! secondary at middle, primary above => test the constraining code ====
-        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
-        test.setPosition(capabilities, SECONDARY_POSITION, 40).setPosition(capabilities, PRIMARY_POSITION, 25);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 40);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 40);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== OK !! secondary at middle, primary below ====
-        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
-        test.setPosition(capabilities, SECONDARY_POSITION, 50).setPosition(capabilities, PRIMARY_POSITION, 75);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 75);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== IMPOSSIBLE !! primary at middle, secondary below => test the constraining code ====
-        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
-        test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 75);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 60);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // ==== OK !! primary at middle, secondary above ====
-        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
-        test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 25);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 25);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Test parsing of DuoLite shades having a secondary blackout shade.
-     *
-     */
-    @Test
-    public void testDuoliteShadePositionParsing() {
-        // blackout shades have capabilities 8
-        Capabilities capabilities = db.getCapabilities(8);
-        ShadePosition test;
-
-        // both shades up
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 50% down
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 50);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 100% down, back shade 0% down
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 100% down, back shade 0% down (ALTERNATE)
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 100% down, back shade 50% down
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 50);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 100% down, back shade 100% down
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Test parsing of DuoLite shades having both a secondary blackout shade, and tilt functionality.
-     *
-     */
-    @Test
-    public void testDuoliteTiltShadePositionParsing() {
-        // blackout shades with tilt have capabilities 9
-        Capabilities capabilities = db.getCapabilities(9);
-        ShadePosition test;
-
-        // front shade up
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 30% down
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 30);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-
-        // front shade 100% down
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
-
-        // tilt 0%
-        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
-
-        // tilt 30%
-        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 30);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
-
-        // tilt 100%
-        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
-
-        // back shade 0% down
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
-
-        // back shade 30% down
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 30);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
-
-        // back shade 100% down
-        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
-
-        // test constraints on impossible values: primary 30% => tilt 30%
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30).setPosition(capabilities,
-                VANE_TILT_POSITION, 30);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
-
-        // test constraints on impossible values: primary 30% => tilt 30% => back shade 30% down
-        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30)
-                .setPosition(capabilities, VANE_TILT_POSITION, 30).setPosition(capabilities, SECONDARY_POSITION, 30);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
-    }
-
-    /**
-     * Test parsing of Capabilities 0 ShadePosition (shade fully up).
-     *
-     */
-    @Test
-    public void testCaps0ShadePositionParsingFullyUp() {
-        Capabilities capabilities = db.getCapabilities(0);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Test parsing of Capabilities 0 ShadePosition (shade fully down).
-     *
-     */
-    @Test
-    public void testCap0ShadePositionParsingShadeFullyDown() {
-        Capabilities capabilities = db.getCapabilities(0);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Helper method; test if shade State is correct.
-     *
-     * @param actual the shade State
-     * @param target the test value to compare with
-     */
-    private void assertShadePosition(State actual, State target) {
-        assertTrue(target.equals(actual));
-    }
-
-    /**
-     * Test parsing of Type 44 ShadePosition (shade fully up).
-     *
-     */
-    @Test
-    public void testType44ShadePositionParsingFullyUp() {
-        Capabilities capabilities = db.getCapabilities(44, null);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
-    }
-
-    /**
-     * Test parsing of Type 44 ShadePosition (shade fully down (method 2) and vane fully open).
-     *
-     */
-    @Test
-    public void testType44ShadePositionParsingShadeFullyDownVaneOpen() {
-        Capabilities capabilities = db.getCapabilities(44, null);
-        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
-        assertNotNull(test);
-        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
-        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
-        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
-    }
-
-    /**
-     * Test the getCapabilities functionality.
-     */
-    @Test
-    public void testGetCapabilities() {
-        Capabilities caps;
-        /*
-         * - type not in database
-         * - null external capabilities
-         * => return default (0)
-         */
-        caps = db.getCapabilities(0, null);
-        assertEquals(0, caps.getValue());
-        /*
-         * - type not in database
-         * - valid external capabilities (1)
-         * => return external capabilities (1)
-         */
-        caps = db.getCapabilities(0, 1);
-        assertEquals(1, caps.getValue());
-        /*
-         * - type not in database
-         * - external capabilities not in database (99)
-         * => return default (0)
-         */
-        caps = db.getCapabilities(0, 99);
-        assertEquals(0, caps.getValue());
-        /*
-         * - type 62 in database
-         * - inherent capabilities (2)
-         * - null external capabilities
-         * => return inherent capabilities (2)
-         */
-        caps = db.getCapabilities(62, null);
-        assertEquals(2, caps.getValue());
-        /*
-         * - type 62 in database
-         * - inherent capabilities (2)
-         * - non matching external capabilities (1)
-         * => return external capabilities (1)
-         */
-        caps = db.getCapabilities(62, 1);
-        assertEquals(1, caps.getValue());
-        /*
-         * - type 44 in database
-         * - inherent capabilities (0)
-         * - with capabilitiesOverride (1)
-         * - non matching external capabilities (2)
-         * => return capabilitiesOverride (1)
-         */
-        caps = db.getCapabilities(44, 2);
-        assertEquals(1, caps.getValue());
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/AutomationChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/AutomationChannelBuilderTest.java
new file mode 100644 (file)
index 0000000..6326ea5
--- /dev/null
@@ -0,0 +1,270 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.builders.AutomationChannelBuilder;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.ScheduledEvent;
+import org.openhab.binding.hdpowerview.internal.providers.MockedLocaleProvider;
+import org.openhab.binding.hdpowerview.internal.providers.MockedTranslationProvider;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelGroupUID;
+import org.openhab.core.thing.ThingUID;
+import org.osgi.framework.Bundle;
+import org.slf4j.LoggerFactory;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+
+/**
+ * Unit tests for {@link AutomationChannelBuilder}.
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class AutomationChannelBuilderTest {
+
+    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
+            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, AutomationChannelBuilderTest.class.getSimpleName()),
+            HDPowerViewBindingConstants.CHANNELTYPE_AUTOMATION_ENABLED);
+
+    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
+            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
+
+    private AutomationChannelBuilder builder = AutomationChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+    private List<Scene> scenes = new ArrayList<>();
+    private List<SceneCollection> sceneCollections = new ArrayList<>();
+
+    @BeforeEach
+    private void setUp() {
+        final Logger logger = (Logger) LoggerFactory.getLogger(AutomationChannelBuilder.class);
+        logger.setLevel(Level.OFF);
+        builder = AutomationChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+
+        Scene scene = new Scene();
+        scene.id = 1;
+        scene.name = Base64.getEncoder().encodeToString(("TestScene").getBytes());
+        scenes = new ArrayList<>(List.of(scene));
+
+        SceneCollection sceneCollection = new SceneCollection();
+        sceneCollection.id = 2;
+        sceneCollection.name = Base64.getEncoder().encodeToString(("TestSceneCollection").getBytes());
+        sceneCollections = new ArrayList<>(List.of(sceneCollection));
+    }
+
+    @Test
+    public void sceneSunriseWeekends() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        scheduledEvent.daySaturday = true;
+        scheduledEvent.daySunday = true;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, At sunrise, Weekends", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneSunsetWeekdays() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNSET);
+        scheduledEvent.dayMonday = true;
+        scheduledEvent.dayTuesday = true;
+        scheduledEvent.dayWednesday = true;
+        scheduledEvent.dayThursday = true;
+        scheduledEvent.dayFriday = true;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, At sunset, Weekdays", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneTimeAllDays() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_TIME);
+        scheduledEvent.dayMonday = true;
+        scheduledEvent.dayTuesday = true;
+        scheduledEvent.dayWednesday = true;
+        scheduledEvent.dayThursday = true;
+        scheduledEvent.dayFriday = true;
+        scheduledEvent.daySaturday = true;
+        scheduledEvent.daySunday = true;
+        scheduledEvent.hour = 6;
+        scheduledEvent.minute = 30;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, 06:30, All days", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneMinutesBeforeSunriseMondayTuesday() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        scheduledEvent.dayMonday = true;
+        scheduledEvent.dayTuesday = true;
+        scheduledEvent.minute = -15;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, 15m before sunrise, Mon, Tue", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneHoursMinutesAfterSunriseMonday() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        scheduledEvent.dayMonday = true;
+        scheduledEvent.minute = 61;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, 1hr 1m after sunrise, Mon", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneMinutesBeforeSunsetWednesdayThursdayFriday() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNSET);
+        scheduledEvent.dayWednesday = true;
+        scheduledEvent.dayThursday = true;
+        scheduledEvent.dayFriday = true;
+        scheduledEvent.minute = -59;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, 59m before sunset, Wed, Thu, Fri", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneHourAfterSunsetFridaySaturdaySunday() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNSET);
+        scheduledEvent.dayFriday = true;
+        scheduledEvent.daySaturday = true;
+        scheduledEvent.daySunday = true;
+        scheduledEvent.minute = 60;
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene, 1hr after sunset, Fri, Sat, Sun", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void sceneCollection() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithSceneCollection(
+                ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).withScheduledEvents(scheduledEvents)
+                .build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestSceneCollection, At sunrise, ", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void suppliedListIsUsed() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> existingChannels = new ArrayList<>(0);
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents)
+                .withChannels(existingChannels).build();
+
+        assertEquals(existingChannels, channels);
+    }
+
+    @Test
+    public void emptyListWhenNoScheduledEvents() {
+        List<Channel> channels = builder.build();
+
+        assertEquals(0, channels.size());
+    }
+
+    @Test
+    public void emptyListWhenNoScenesOrSceneCollections() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(0, channels.size());
+    }
+
+    @Test
+    public void emptyListWhenNoSceneForScheduledEvent() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithSceneCollection(
+                ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(0, channels.size());
+    }
+
+    @Test
+    public void emptyListWhenNoSceneCollectionForScheduledEvent() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).withScheduledEvents(scheduledEvents)
+                .build();
+
+        assertEquals(0, channels.size());
+    }
+
+    @Test
+    public void groupAndIdAreCorrect() {
+        ScheduledEvent scheduledEvent = createScheduledEventWithScene(ScheduledEvent.SCHEDULED_EVENT_TYPE_SUNRISE);
+        scheduledEvent.id = 42;
+        List<ScheduledEvent> scheduledEvents = new ArrayList<>(List.of(scheduledEvent));
+        List<Channel> channels = builder.withScenes(scenes).withScheduledEvents(scheduledEvents).build();
+
+        assertEquals(1, channels.size());
+        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
+        assertEquals(Integer.toString(scheduledEvent.id), channels.get(0).getUID().getIdWithoutGroup());
+    }
+
+    private ScheduledEvent createScheduledEventWithScene(int eventType) {
+        ScheduledEvent scheduledEvent = new ScheduledEvent();
+        scheduledEvent.id = 1;
+        scheduledEvent.sceneId = scenes.get(0).id;
+        scheduledEvent.eventType = eventType;
+        return scheduledEvent;
+    }
+
+    private ScheduledEvent createScheduledEventWithSceneCollection(int eventType) {
+        ScheduledEvent scheduledEvent = new ScheduledEvent();
+        scheduledEvent.id = 1;
+        scheduledEvent.sceneCollectionId = sceneCollections.get(0).id;
+        scheduledEvent.eventType = eventType;
+        return scheduledEvent;
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/HDPowerViewJUnitTests.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/HDPowerViewJUnitTests.java
new file mode 100644 (file)
index 0000000..b28e2cb
--- /dev/null
@@ -0,0 +1,191 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.binding.hdpowerview.internal.dto.BatteryKind;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+import org.openhab.binding.hdpowerview.internal.dto.responses.SceneCollections;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Scenes;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shades;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+
+import com.google.gson.Gson;
+
+/**
+ * Unit tests for HD PowerView binding.
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ * @author Jacob Laursen - Add support for scene groups
+ */
+@NonNullByDefault
+public class HDPowerViewJUnitTests {
+
+    private Gson gson = new Gson();
+
+    private <T> T getObjectFromJson(String filename, Class<T> clazz) throws IOException {
+        try (InputStream inputStream = HDPowerViewJUnitTests.class.getResourceAsStream(filename)) {
+            if (inputStream == null) {
+                throw new IOException("inputstream is null");
+            }
+            byte[] bytes = inputStream.readAllBytes();
+            if (bytes == null) {
+                throw new IOException("Resulting byte-array empty");
+            }
+            String json = new String(bytes, StandardCharsets.UTF_8);
+            return Objects.requireNonNull(gson.fromJson(json, clazz));
+        }
+    }
+
+    /**
+     * Test generic JSON shades response.
+     */
+    @Test
+    public void shadeNameIsDecoded() throws IOException {
+        Shades shades = getObjectFromJson("shades.json", Shades.class);
+        List<ShadeData> shadeData = shades.shadeData;
+        assertNotNull(shadeData);
+        assertEquals(3, shadeData.size());
+        ShadeData shade = shadeData.get(0);
+        assertEquals("Shade 2", shade.getName());
+    }
+
+    /**
+     * Test the BatteryKind decoding.
+     */
+    @Test
+    public void testBatteryKind() throws IOException {
+        Shades shades = getObjectFromJson("shades.json", Shades.class);
+        List<ShadeData> 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.
+     */
+    @Test
+    public void sceneNameIsDecoded() throws IOException {
+        Scenes scenes = getObjectFromJson("scenes.json", Scenes.class);
+        List<Scene> sceneData = scenes.sceneData;
+        assertNotNull(sceneData);
+        assertEquals(4, sceneData.size());
+        Scene scene = sceneData.get(0);
+        assertEquals("Door Open", scene.getName());
+    }
+
+    /**
+     * Test generic JSON scene collection response.
+     */
+    @Test
+    public void sceneCollectionNameIsDecoded() throws IOException {
+        SceneCollections sceneCollections = getObjectFromJson("sceneCollections.json", SceneCollections.class);
+
+        List<SceneCollection> sceneCollectionData = sceneCollections.sceneCollectionData;
+        assertNotNull(sceneCollectionData);
+        assertEquals(1, sceneCollectionData.size());
+
+        SceneCollection sceneCollection = sceneCollectionData.get(0);
+        assertEquals("Børn op", sceneCollection.getName());
+    }
+
+    /**
+     * Test the JSON parsing for a duette top down bottom up shade.
+     */
+    @Test
+    public void duetteTopDownBottomUpShadeIsParsedCorrectly() throws IOException {
+        Shades shades = getObjectFromJson("duette.json", Shades.class);
+        List<ShadeData> shadesData = shades.shadeData;
+        assertNotNull(shadesData);
+
+        assertEquals(1, shadesData.size());
+        ShadeData shadeData = shadesData.get(0);
+        assertNotNull(shadeData);
+
+        assertEquals("Gardin 1", shadeData.getName());
+        assertEquals(63778, shadeData.id);
+
+        ShadePosition shadePos = shadeData.positions;
+        assertNotNull(shadePos);
+
+        Integer capabilitiesValue = shadeData.capabilities;
+        assertNotNull(capabilitiesValue);
+        assertEquals(7, capabilitiesValue.intValue());
+        ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
+        Capabilities capabilities = db.getCapabilities(capabilitiesValue);
+
+        State pos = shadePos.getState(capabilities, PRIMARY_POSITION);
+        assertEquals(PercentType.class, pos.getClass());
+        assertEquals(59, ((PercentType) pos).intValue());
+
+        pos = shadePos.getState(capabilities, SECONDARY_POSITION);
+        assertEquals(PercentType.class, pos.getClass());
+        assertEquals(35, ((PercentType) pos).intValue());
+
+        pos = shadePos.getState(capabilities, VANE_TILT_POSITION);
+        assertEquals(UnDefType.class, pos.getClass());
+
+        assertEquals(3, shadeData.batteryStatus);
+
+        assertEquals(4, shadeData.signalStrength);
+
+        assertEquals(8, shadeData.type);
+
+        assertTrue(db.isTypeInDatabase(shadeData.type));
+        assertTrue(db.isCapabilitiesInDatabase(capabilitiesValue.intValue()));
+
+        assertEquals(db.getType(shadeData.type).getCapabilities(), capabilitiesValue.intValue());
+
+        assertTrue(db.getCapabilities(capabilitiesValue.intValue()).supportsSecondary());
+        assertNotEquals(db.getType(shadeData.type).getCapabilities(), capabilitiesValue.intValue() + 1);
+
+        // ==== when changing position1, position2 value is not changed (vice-versa) ====
+        ShadePosition shadePosition = shadeData.positions;
+        assertNotNull(shadePosition);
+        // ==== position2 ====
+        State position2Old = shadePosition.getState(capabilities, SECONDARY_POSITION);
+        shadePosition.setPosition(capabilities, PRIMARY_POSITION, 99);
+        State position2New = shadePosition.getState(capabilities, SECONDARY_POSITION);
+        assertEquals(PercentType.class, position2Old.getClass());
+        assertEquals(PercentType.class, position2New.getClass());
+        assertEquals(((PercentType) position2Old).intValue(), ((PercentType) position2New).intValue());
+
+        // ==== position2 ====
+        State position1Old = shadePosition.getState(capabilities, PRIMARY_POSITION);
+        shadePosition.setPosition(capabilities, SECONDARY_POSITION, 99);
+        State position1New = shadePosition.getState(capabilities, PRIMARY_POSITION);
+        assertEquals(PercentType.class, position1Old.getClass());
+        assertEquals(PercentType.class, position1New.getClass());
+        assertEquals(((PercentType) position1Old).intValue(), ((PercentType) position1New).intValue());
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/OnlineCommunicationTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/OnlineCommunicationTest.java
new file mode 100644 (file)
index 0000000..d5415f6
--- /dev/null
@@ -0,0 +1,218 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jetty.client.HttpClient;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.dto.ShadeData;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Scenes;
+import org.openhab.binding.hdpowerview.internal.dto.responses.Shades;
+import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
+import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
+import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.types.State;
+
+/**
+ * Unit tests for HD PowerView binding.
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+public class OnlineCommunicationTest {
+
+    private static final Pattern VALID_IP_V4_ADDRESS = Pattern
+            .compile("\\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\.|$)){4}\\b");
+
+    /**
+     * Run a series of ONLINE tests on the communication with a hub.
+     *
+     * @param hubIPAddress must be a valid hub IP address to run the
+     *            tests on; or an INVALID IP address to
+     *            suppress the tests
+     * @param allowShadeMovementCommands set to true if you accept that the tests
+     *            shall physically move the shades
+     */
+    @Test
+    public void testOnlineCommunication() {
+        /*
+         * NOTE: in order to actually run these tests you must have a hub physically
+         * available, and its IP address must be correctly configured in the
+         * "hubIPAddress" string constant e.g. "192.168.1.123"
+         */
+        String hubIPAddress = "192.168.1.xxx";
+
+        /*
+         * NOTE: set allowShadeMovementCommands = true if you accept physically moving
+         * the shades during these tests
+         */
+        boolean allowShadeMovementCommands = false;
+
+        if (VALID_IP_V4_ADDRESS.matcher(hubIPAddress).matches()) {
+            // ==== initialize stuff ====
+            HttpClient client = new HttpClient();
+            assertNotNull(client);
+
+            // ==== start the client ====
+            try {
+                client.start();
+                assertTrue(client.isStarted());
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+
+            HDPowerViewWebTargets webTargets = new HDPowerViewWebTargets(client, hubIPAddress);
+            assertNotNull(webTargets);
+
+            int shadeId = 0;
+            ShadePosition shadePos = null;
+            Shades shadesX = null;
+
+            // ==== get all shades ====
+            try {
+                shadesX = webTargets.getShades();
+                assertNotNull(shadesX);
+                List<ShadeData> shadesData = shadesX.shadeData;
+                assertNotNull(shadesData);
+
+                assertTrue(!shadesData.isEmpty());
+                ShadeData shadeData;
+                shadeData = shadesData.get(0);
+                assertNotNull(shadeData);
+                assertTrue(shadeData.getName().length() > 0);
+                shadePos = shadeData.positions;
+                assertNotNull(shadePos);
+                ShadeData shadeZero = shadesData.get(0);
+                assertNotNull(shadeZero);
+                shadeId = shadeZero.id;
+                assertNotEquals(0, shadeId);
+
+                for (ShadeData shadexData : shadesData) {
+                    String shadeName = shadexData.getName();
+                    assertNotNull(shadeName);
+                }
+            } catch (HubException e) {
+                fail(e.getMessage());
+            }
+
+            // ==== get all scenes ====
+            int sceneId = 0;
+            try {
+                Scenes scenes = webTargets.getScenes();
+                assertNotNull(scenes);
+
+                List<Scene> scenesData = scenes.sceneData;
+                assertNotNull(scenesData);
+
+                assertTrue(!scenesData.isEmpty());
+                Scene sceneZero = scenesData.get(0);
+                assertNotNull(sceneZero);
+                sceneId = sceneZero.id;
+                assertTrue(sceneId > 0);
+
+                for (Scene scene : scenesData) {
+                    String sceneName = scene.getName();
+                    assertNotNull(sceneName);
+                }
+            } catch (HubException e) {
+                fail(e.getMessage());
+            }
+
+            // ==== refresh a specific shade ====
+            ShadeData shadeData = null;
+            try {
+                assertNotEquals(0, shadeId);
+                shadeData = webTargets.refreshShadePosition(shadeId);
+            } catch (HubException e) {
+                fail(e.getMessage());
+            }
+
+            // ==== move a specific shade ====
+            try {
+                assertNotEquals(0, shadeId);
+
+                if (shadeData != null) {
+                    ShadePosition positions = shadeData.positions;
+                    assertNotNull(positions);
+                    Integer capabilitiesValue = shadeData.capabilities;
+                    assertNotNull(capabilitiesValue);
+
+                    Capabilities capabilities = new ShadeCapabilitiesDatabase()
+                            .getCapabilities(capabilitiesValue.intValue());
+
+                    State pos = positions.getState(capabilities, PRIMARY_POSITION);
+                    assertEquals(PercentType.class, pos.getClass());
+
+                    int position = ((PercentType) pos).intValue();
+                    position = position + ((position <= 10) ? 5 : -5);
+
+                    ShadePosition targetPosition = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION,
+                            position);
+                    assertNotNull(targetPosition);
+
+                    if (allowShadeMovementCommands) {
+                        webTargets.moveShade(shadeId, targetPosition);
+
+                        ShadeData newData = webTargets.getShade(shadeId);
+                        ShadePosition actualPosition = newData.positions;
+                        assertNotNull(actualPosition);
+                        assertEquals(targetPosition.getState(capabilities, PRIMARY_POSITION),
+                                actualPosition.getState(capabilities, PRIMARY_POSITION));
+                    }
+                }
+            } catch (HubException e) {
+                fail(e.getMessage());
+            }
+
+            // ==== activate a specific scene ====
+            if (allowShadeMovementCommands) {
+                try {
+                    assertNotNull(sceneId);
+                    webTargets.activateScene(sceneId);
+                } catch (HubProcessingException | HubMaintenanceException e) {
+                    fail(e.getMessage());
+                }
+            }
+
+            // ==== test stop command ====
+            if (allowShadeMovementCommands) {
+                try {
+                    assertNotNull(sceneId);
+                    webTargets.stopShade(shadeId);
+                } catch (HubException e) {
+                    fail(e.getMessage());
+                }
+            }
+
+            // ==== stop the client ====
+            if (client.isRunning()) {
+                try {
+                    client.stop();
+                } catch (Exception e) {
+                    fail(e.getMessage());
+                }
+            }
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneChannelBuilderTest.java
new file mode 100644 (file)
index 0000000..4d6be15
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.builders.SceneChannelBuilder;
+import org.openhab.binding.hdpowerview.internal.dto.Scene;
+import org.openhab.binding.hdpowerview.internal.providers.MockedLocaleProvider;
+import org.openhab.binding.hdpowerview.internal.providers.MockedTranslationProvider;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelGroupUID;
+import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+import org.osgi.framework.Bundle;
+
+/**
+ * Unit tests for {@link SceneChannelBuilder}.
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class SceneChannelBuilderTest {
+
+    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
+            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneChannelBuilderTest.class.getSimpleName()),
+            HDPowerViewBindingConstants.CHANNELTYPE_SCENE_ACTIVATE);
+
+    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
+            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
+
+    private SceneChannelBuilder builder = SceneChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+
+    @BeforeEach
+    private void setUp() {
+        builder = SceneChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+    }
+
+    @Test
+    public void labelIsCorrect() {
+        List<Scene> scenes = createScenes();
+        List<Channel> channels = builder.withScenes(scenes).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestScene", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void descriptionIsCorrect() {
+        List<Scene> scenes = createScenes();
+        List<Channel> channels = builder.withScenes(scenes).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("Activates the scene 'TestScene'", channels.get(0).getDescription());
+    }
+
+    @Test
+    public void groupAndIdAreCorrect() {
+        List<Scene> scenes = createScenes();
+        List<Channel> channels = builder.withScenes(scenes).build();
+
+        assertEquals(1, channels.size());
+        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
+        assertEquals(Integer.toString(scenes.get(0).id), channels.get(0).getUID().getIdWithoutGroup());
+    }
+
+    @Test
+    public void autoUpdatePolicyIsCorrect() {
+        List<Scene> scenes = createScenes();
+        List<Channel> channels = builder.withScenes(scenes).build();
+
+        assertEquals(1, channels.size());
+        assertEquals(AutoUpdatePolicy.VETO, channels.get(0).getAutoUpdatePolicy());
+    }
+
+    @Test
+    public void suppliedListIsUsed() {
+        List<Scene> scenes = createScenes();
+        List<Channel> existingChannels = new ArrayList<>(0);
+        List<Channel> channels = builder.withScenes(scenes).withChannels(existingChannels).build();
+
+        assertEquals(existingChannels, channels);
+    }
+
+    @Test
+    public void emptyListWhenNoScenes() {
+        List<Channel> channels = builder.build();
+
+        assertEquals(0, channels.size());
+    }
+
+    private List<Scene> createScenes() {
+        Scene scene = new Scene();
+        scene.id = 1;
+        scene.name = Base64.getEncoder().encodeToString(("TestScene").getBytes());
+        return new ArrayList<>(List.of(scene));
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneGroupChannelBuilderTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/SceneGroupChannelBuilderTest.java
new file mode 100644 (file)
index 0000000..fc1344e
--- /dev/null
@@ -0,0 +1,116 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.builders.SceneGroupChannelBuilder;
+import org.openhab.binding.hdpowerview.internal.dto.SceneCollection;
+import org.openhab.binding.hdpowerview.internal.providers.MockedLocaleProvider;
+import org.openhab.binding.hdpowerview.internal.providers.MockedTranslationProvider;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelGroupUID;
+import org.openhab.core.thing.ThingUID;
+import org.openhab.core.thing.type.AutoUpdatePolicy;
+import org.osgi.framework.Bundle;
+
+/**
+ * Unit tests for {@link SceneGroupChannelBuilder}.
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class SceneGroupChannelBuilderTest {
+
+    private static final ChannelGroupUID CHANNEL_GROUP_UID = new ChannelGroupUID(
+            new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneGroupChannelBuilderTest.class.getSimpleName()),
+            HDPowerViewBindingConstants.CHANNELTYPE_SCENE_GROUP_ACTIVATE);
+
+    private static final HDPowerViewTranslationProvider TRANSLATION_PROVIDER = new HDPowerViewTranslationProvider(
+            mock(Bundle.class), new MockedTranslationProvider(), new MockedLocaleProvider());
+
+    private SceneGroupChannelBuilder builder = SceneGroupChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+
+    @BeforeEach
+    private void setUp() {
+        builder = SceneGroupChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID);
+    }
+
+    @Test
+    public void labelIsCorrect() {
+        List<SceneCollection> sceneCollections = createSceneCollections();
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("TestSceneCollection", channels.get(0).getLabel());
+    }
+
+    @Test
+    public void descriptionIsCorrect() {
+        List<SceneCollection> sceneCollections = createSceneCollections();
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
+
+        assertEquals(1, channels.size());
+        assertEquals("Activates the scene group 'TestSceneCollection'", channels.get(0).getDescription());
+    }
+
+    @Test
+    public void groupAndIdAreCorrect() {
+        List<SceneCollection> sceneCollections = createSceneCollections();
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
+
+        assertEquals(1, channels.size());
+        assertEquals(CHANNEL_GROUP_UID.getId(), channels.get(0).getUID().getGroupId());
+        assertEquals(Integer.toString(sceneCollections.get(0).id), channels.get(0).getUID().getIdWithoutGroup());
+    }
+
+    @Test
+    public void autoUpdatePolicyIsCorrect() {
+        List<SceneCollection> sceneCollections = createSceneCollections();
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).build();
+
+        assertEquals(1, channels.size());
+        assertEquals(AutoUpdatePolicy.VETO, channels.get(0).getAutoUpdatePolicy());
+    }
+
+    @Test
+    public void suppliedListIsUsed() {
+        List<SceneCollection> sceneCollections = createSceneCollections();
+        List<Channel> existingChannels = new ArrayList<>(0);
+        List<Channel> channels = builder.withSceneCollections(sceneCollections).withChannels(existingChannels).build();
+
+        assertEquals(existingChannels, channels);
+    }
+
+    @Test
+    public void emptyListWhenNoSceneCollections() {
+        List<Channel> channels = builder.build();
+
+        assertEquals(0, channels.size());
+    }
+
+    private List<SceneCollection> createSceneCollections() {
+        SceneCollection sceneCollection = new SceneCollection();
+        sceneCollection.id = 1;
+        sceneCollection.name = Base64.getEncoder().encodeToString(("TestSceneCollection").getBytes());
+        return new ArrayList<>(List.of(sceneCollection));
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/ShadePositionTest.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/ShadePositionTest.java
new file mode 100644 (file)
index 0000000..5ced717
--- /dev/null
@@ -0,0 +1,461 @@
+/**
+ * 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;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
+import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
+import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
+import org.openhab.core.library.types.PercentType;
+import org.openhab.core.types.State;
+import org.openhab.core.types.UnDefType;
+
+/**
+ * Unit tests for Shade Position setting and getting.
+ *
+ * @author Andrew Fiddian-Green - Initial contribution
+ */
+@NonNullByDefault
+public class ShadePositionTest {
+
+    private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
+
+    /**
+     * General tests of the database of known types.
+     */
+    @Test
+    public void testKnownTypesDatabase() {
+        assertTrue(db.isTypeInDatabase(4));
+        assertTrue(db.isCapabilitiesInDatabase(0));
+        assertTrue(db.isCapabilitiesInDatabase(10));
+
+        assertTrue(db.getCapabilities(0).supportsPrimary());
+        assertTrue(db.getCapabilities(1).supportsTiltOnClosed());
+        assertTrue(db.getCapabilities(2).supportsTilt180());
+        assertTrue(db.getCapabilities(2).supportsTiltAnywhere());
+        assertTrue(db.getCapabilities(4).supportsTilt180());
+        assertTrue(db.getCapabilities(4).supportsTiltAnywhere());
+        assertTrue(db.getCapabilities(5).supportsTilt180());
+        assertFalse(db.getCapabilities(5).supportsPrimary());
+        assertTrue(db.getCapabilities(6).isPrimaryInverted());
+        assertTrue(db.getCapabilities(7).supportsSecondary());
+        assertTrue(db.getCapabilities(8).supportsSecondaryOverlapped());
+        assertTrue(db.getCapabilities(9).supportsSecondaryOverlapped());
+        assertTrue(db.getCapabilities(9).supportsTiltOnClosed());
+
+        assertEquals(db.getType(4).getCapabilities(), 0);
+        assertEquals(db.getType(-1).getCapabilities(), -1);
+
+        assertFalse(db.isTypeInDatabase(99));
+        assertFalse(db.isCapabilitiesInDatabase(99));
+
+        assertFalse(db.getCapabilities(0).isPrimaryInverted());
+        assertFalse(db.getCapabilities(-1).isPrimaryInverted());
+        assertFalse(db.getCapabilities(99).isPrimaryInverted());
+
+        assertFalse(db.getCapabilities(0).supportsSecondary());
+        assertFalse(db.getCapabilities(-1).supportsSecondary());
+        assertFalse(db.getCapabilities(99).supportsSecondary());
+    }
+
+    /**
+     * Helper method; test if shade position is a PercentType and that its value is correct.
+     *
+     * @param position the shade position
+     * @param value the test value to compare with
+     */
+    private void assertShadePosition(State position, int value) {
+        assertEquals(PercentType.class, position.getClass());
+        assertEquals(value, ((PercentType) position).intValue());
+    }
+
+    /**
+     * Test parsing of Capabilities 1 ShadePosition (shade fully up).
+     *
+     */
+    @Test
+    public void testCaps1ShadePositionParsingFullyUp() {
+        Capabilities capabilities = db.getCapabilities(1);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 1)).
+     *
+     */
+    @Test
+    public void testCaps1ShadePositionParsingShadeFullyDown1() {
+        Capabilities capabilities = db.getCapabilities(1);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
+    }
+
+    /**
+     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2)).
+     *
+     */
+    @Test
+    public void testCaps1ShadePositionParsingShadeFullyDown2() {
+        Capabilities capabilities = db.getCapabilities(1);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
+    }
+
+    /**
+     * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2) and vane fully open).
+     *
+     */
+    @Test
+    public void testCaps1ShadePositionParsingShadeFullyDownVaneOpen() {
+        Capabilities capabilities = db.getCapabilities(1);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
+    }
+
+    /**
+     * On dual rail shades, it should not be possible to drive the upper rail below the lower rail, or vice-versa. So
+     * the binding code applies constraints on setting such positions. This test checks that the constraint code is
+     * working.
+     */
+    @Test
+    public void testDualRailConstraints() {
+        Capabilities capabilities = db.getCapabilities(7);
+        ShadePosition test = new ShadePosition();
+
+        // ==== OK !! primary at bottom, secondary at top ====
+        test.setPosition(capabilities, PRIMARY_POSITION, 100).setPosition(capabilities, SECONDARY_POSITION, 0);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== OK !! primary at middle, secondary at top ====
+        test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 0);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== OK !! primary at middle, secondary at middle ====
+        test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 50);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== IMPOSSIBLE !! secondary at middle, primary above => test the constraining code ====
+        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
+        test.setPosition(capabilities, SECONDARY_POSITION, 40).setPosition(capabilities, PRIMARY_POSITION, 25);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 40);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 40);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== OK !! secondary at middle, primary below ====
+        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
+        test.setPosition(capabilities, SECONDARY_POSITION, 50).setPosition(capabilities, PRIMARY_POSITION, 75);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 75);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== IMPOSSIBLE !! primary at middle, secondary below => test the constraining code ====
+        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
+        test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 75);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 60);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // ==== OK !! primary at middle, secondary above ====
+        test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
+        test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 25);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 25);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Test parsing of DuoLite shades having a secondary blackout shade.
+     *
+     */
+    @Test
+    public void testDuoliteShadePositionParsing() {
+        // blackout shades have capabilities 8
+        Capabilities capabilities = db.getCapabilities(8);
+        ShadePosition test;
+
+        // both shades up
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 50% down
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 50);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 100% down, back shade 0% down
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 100% down, back shade 0% down (ALTERNATE)
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 100% down, back shade 50% down
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 50);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 100% down, back shade 100% down
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Test parsing of DuoLite shades having both a secondary blackout shade, and tilt functionality.
+     *
+     */
+    @Test
+    public void testDuoliteTiltShadePositionParsing() {
+        // blackout shades with tilt have capabilities 9
+        Capabilities capabilities = db.getCapabilities(9);
+        ShadePosition test;
+
+        // front shade up
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 30% down
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 30);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+
+        // front shade 100% down
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
+
+        // tilt 0%
+        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
+
+        // tilt 30%
+        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 30);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
+
+        // tilt 100%
+        test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
+
+        // back shade 0% down
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
+
+        // back shade 30% down
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 30);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
+
+        // back shade 100% down
+        test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
+
+        // test constraints on impossible values: primary 30% => tilt 30%
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30).setPosition(capabilities,
+                VANE_TILT_POSITION, 30);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
+
+        // test constraints on impossible values: primary 30% => tilt 30% => back shade 30% down
+        test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30)
+                .setPosition(capabilities, VANE_TILT_POSITION, 30).setPosition(capabilities, SECONDARY_POSITION, 30);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
+    }
+
+    /**
+     * Test parsing of Capabilities 0 ShadePosition (shade fully up).
+     *
+     */
+    @Test
+    public void testCaps0ShadePositionParsingFullyUp() {
+        Capabilities capabilities = db.getCapabilities(0);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Test parsing of Capabilities 0 ShadePosition (shade fully down).
+     *
+     */
+    @Test
+    public void testCap0ShadePositionParsingShadeFullyDown() {
+        Capabilities capabilities = db.getCapabilities(0);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Helper method; test if shade State is correct.
+     *
+     * @param actual the shade State
+     * @param target the test value to compare with
+     */
+    private void assertShadePosition(State actual, State target) {
+        assertTrue(target.equals(actual));
+    }
+
+    /**
+     * Test parsing of Type 44 ShadePosition (shade fully up).
+     *
+     */
+    @Test
+    public void testType44ShadePositionParsingFullyUp() {
+        Capabilities capabilities = db.getCapabilities(44, null);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
+    }
+
+    /**
+     * Test parsing of Type 44 ShadePosition (shade fully down (method 2) and vane fully open).
+     *
+     */
+    @Test
+    public void testType44ShadePositionParsingShadeFullyDownVaneOpen() {
+        Capabilities capabilities = db.getCapabilities(44, null);
+        ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
+        assertNotNull(test);
+        assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
+        assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
+        assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
+    }
+
+    /**
+     * Test the getCapabilities functionality.
+     */
+    @Test
+    public void testGetCapabilities() {
+        Capabilities caps;
+        /*
+         * - type not in database
+         * - null external capabilities
+         * => return default (0)
+         */
+        caps = db.getCapabilities(0, null);
+        assertEquals(0, caps.getValue());
+        /*
+         * - type not in database
+         * - valid external capabilities (1)
+         * => return external capabilities (1)
+         */
+        caps = db.getCapabilities(0, 1);
+        assertEquals(1, caps.getValue());
+        /*
+         * - type not in database
+         * - external capabilities not in database (99)
+         * => return default (0)
+         */
+        caps = db.getCapabilities(0, 99);
+        assertEquals(0, caps.getValue());
+        /*
+         * - type 62 in database
+         * - inherent capabilities (2)
+         * - null external capabilities
+         * => return inherent capabilities (2)
+         */
+        caps = db.getCapabilities(62, null);
+        assertEquals(2, caps.getValue());
+        /*
+         * - type 62 in database
+         * - inherent capabilities (2)
+         * - non matching external capabilities (1)
+         * => return external capabilities (1)
+         */
+        caps = db.getCapabilities(62, 1);
+        assertEquals(1, caps.getValue());
+        /*
+         * - type 44 in database
+         * - inherent capabilities (0)
+         * - with capabilitiesOverride (1)
+         * - non matching external capabilities (2)
+         * => return capabilitiesOverride (1)
+         */
+        caps = db.getCapabilities(44, 2);
+        assertEquals(1, caps.getValue());
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedLocaleProvider.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedLocaleProvider.java
new file mode 100644 (file)
index 0000000..d95879f
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * 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.providers;
+
+import java.util.Locale;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.i18n.LocaleProvider;
+
+/**
+ * Locale provider for unit tests.
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class MockedLocaleProvider implements LocaleProvider {
+    public Locale getLocale() {
+        return Locale.ENGLISH;
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedTranslationProvider.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/internal/providers/MockedTranslationProvider.java
new file mode 100644 (file)
index 0000000..9c9503e
--- /dev/null
@@ -0,0 +1,66 @@
+/**
+ * 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.providers;
+
+import static java.util.Map.entry;
+
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.Map;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.i18n.TranslationProvider;
+import org.osgi.framework.Bundle;
+
+/**
+ * Translation provider for unit tests.
+ *
+ * @author Jacob Laursen - Initial contribution
+ */
+@NonNullByDefault
+public class MockedTranslationProvider implements TranslationProvider {
+
+    private static final Map<String, String> TEXTS = Map.ofEntries(
+            entry("dynamic-channel.scene-activate.description", "Activates the scene ''{0}''"),
+            entry("dynamic-channel.scene-group-activate.description", "Activates the scene group ''{0}''"),
+            entry("dynamic-channel.automation-enabled.description", "Enables/disables the automation ''{0}''"),
+            entry("dynamic-channel.automation-enabled.label", "{0}, {1}, {2}"),
+            entry("dynamic-channel.automation.hour", "{0}hr"), entry("dynamic-channel.automation.minute", "{0}m"),
+            entry("dynamic-channel.automation.hour-minute", "{0}hr {1}m"),
+            entry("dynamic-channel.automation.at-sunrise", "At sunrise"),
+            entry("dynamic-channel.automation.before-sunrise", "{0} before sunrise"),
+            entry("dynamic-channel.automation.after-sunrise", "{0} after sunrise"),
+            entry("dynamic-channel.automation.at-sunset", "At sunset"),
+            entry("dynamic-channel.automation.before-sunset", "{0} before sunset"),
+            entry("dynamic-channel.automation.after-sunset", "{0} after sunset"),
+            entry("dynamic-channel.automation.weekdays", "Weekdays"),
+            entry("dynamic-channel.automation.weekends", "Weekends"),
+            entry("dynamic-channel.automation.all-days", "All days"));
+
+    public MockedTranslationProvider() {
+    }
+
+    @Nullable
+    public String getText(@Nullable Bundle bundle, @Nullable String key, @Nullable String defaultText,
+            @Nullable Locale locale) {
+        return "";
+    }
+
+    @Nullable
+    public String getText(@Nullable Bundle bundle, @Nullable String key, @Nullable String defaultText,
+            @Nullable Locale locale, @Nullable Object @Nullable... arguments) {
+        String text = TEXTS.get(key);
+        return MessageFormat.format(text != null ? text : key, arguments);
+    }
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedLocaleProvider.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedLocaleProvider.java
deleted file mode 100644 (file)
index 8161cc8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.providers;
-
-import java.util.Locale;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.i18n.LocaleProvider;
-
-/**
- * Locale provider for unit tests.
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class MockedLocaleProvider implements LocaleProvider {
-    public Locale getLocale() {
-        return Locale.ENGLISH;
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedTranslationProvider.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedTranslationProvider.java
deleted file mode 100644 (file)
index da7152a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * 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.providers;
-
-import static java.util.Map.entry;
-
-import java.text.MessageFormat;
-import java.util.Locale;
-import java.util.Map;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.i18n.TranslationProvider;
-import org.osgi.framework.Bundle;
-
-/**
- * Translation provider for unit tests.
- *
- * @author Jacob Laursen - Initial contribution
- */
-@NonNullByDefault
-public class MockedTranslationProvider implements TranslationProvider {
-
-    private static final Map<String, String> TEXTS = Map.ofEntries(
-            entry("dynamic-channel.scene-activate.description", "Activates the scene ''{0}''"),
-            entry("dynamic-channel.scene-group-activate.description", "Activates the scene group ''{0}''"),
-            entry("dynamic-channel.automation-enabled.description", "Enables/disables the automation ''{0}''"),
-            entry("dynamic-channel.automation-enabled.label", "{0}, {1}, {2}"),
-            entry("dynamic-channel.automation.hour", "{0}hr"), entry("dynamic-channel.automation.minute", "{0}m"),
-            entry("dynamic-channel.automation.hour-minute", "{0}hr {1}m"),
-            entry("dynamic-channel.automation.at-sunrise", "At sunrise"),
-            entry("dynamic-channel.automation.before-sunrise", "{0} before sunrise"),
-            entry("dynamic-channel.automation.after-sunrise", "{0} after sunrise"),
-            entry("dynamic-channel.automation.at-sunset", "At sunset"),
-            entry("dynamic-channel.automation.before-sunset", "{0} before sunset"),
-            entry("dynamic-channel.automation.after-sunset", "{0} after sunset"),
-            entry("dynamic-channel.automation.weekdays", "Weekdays"),
-            entry("dynamic-channel.automation.weekends", "Weekends"),
-            entry("dynamic-channel.automation.all-days", "All days"));
-
-    public MockedTranslationProvider() {
-    }
-
-    @Nullable
-    public String getText(@Nullable Bundle bundle, @Nullable String key, @Nullable String defaultText,
-            @Nullable Locale locale) {
-        return "";
-    }
-
-    @Nullable
-    public String getText(@Nullable Bundle bundle, @Nullable String key, @Nullable String defaultText,
-            @Nullable Locale locale, @Nullable Object @Nullable... arguments) {
-        String text = TEXTS.get(key);
-        return MessageFormat.format(text != null ? text : key, arguments);
-    }
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/duette.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/duette.json
deleted file mode 100644 (file)
index ff4e03e..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-{
-       "shadeIds": [
-               63778
-       ],
-       "shadeData": [
-               {
-                       "id": 63778,
-                       "type": 8,
-                       "batteryStatus": 3,
-                       "batteryStrength": 168,
-                       "roomId": 891,
-                       "firmware": {
-                               "revision": 1,
-                               "subRevision": 8,
-                               "build": 1944
-                       },
-                       "motor": {
-                               "revision": 0,
-                               "subRevision": 0,
-                               "build": 267
-                       },
-                       "name": "R2FyZGluIDE=",
-                       "groupId": 18108,
-                       "positions": {
-                               "posKind2": 2,
-                               "position2": 23194,
-                               "posKind1": 1,
-                               "position1": 26566
-                       },
-                       "signalStrength": 4,
-                       "aid": 2,
-                       "capabilities": 7,
-                       "batteryKind": "unassigned"
-               }
-       ]
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/duette.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/duette.json
new file mode 100644 (file)
index 0000000..ff4e03e
--- /dev/null
@@ -0,0 +1,36 @@
+{
+       "shadeIds": [
+               63778
+       ],
+       "shadeData": [
+               {
+                       "id": 63778,
+                       "type": 8,
+                       "batteryStatus": 3,
+                       "batteryStrength": 168,
+                       "roomId": 891,
+                       "firmware": {
+                               "revision": 1,
+                               "subRevision": 8,
+                               "build": 1944
+                       },
+                       "motor": {
+                               "revision": 0,
+                               "subRevision": 0,
+                               "build": 267
+                       },
+                       "name": "R2FyZGluIDE=",
+                       "groupId": 18108,
+                       "positions": {
+                               "posKind2": 2,
+                               "position2": 23194,
+                               "posKind1": 1,
+                               "position1": 26566
+                       },
+                       "signalStrength": 4,
+                       "aid": 2,
+                       "capabilities": 7,
+                       "batteryKind": "unassigned"
+               }
+       ]
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/sceneCollections.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/sceneCollections.json
new file mode 100644 (file)
index 0000000..7631f89
--- /dev/null
@@ -0,0 +1,15 @@
+{
+       "sceneCollectionIds": [
+               27119
+       ],
+       "sceneCollectionData": [
+               {
+                       "name": "QsO4cm4gb3A=",
+                       "colorId": 12,
+                       "iconId": 17,
+                       "id": 27119,
+                       "order": 0,
+                       "hkAssist": false
+               }
+       ]
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/scenes.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/scenes.json
new file mode 100644 (file)
index 0000000..4cbe0a4
--- /dev/null
@@ -0,0 +1,50 @@
+{
+       "sceneIds": [
+               18097,
+               22663,
+               35821,
+               6551
+       ],
+       "sceneData": [
+               {
+                       "roomId": 59611,
+                       "name": "RG9vciBPcGVu",
+                       "colorId": 6,
+                       "iconId": 160,
+                       "networkNumber": 19,
+                       "id": 18097,
+                       "order": 3,
+                       "hkAssist": false
+               },
+               {
+                       "roomId": 59611,
+                       "name": "SGVhcnQ=",
+                       "colorId": 15,
+                       "iconId": 49,
+                       "networkNumber": 3,
+                       "id": 22663,
+                       "order": 0,
+                       "hkAssist": false
+               },
+               {
+                       "roomId": 59611,
+                       "name": "Q2xvc2U=",
+                       "colorId": 5,
+                       "iconId": 31,
+                       "networkNumber": 8,
+                       "id": 35821,
+                       "order": 2,
+                       "hkAssist": false
+               },
+               {
+                       "roomId": 59611,
+                       "name": "T3Blbg==",
+                       "colorId": 10,
+                       "iconId": 95,
+                       "networkNumber": 20,
+                       "id": 6551,
+                       "order": 1,
+                       "hkAssist": false
+               }
+       ]
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/shades.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/internal/shades.json
new file mode 100644 (file)
index 0000000..cfbf435
--- /dev/null
@@ -0,0 +1,90 @@
+{
+       "shadeIds": [
+               25206,
+               55854,
+               50150
+       ],
+       "shadeData": [
+               {
+                       "id": 25206,
+                       "type": 44,
+                       "batteryStatus": 3,
+                       "batteryStrength": 179,
+                       "roomId": 59611,
+                       "firmware": {
+                               "revision": 1,
+                               "subRevision": 8,
+                               "build": 1944
+                       },
+                       "name": "U2hhZGUgMg==",
+                       "motor": {
+                               "revision": 51,
+                               "subRevision": 51,
+                               "build": 11825
+                       },
+                       "groupId": 64003,
+                       "aid": 2,
+                       "signalStrength": 4,
+                       "capabilities": 0,
+                       "batteryKind": 1,
+                       "positions": {
+                               "posKind1": 3,
+                               "position1": 32579
+                       }
+               },
+               {
+                       "id": 55854,
+                       "type": 44,
+                       "batteryStatus": 3,
+                       "batteryStrength": 187,
+                       "roomId": 59611,
+                       "firmware": {
+                               "revision": 1,
+                               "subRevision": 8,
+                               "build": 1944
+                       },
+                       "motor": {
+                               "revision": 51,
+                               "subRevision": 51,
+                               "build": 11825
+                       },
+                       "name": "U2hhZGUgMw==",
+                       "groupId": 64003,
+                       "aid": 3,
+                       "signalStrength": 4,
+                       "capabilities": 0,
+                       "positions": {
+                               "posKind1": 1,
+                               "position1": 65534
+                       },
+                       "batteryKind": "unassigned"
+               },
+               {
+                       "id": 50150,
+                       "type": 44,
+                       "batteryStatus": 3,
+                       "batteryStrength": 181,
+                       "roomId": 59611,
+                       "name": "U2hhZGUgMQ==",
+                       "firmware": {
+                               "revision": 1,
+                               "subRevision": 8,
+                               "build": 1944
+                       },
+                       "motor": {
+                               "revision": 51,
+                               "subRevision": 51,
+                               "build": 11825
+                       },
+                       "groupId": 64003,
+                       "aid": 4,
+                       "signalStrength": 4,
+                       "capabilities": 0,
+                       "batteryKind": "unassigned",
+                       "positions": {
+                               "posKind1": 1,
+                               "position1": 1040
+                       }
+               }
+       ]
+}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/sceneCollections.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/sceneCollections.json
deleted file mode 100644 (file)
index 7631f89..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-       "sceneCollectionIds": [
-               27119
-       ],
-       "sceneCollectionData": [
-               {
-                       "name": "QsO4cm4gb3A=",
-                       "colorId": 12,
-                       "iconId": 17,
-                       "id": 27119,
-                       "order": 0,
-                       "hkAssist": false
-               }
-       ]
-}
diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/scenes.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/scenes.json
deleted file mode 100644 (file)
index 4cbe0a4..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-{
-       "sceneIds": [
-               18097,
-               22663,
-               35821,
-               6551
-       ],
-       "sceneData": [
-               {
-                       "roomId": 59611,
-                       "name": "RG9vciBPcGVu",
-                       "colorId": 6,
-                       "iconId": 160,
-                       "networkNumber": 19,
-                       "id": 18097,
-                       "order": 3,
-                       "hkAssist": false
-               },
-               {
-                       "roomId": 59611,
-                       "name": "SGVhcnQ=",
-                       "colorId": 15,
-                       "iconId": 49,
-                       "networkNumber": 3,
-                       "id": 22663,
-                       "order": 0,
-                       "hkAssist": false
-               },
-               {
-                       "roomId": 59611,
-                       "name": "Q2xvc2U=",
-                       "colorId": 5,
-                       "iconId": 31,
-                       "networkNumber": 8,
-                       "id": 35821,
-                       "order": 2,
-                       "hkAssist": false
-               },
-               {
-                       "roomId": 59611,
-                       "name": "T3Blbg==",
-                       "colorId": 10,
-                       "iconId": 95,
-                       "networkNumber": 20,
-                       "id": 6551,
-                       "order": 1,
-                       "hkAssist": false
-               }
-       ]
-}
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
deleted file mode 100644 (file)
index cfbf435..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-{
-       "shadeIds": [
-               25206,
-               55854,
-               50150
-       ],
-       "shadeData": [
-               {
-                       "id": 25206,
-                       "type": 44,
-                       "batteryStatus": 3,
-                       "batteryStrength": 179,
-                       "roomId": 59611,
-                       "firmware": {
-                               "revision": 1,
-                               "subRevision": 8,
-                               "build": 1944
-                       },
-                       "name": "U2hhZGUgMg==",
-                       "motor": {
-                               "revision": 51,
-                               "subRevision": 51,
-                               "build": 11825
-                       },
-                       "groupId": 64003,
-                       "aid": 2,
-                       "signalStrength": 4,
-                       "capabilities": 0,
-                       "batteryKind": 1,
-                       "positions": {
-                               "posKind1": 3,
-                               "position1": 32579
-                       }
-               },
-               {
-                       "id": 55854,
-                       "type": 44,
-                       "batteryStatus": 3,
-                       "batteryStrength": 187,
-                       "roomId": 59611,
-                       "firmware": {
-                               "revision": 1,
-                               "subRevision": 8,
-                               "build": 1944
-                       },
-                       "motor": {
-                               "revision": 51,
-                               "subRevision": 51,
-                               "build": 11825
-                       },
-                       "name": "U2hhZGUgMw==",
-                       "groupId": 64003,
-                       "aid": 3,
-                       "signalStrength": 4,
-                       "capabilities": 0,
-                       "positions": {
-                               "posKind1": 1,
-                               "position1": 65534
-                       },
-                       "batteryKind": "unassigned"
-               },
-               {
-                       "id": 50150,
-                       "type": 44,
-                       "batteryStatus": 3,
-                       "batteryStrength": 181,
-                       "roomId": 59611,
-                       "name": "U2hhZGUgMQ==",
-                       "firmware": {
-                               "revision": 1,
-                               "subRevision": 8,
-                               "build": 1944
-                       },
-                       "motor": {
-                               "revision": 51,
-                               "subRevision": 51,
-                               "build": 11825
-                       },
-                       "groupId": 64003,
-                       "aid": 4,
-                       "signalStrength": 4,
-                       "capabilities": 0,
-                       "batteryKind": "unassigned",
-                       "positions": {
-                               "posKind1": 1,
-                               "position1": 1040
-                       }
-               }
-       ]
-}