From c806c766318e73dc675ba0bb98d000ab0a9c2ac9 Mon Sep 17 00:00:00 2001 From: Andrew Fiddian-Green Date: Fri, 10 Jun 2022 20:10:31 +0200 Subject: [PATCH] [hdpowerview] Corrections to shade database and capabilities (#12902) * [hdpowerview] add type 66 shutters to database * [hdpowerview] shade database updates * [hdpowerview] shade database additions and corrections * [hdpowerview] enhance database features * [hdpowerview] fix capabilities 8, 9 functionality * [hdpowerview] adjust tests to match new capabilities * [hdpowerview] correct method visibility * [hdpowerview] test type 44 * [hdpowerview] remove comment * [hdpowerview] name change * [hdpowerview] remove comments attribute * [hdpowerview] refactor capabilities code * [hdpowerview] 'hard' properties now hidden * [hdpowerview] adopt reviewer suggestion * [hdpowerview] refactor constant names Signed-off-by: Andrew Fiddian-Green --- .../internal/HDPowerViewBindingConstants.java | 2 - .../internal/api/ShadePosition.java | 6 +- .../database/ShadeCapabilitiesDatabase.java | 69 ++++-- .../HDPowerViewDeviceDiscoveryService.java | 3 +- .../handler/HDPowerViewShadeHandler.java | 66 +++--- .../hdpowerview/ShadePositionTest.java | 206 ++++++++++++++---- 6 files changed, 255 insertions(+), 97 deletions(-) diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java index 1b19597dfa7..be154bc2ec4 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/HDPowerViewBindingConstants.java @@ -67,8 +67,6 @@ public class HDPowerViewBindingConstants { // Shade properties public static final String PROPERTY_SHADE_TYPE = "type"; public static final String PROPERTY_SHADE_CAPABILITIES = "capabilities"; - public static final String PROPERTY_SECONDARY_RAIL_DETECTED = "secondaryRailDetected"; - public static final String PROPERTY_TILT_ANYWHERE_DETECTED = "tiltAnywhereDetected"; public static final String PROPERTY_MOTOR_FIRMWARE_VERSION = "motorFirmwareVersion"; public static final List NETBIOS_NAMES = Arrays.asList("PDBU-Hub3.0", "PowerView-Hub"); 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 index 00ca3297603..0eee7aff49c 100644 --- 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 @@ -158,7 +158,7 @@ public class ShadePosition { } return new PercentType((int) Math.round((double) position1 / MAX_SHADE * 100)); } - if (PRIMARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) { + if (!SECONDARY_POSITION.equals(posKind1) && shadeCapabilities.supportsSecondaryOverlapped()) { return PercentType.ZERO; } break; @@ -182,6 +182,10 @@ public class ShadePosition { 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: diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java index 47a3b1ed942..6b0bdd90568 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/database/ShadeCapabilitiesDatabase.java @@ -18,6 +18,7 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,16 +41,17 @@ public class ShadeCapabilitiesDatabase { */ private static final Map CAPABILITIES_DATABASE = Arrays.asList( // @formatter:off - new Capabilities(0).primary() .tiltOnClosed() .text("Bottom Up"), + new Capabilities(0).primary() .text("Bottom Up"), new Capabilities(1).primary() .tiltOnClosed() .text("Bottom Up Tilt 90°"), new Capabilities(2).primary() .tiltAnywhere().tilt180() .text("Bottom Up Tilt 180°"), - new Capabilities(3).primary() .tiltOnClosed() .text("Vertical"), - new Capabilities(4).primary() .tiltAnywhere().tilt180() .text("Vertical Tilt 180°"), + new Capabilities(3).primary() .tiltAnywhere().tilt180() .text("Vertical Tilt 180°"), + new Capabilities(4).primary() .text("Vertical"), new Capabilities(5) .tiltAnywhere().tilt180() .text("Tilt Only 180°"), new Capabilities(6).primaryInverted() .text("Top Down"), new Capabilities(7).primary() .secondary() .text("Top Down Bottom Up"), new Capabilities(8).primary() .secondaryOverlapped().text("Dual Overlapped"), - new Capabilities(9).primary() .tiltAnywhere() .secondaryOverlapped().text("Dual Overlapped Tilt 90°"), + // note: for the following capabilities entry the 'tiltOnClosed()' applies to the primary shade + new Capabilities(9).primary() .tiltOnClosed() .secondaryOverlapped().text("Dual Overlapped Tilt 90°"), // @formatter:on new Capabilities()).stream().collect(Collectors.toMap(Capabilities::getValue, Function.identity())); @@ -58,18 +60,20 @@ public class ShadeCapabilitiesDatabase { */ private static final Map TYPE_DATABASE = Arrays.asList( // @formatter:off + new Type( 1).capabilities(0).text("Roller / Solar"), new Type( 4).capabilities(0).text("Roman"), new Type( 5).capabilities(0).text("Bottom Up"), new Type( 6).capabilities(0).text("Duette"), new Type( 7).capabilities(6).text("Top Down"), new Type( 8).capabilities(7).text("Duette Top Down Bottom Up"), new Type( 9).capabilities(7).text("Duette DuoLite Top Down Bottom Up"), - new Type(18).capabilities(1).text("Silhouette"), + new Type(18).capabilities(1).text("Pirouette"), new Type(23).capabilities(1).text("Silhouette"), new Type(38).capabilities(9).text("Silhouette Duolite"), new Type(42).capabilities(0).text("M25T Roller Blind"), new Type(43).capabilities(1).text("Facette"), - new Type(44).capabilities(0).text("Twist"), + // note: the following shade type has the functionality of a capabilities 1 shade + new Type(44).capabilities(0).text("Twist").capabilitiesOverride(1), new Type(47).capabilities(7).text("Pleated Top Down Bottom Up"), new Type(49).capabilities(0).text("AC Roller"), new Type(51).capabilities(2).text("Venetian"), @@ -79,9 +83,9 @@ public class ShadeCapabilitiesDatabase { new Type(62).capabilities(2).text("Venetian"), new Type(65).capabilities(8).text("Vignette Duolite"), new Type(66).capabilities(5).text("Shutter"), - new Type(69).capabilities(3).text("Curtain Left Stack"), - new Type(70).capabilities(3).text("Curtain Right Stack"), - new Type(71).capabilities(3).text("Curtain Split Stack"), + new Type(69).capabilities(4).text("Curtain Left Stack"), + new Type(70).capabilities(4).text("Curtain Right Stack"), + new Type(71).capabilities(4).text("Curtain Split Stack"), new Type(79).capabilities(8).text("Duolite Lift"), // @formatter:on new Type()).stream().collect(Collectors.toMap(Type::getValue, Function.identity())); @@ -112,6 +116,7 @@ public class ShadeCapabilitiesDatabase { */ public static class Type extends Base { private int capabilities = -1; + private int capabilitiesOverride = -1; protected Type() { } @@ -130,6 +135,11 @@ public class ShadeCapabilitiesDatabase { return this; } + protected Type capabilitiesOverride(int capabilitiesOverride) { + this.capabilitiesOverride = capabilitiesOverride; + return this; + } + /** * Get shade types's 'capabilities'. * @@ -138,6 +148,15 @@ public class ShadeCapabilitiesDatabase { public int getCapabilities() { return capabilities; } + + /** + * Get shade's type specific 'capabilities'. + * + * @return 'typeCapabilities'. + */ + public int getCapabilitiesOverride() { + return capabilitiesOverride; + } } /** @@ -301,13 +320,35 @@ public class ShadeCapabilitiesDatabase { } /** - * Return a Capabilities class instance that corresponds to the given 'capabilities' parameter. + * Return a Capabilities class instance that corresponds to the given 'capabilitiesId' parameter. If the + * 'capabilitiesId' parameter is for a valid capabilities entry in the database, then that respective Capabilities + * class instance is returned. Otherwise a blank Capabilities class instance is returned. * - * @param capabilities the shade 'capabilities' parameter. - * @return corresponding instance of Capabilities class. + * @param capabilitiesId the target capabilities Id. + * @return corresponding Capabilities class instance. */ - public Capabilities getCapabilities(int capabilities) { - return CAPABILITIES_DATABASE.getOrDefault(capabilities, new Capabilities()); + public Capabilities getCapabilities(@Nullable Integer capabilitiesId) { + return CAPABILITIES_DATABASE.getOrDefault(capabilitiesId != null ? capabilitiesId.intValue() : -1, + new Capabilities()); + } + + /** + * Return a Capabilities class instance that corresponds to the given 'typeId' parameter. If the 'typeId' parameter + * is a valid type in the database, and it has a 'capabilitiesOverride' value, then an instance of the respective + * overridden Capabilities class is returned. Otherwise if the 'capabilitiesId' parameter is for a valid + * capabilities entry in the database, then that respective Capabilities class instance is returned. Otherwise a + * blank Capabilities class instance is returned. + * + * @param typeId the target shade type Id (to check if it has a 'capabilitiesOverride' value). + * @param capabilitiesId the target capabilities value (when type Id does not have a 'capabilitiesOverride'). + * @return corresponding Capabilities class instance. + */ + public Capabilities getCapabilities(int typeId, @Nullable Integer capabilitiesId) { + int targetCapabilities = TYPE_DATABASE.getOrDefault(typeId, new Type()).getCapabilitiesOverride(); + if (targetCapabilities < 0) { + targetCapabilities = capabilitiesId != null ? capabilitiesId.intValue() : -1; + } + return getCapabilities(targetCapabilities); } private static final String REQUEST_DEVELOPERS_TO_UPDATE = " => Please request developers to update the database!"; diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java index f61be9f9a9b..d8f5d9862d0 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/discovery/HDPowerViewDeviceDiscoveryService.java @@ -115,8 +115,7 @@ public class HDPowerViewDeviceDiscoveryService extends AbstractDiscoveryService } String id = Integer.toString(shadeData.id); ThingUID thingUID = new ThingUID(HDPowerViewBindingConstants.THING_TYPE_SHADE, bridgeUid, id); - Integer caps = shadeData.capabilities; - Capabilities capabilities = db.getCapabilities((caps != null) ? caps.intValue() : -1); + Capabilities capabilities = db.getCapabilities(shadeData.capabilities); DiscoveryResultBuilder builder = DiscoveryResultBuilder.create(thingUID).withLabel(shadeData.getName()) .withBridge(bridgeUid).withProperty(HDPowerViewShadeConfiguration.ID, id) diff --git a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java index 2c072811c64..5a3e203af6c 100644 --- a/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java +++ b/bundles/org.openhab.binding.hdpowerview/src/main/java/org/openhab/binding/hdpowerview/internal/handler/HDPowerViewShadeHandler.java @@ -15,6 +15,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 java.util.HashMap; import java.util.Map; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -75,6 +76,10 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { private static final String COMMAND_CALIBRATE = "CALIBRATE"; private static final String COMMAND_IDENTIFY = "IDENTIFY"; + private static final String DETECTED_SECONDARY_RAIL = "secondaryRailDetected"; + private static final String DETECTED_TILT_ANYWHERE = "tiltAnywhereDetected"; + private final Map detectedCapabilities = new HashMap<>(); + private final Logger logger = LoggerFactory.getLogger(HDPowerViewShadeHandler.class); private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase(); @@ -260,14 +265,13 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { // Already cached. return; } - Integer value = shade.capabilities; - if (value != null) { - int valueAsInt = value.intValue(); - logger.debug("Caching capabilities {} for shade {}", valueAsInt, shade.id); - capabilities = db.getCapabilities(valueAsInt); - } else { - logger.debug("Capabilities not included in shade response"); + Capabilities capabilities = db.getCapabilities(shade.type, shade.capabilities); + if (capabilities.getValue() < 0) { + logger.debug("Unable to set capabilities for shade {}", shade.id); + return; } + logger.debug("Caching capabilities {} for shade {}", capabilities.getValue(), shade.id); + this.capabilities = capabilities; } private Capabilities getCapabilitiesOrDefault() { @@ -304,9 +308,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { } // update 'capabilities' property - final Integer temp = shadeData.capabilities; - final int capabilitiesVal = temp != null ? temp.intValue() : -1; - Capabilities capabilities = db.getCapabilities(capabilitiesVal); + Capabilities capabilities = db.getCapabilities(shadeData.capabilities); + final int capabilitiesVal = capabilities.getValue(); propKey = HDPowerViewBindingConstants.PROPERTY_SHADE_CAPABILITIES; propOldVal = properties.getOrDefault(propKey, ""); propNewVal = capabilities.toString(); @@ -338,7 +341,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { } /** - * After a hard refresh, update the Thing's properties based on the contents of the provided ShadeData. + * After a hard refresh, update the Thing's detected capabilities based on the contents of the provided ShadeData. * * Checks if the secondary support capabilities in the database of known Shade 'types' and 'capabilities' matches * that implied by the ShadeData and logs any incompatible values, so that developers can be kept updated about the @@ -346,35 +349,34 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { * * @param shadeData */ - private void updateHardProperties(ShadeData shadeData) { + private void updateDetectedCapabilities(ShadeData shadeData) { final ShadePosition positions = shadeData.positions; if (positions == null) { return; } Capabilities capabilities = getCapabilitiesOrDefault(); - final Map properties = getThing().getProperties(); - // update 'secondary rail detected' property - String propKey = HDPowerViewBindingConstants.PROPERTY_SECONDARY_RAIL_DETECTED; - String propOldVal = properties.getOrDefault(propKey, ""); - boolean propNewBool = positions.secondaryRailDetected(); - String propNewVal = String.valueOf(propNewBool); - if (!propNewVal.equals(propOldVal)) { - getThing().setProperty(propKey, propNewVal); - if (propNewBool != capabilities.supportsSecondary()) { - db.logPropertyMismatch(propKey, shadeData.type, capabilities.getValue(), propNewBool); + // update 'secondary rail' detected capability + String capsKey = DETECTED_SECONDARY_RAIL; + String capsOldVal = detectedCapabilities.getOrDefault(capsKey, ""); + boolean capsNewBool = positions.secondaryRailDetected(); + String capsNewVal = String.valueOf(capsNewBool); + if (!capsNewVal.equals(capsOldVal)) { + detectedCapabilities.put(capsKey, capsNewVal); + if (capsNewBool != capabilities.supportsSecondary()) { + db.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool); } } - // update 'tilt anywhere detected' property - propKey = HDPowerViewBindingConstants.PROPERTY_TILT_ANYWHERE_DETECTED; - propOldVal = properties.getOrDefault(propKey, ""); - propNewBool = positions.tiltAnywhereDetected(); - propNewVal = String.valueOf(propNewBool); - if (!propNewVal.equals(propOldVal)) { - getThing().setProperty(propKey, propNewVal); - if (propNewBool != capabilities.supportsTiltAnywhere()) { - db.logPropertyMismatch(propKey, shadeData.type, capabilities.getValue(), propNewBool); + // update 'tilt anywhere' detected capability + capsKey = DETECTED_TILT_ANYWHERE; + capsOldVal = detectedCapabilities.getOrDefault(capsKey, ""); + capsNewBool = positions.tiltAnywhereDetected(); + capsNewVal = String.valueOf(capsNewBool); + if (!capsNewVal.equals(capsOldVal)) { + detectedCapabilities.put(capsKey, capsNewVal); + if (capsNewBool != capabilities.supportsTiltAnywhere()) { + db.logPropertyMismatch(capsKey, shadeData.type, capabilities.getValue(), capsNewBool); } } } @@ -523,7 +525,7 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler { case POSITION: shadeData = webTargets.refreshShadePosition(shadeId); updateShadePositions(shadeData); - updateHardProperties(shadeData); + updateDetectedCapabilities(shadeData); break; case SURVEY: Survey survey = webTargets.getShadeSurvey(shadeId); 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 index ce74424e50a..b944c27d56e 100644 --- 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 @@ -43,17 +43,18 @@ public class ShadePositionTest { assertTrue(db.isCapabilitiesInDatabase(0)); assertTrue(db.getCapabilities(0).supportsPrimary()); - assertTrue(db.getCapabilities(0).supportsTiltOnClosed()); assertTrue(db.getCapabilities(1).supportsTiltOnClosed()); assertTrue(db.getCapabilities(2).supportsTilt180()); - assertTrue(db.getCapabilities(3).supportsTiltOnClosed()); - assertTrue(db.getCapabilities(4).supportsTilt180()); + assertTrue(db.getCapabilities(2).supportsTiltAnywhere()); + assertTrue(db.getCapabilities(3).supportsTilt180()); + assertTrue(db.getCapabilities(3).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); @@ -82,57 +83,59 @@ public class ShadePositionTest { } /** - * Test parsing of ShadePosition (shade fully up). + * Test parsing of Capabilities 1 ShadePosition (shade fully up). * */ @Test - public void testShadePositionParsingFullyUp() { - Capabilities capabilities = db.getCapabilities(0); + public void testCaps1ShadePositionParsingFullyUp() { + Capabilities capabilities = db.getCapabilities(1); ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0); assertNotNull(test); - State pos = test.getState(capabilities, PRIMARY_POSITION); - assertShadePosition(pos, 0); - pos = test.getState(capabilities, VANE_TILT_POSITION); - assertTrue(UnDefType.UNDEF.equals(pos)); + 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 ShadePosition (shade fully down (method 1)). + * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 1)). * */ @Test - public void testShadePositionParsingShadeFullyDown1() { - Capabilities capabilities = db.getCapabilities(0); + 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 ShadePosition (shade fully down (method 2)). + * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2)). * */ @Test - public void testShadePositionParsingShadeFullyDown2() { - Capabilities capabilities = db.getCapabilities(0); + 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 ShadePosition (shade fully down (method 2) and vane fully open). + * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2) and vane fully open). * */ @Test - public void testShadePositionParsingShadeFullyDownVaneOpen() { - Capabilities capabilities = db.getCapabilities(0); - ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 100); + 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, VANE_TILT_POSITION), 100); + assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF); + assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88); } /** @@ -149,40 +152,47 @@ public class ShadePositionTest { 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); } /** @@ -200,40 +210,46 @@ public class ShadePositionTest { 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 anywhere functionality. + * Test parsing of DuoLite shades having both a secondary blackout shade, and tilt functionality. * */ @Test @@ -242,51 +258,149 @@ public class ShadePositionTest { Capabilities capabilities = db.getCapabilities(9); ShadePosition test; - // both shades up, tilt 0% - test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0).setPosition(capabilities, - VANE_TILT_POSITION, 0); + // 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 50% down, tilt 30% - test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, - VANE_TILT_POSITION, 30); + // front shade 30% down + test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30); assertNotNull(test); - assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50); + assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 30); assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0); - assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30); + assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF); - // front shade 100% down, back shade 0% down, tilt 30% - test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100).setPosition(capabilities, - VANE_TILT_POSITION, 30); + // 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); - // front shade 100% down, back shade 0% down, tilt 30% (ALTERNATE) - test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(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), 30); + assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100); - // front shade 100% down, back shade 50% down, tilt 30% - test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 50).setPosition(capabilities, - VANE_TILT_POSITION, 30); + // 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), 50); - assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30); + assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0); + assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100); - // front shade 100% down, back shade 100% down, tilt 70% - test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100).setPosition(capabilities, - VANE_TILT_POSITION, 70); + // 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), 70); + 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); } }