From: Jacob Laursen Date: Sat, 30 Jul 2022 18:43:17 +0000 (+0200) Subject: [hdpowerview] Refactor tests (#13175) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=c7f8507caecf73ca84f4b8cbf07f69dad621ffe9;p=openhab-addons.git [hdpowerview] Refactor tests (#13175) * Move test providers to dedicated folder * Simplify resource loading * Clarify what is being tested * Extract online communication test to separate class * Fix SAT findings * Rename variable to comply with naming convention Signed-off-by: Jacob Laursen --- diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java index 37020492e9..b3991f3aad 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewHubHandler.java @@ -99,7 +99,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler { private List sceneCache = new CopyOnWriteArrayList<>(); private List sceneCollectionCache = new CopyOnWriteArrayList<>(); private List scheduledEventCache = new CopyOnWriteArrayList<>(); - private Instant UserDataUpdated = Instant.MIN; + private Instant userDataUpdated = Instant.MIN; private Boolean deprecatedChannelsCreated = false; private final ChannelTypeUID sceneChannelTypeUID = new ChannelTypeUID(HDPowerViewBindingConstants.BINDING_ID, @@ -145,7 +145,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler { } } catch (HubMaintenanceException e) { // exceptions are logged in HDPowerViewWebTargets - UserDataUpdated = Instant.MIN; + userDataUpdated = Instant.MIN; } catch (NumberFormatException | HubException e) { logger.debug("Unexpected error {}", e.getMessage()); } @@ -169,7 +169,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler { hardRefreshPositionInterval = config.hardRefresh; hardRefreshBatteryLevelInterval = config.hardRefreshBatteryLevel; initializeChannels(); - UserDataUpdated = Instant.MIN; + userDataUpdated = Instant.MIN; updateStatus(ThingStatus.UNKNOWN); schedulePoll(); @@ -309,17 +309,17 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler { } } catch (HubMaintenanceException e) { // exceptions are logged in HDPowerViewWebTargets - UserDataUpdated = Instant.MIN; + userDataUpdated = Instant.MIN; } catch (HubException e) { logger.warn("Error connecting to bridge: {}", e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); - UserDataUpdated = Instant.MIN; + userDataUpdated = Instant.MIN; } } private void updateUserDataProperties() throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { - if (UserDataUpdated.isAfter(Instant.now().minus(firmwareVersionValidityPeriod))) { + if (userDataUpdated.isAfter(Instant.now().minus(firmwareVersionValidityPeriod))) { return; } @@ -342,7 +342,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler { properties.put(HDPowerViewBindingConstants.PROPERTY_HUB_NAME, hubName); } updateProperties(properties); - UserDataUpdated = Instant.now(); + userDataUpdated = Instant.now(); } private void updateFirmwareProperties(Map properties, HubFirmware firmwareVersions) { 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 index a5681db3a6..ba6cb99574 100644 --- 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 @@ -29,6 +29,8 @@ 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; @@ -50,9 +52,10 @@ public class AutomationChannelBuilderTest { new ThingUID(HDPowerViewBindingConstants.BINDING_ID, AutomationChannelBuilderTest.class.getSimpleName()), HDPowerViewBindingConstants.CHANNELTYPE_AUTOMATION_ENABLED); - private static final HDPowerViewTranslationProvider translationProvider = new HDPowerViewTranslationProvider( - mock(Bundle.class), new TranslationProviderForTests(), new LocaleProviderForTests()); - private AutomationChannelBuilder builder = AutomationChannelBuilder.create(translationProvider, CHANNEL_GROUP_UID); + 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 scenes = new ArrayList<>(); private List sceneCollections = new ArrayList<>(); @@ -60,7 +63,7 @@ public class AutomationChannelBuilderTest { private void setUp() { final Logger logger = (Logger) LoggerFactory.getLogger(AutomationChannelBuilder.class); logger.setLevel(Level.OFF); - builder = AutomationChannelBuilder.create(translationProvider, CHANNEL_GROUP_UID); + builder = AutomationChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID); Scene scene = new Scene(); scene.id = 1; diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java index 1229c05fb2..438055477a 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/HDPowerViewJUnitTests.java @@ -16,16 +16,13 @@ import static org.junit.jupiter.api.Assertions.*; import static org.openhab.binding.hdpowerview.internal.api.CoordinateSystem.*; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import java.util.Objects; 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.SceneCollections; import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection; @@ -35,15 +32,11 @@ 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; import org.openhab.core.types.UnDefType; import com.google.gson.Gson; -import com.google.gson.JsonParseException; /** * Unit tests for HD PowerView binding. @@ -54,190 +47,19 @@ import com.google.gson.JsonParseException; @NonNullByDefault public class HDPowerViewJUnitTests { - 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"); + private Gson gson = new Gson(); - /* - * load a test JSON string from a file. - */ - private String loadJson(String fileName) { - try { - return Files.readAllLines(Paths.get(String.format("src/test/resources/%s.json", fileName))).stream() - .collect(Collectors.joining()); - } catch (IOException e) { - fail(e.getMessage()); - } - return ""; - } - - /** - * 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()); + private T getObjectFromJson(String filename, Class clazz) throws IOException { + try (InputStream inputStream = HDPowerViewJUnitTests.class.getResourceAsStream(filename)) { + if (inputStream == null) { + throw new IOException("inputstream is null"); } - - 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 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 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()); - } + 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)); } } @@ -245,45 +67,34 @@ public class HDPowerViewJUnitTests { * Test generic JSON shades response. */ @Test - public void shadeResponseIsParsedCorrectly() throws JsonParseException { - final Gson gson = new Gson(); - Shades shades; - String json = loadJson("shades"); - assertNotEquals("", json); - shades = gson.fromJson(json, Shades.class); - assertNotNull(shades); + public void shadeNameIsDecoded() throws IOException { + Shades shades = getObjectFromJson("shades.json", Shades.class); + List shadeData = shades.shadeData; + assertNotNull(shadeData); + assertEquals(3, shadeData.size()); + ShadeData shade = shadeData.get(0); + assertEquals("Shade 2", shade.getName()); } /** * Test generic JSON scene response. */ @Test - public void sceneResponseIsParsedCorrectly() throws JsonParseException { - final Gson gson = new Gson(); - String json = loadJson("scenes"); - assertNotEquals("", json); - - Scenes scenes = gson.fromJson(json, Scenes.class); - assertNotNull(scenes); + public void sceneNameIsDecoded() throws IOException { + Scenes scenes = getObjectFromJson("scenes.json", Scenes.class); List sceneData = scenes.sceneData; assertNotNull(sceneData); assertEquals(4, sceneData.size()); Scene scene = sceneData.get(0); assertEquals("Door Open", scene.getName()); - assertEquals(18097, scene.id); } /** * Test generic JSON scene collection response. */ @Test - public void sceneCollectionResponseIsParsedCorrectly() throws JsonParseException { - final Gson gson = new Gson(); - String json = loadJson("sceneCollections"); - assertNotEquals("", json); - - SceneCollections sceneCollections = gson.fromJson(json, SceneCollections.class); - assertNotNull(sceneCollections); + public void sceneCollectionNameIsDecoded() throws IOException { + SceneCollections sceneCollections = getObjectFromJson("sceneCollections.json", SceneCollections.class); List sceneCollectionData = sceneCollections.sceneCollectionData; assertNotNull(sceneCollectionData); @@ -291,20 +102,14 @@ public class HDPowerViewJUnitTests { SceneCollection sceneCollection = sceneCollectionData.get(0); assertEquals("Børn op", sceneCollection.getName()); - assertEquals(27119, sceneCollection.id); } /** * Test the JSON parsing for a duette top down bottom up shade. */ @Test - public void duetteTopDownBottomUpShadeIsParsedCorrectly() throws JsonParseException { - final Gson gson = new Gson(); - String json = loadJson("duette"); - assertNotEquals("", json); - - Shades shades = gson.fromJson(json, Shades.class); - assertNotNull(shades); + public void duetteTopDownBottomUpShadeIsParsedCorrectly() throws IOException { + Shades shades = getObjectFromJson("duette.json", Shades.class); List shadesData = shades.shadeData; assertNotNull(shadesData); diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/LocaleProviderForTests.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/LocaleProviderForTests.java deleted file mode 100644 index 53747462c2..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/LocaleProviderForTests.java +++ /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; - -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 LocaleProviderForTests implements LocaleProvider { - public Locale getLocale() { - return Locale.ENGLISH; - } -} 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 new file mode 100644 index 0000000000..b8670bb91e --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/OnlineCommunicationTest.java @@ -0,0 +1,219 @@ +/** + * 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 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 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 index 80f867423e..eca2a1f2e9 100644 --- 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 @@ -26,6 +26,8 @@ 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; @@ -44,13 +46,14 @@ public class SceneChannelBuilderTest { new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneChannelBuilderTest.class.getSimpleName()), HDPowerViewBindingConstants.CHANNELTYPE_SCENE_ACTIVATE); - private static final HDPowerViewTranslationProvider translationProvider = new HDPowerViewTranslationProvider( - mock(Bundle.class), new TranslationProviderForTests(), new LocaleProviderForTests()); - private SceneChannelBuilder builder = SceneChannelBuilder.create(translationProvider, CHANNEL_GROUP_UID); + 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(translationProvider, CHANNEL_GROUP_UID); + builder = SceneChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID); } @Test 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 index f5566e4c5b..e2dc8b1b7a 100644 --- 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 @@ -26,6 +26,8 @@ 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; @@ -44,13 +46,14 @@ public class SceneGroupChannelBuilderTest { new ThingUID(HDPowerViewBindingConstants.BINDING_ID, SceneGroupChannelBuilderTest.class.getSimpleName()), HDPowerViewBindingConstants.CHANNELTYPE_SCENE_GROUP_ACTIVATE); - private static final HDPowerViewTranslationProvider translationProvider = new HDPowerViewTranslationProvider( - mock(Bundle.class), new TranslationProviderForTests(), new LocaleProviderForTests()); - private SceneGroupChannelBuilder builder = SceneGroupChannelBuilder.create(translationProvider, CHANNEL_GROUP_UID); + 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(translationProvider, CHANNEL_GROUP_UID); + builder = SceneGroupChannelBuilder.create(TRANSLATION_PROVIDER, CHANNEL_GROUP_UID); } @Test diff --git a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/TranslationProviderForTests.java b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/TranslationProviderForTests.java deleted file mode 100644 index 282c7875d7..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/TranslationProviderForTests.java +++ /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; - -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 TranslationProviderForTests implements TranslationProvider { - - private final static Map 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 TranslationProviderForTests() { - } - - @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 new file mode 100644 index 0000000000..8161cc8e28 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedLocaleProvider.java @@ -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.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 new file mode 100644 index 0000000000..da7152ad75 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/java/org/openhab/binding/hdpowerview/providers/MockedTranslationProvider.java @@ -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.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 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/duette.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/duette.json deleted file mode 100644 index ff4e03e01c..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/resources/duette.json +++ /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/duette.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/duette.json new file mode 100644 index 0000000000..ff4e03e01c --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/duette.json @@ -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/sceneCollections.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/sceneCollections.json new file mode 100644 index 0000000000..7631f89077 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/sceneCollections.json @@ -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/scenes.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/scenes.json new file mode 100644 index 0000000000..4cbe0a4339 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/scenes.json @@ -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/shades.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json new file mode 100644 index 0000000000..9f682952d4 --- /dev/null +++ b/bundles/org.openhab.binding.hdpowerview/src/test/resources/org/openhab/binding/hdpowerview/shades.json @@ -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": "unassigned", + "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/sceneCollections.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/sceneCollections.json deleted file mode 100644 index 7631f89077..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/resources/sceneCollections.json +++ /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/scenes.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/scenes.json deleted file mode 100644 index 4cbe0a4339..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/resources/scenes.json +++ /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/shades.json b/bundles/org.openhab.binding.hdpowerview/src/test/resources/shades.json deleted file mode 100644 index 9f682952d4..0000000000 --- a/bundles/org.openhab.binding.hdpowerview/src/test/resources/shades.json +++ /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": "unassigned", - "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 - } - } - ] -}