2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.hdpowerview.internal;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.openhab.binding.hdpowerview.internal.dto.CoordinateSystem.*;
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.junit.jupiter.api.Test;
20 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase;
21 import org.openhab.binding.hdpowerview.internal.database.ShadeCapabilitiesDatabase.Capabilities;
22 import org.openhab.binding.hdpowerview.internal.dto.ShadePosition;
23 import org.openhab.core.library.types.PercentType;
24 import org.openhab.core.types.State;
25 import org.openhab.core.types.UnDefType;
28 * Unit tests for Shade Position setting and getting.
30 * @author Andrew Fiddian-Green - Initial contribution
33 public class ShadePositionTest {
35 private final ShadeCapabilitiesDatabase db = new ShadeCapabilitiesDatabase();
38 * General tests of the database of known types.
41 public void testKnownTypesDatabase() {
42 assertTrue(db.isTypeInDatabase(4));
43 assertTrue(db.isCapabilitiesInDatabase(0));
44 assertTrue(db.isCapabilitiesInDatabase(10));
46 assertTrue(db.getCapabilities(0).supportsPrimary());
47 assertTrue(db.getCapabilities(1).supportsTiltOnClosed());
48 assertTrue(db.getCapabilities(2).supportsTilt180());
49 assertTrue(db.getCapabilities(2).supportsTiltAnywhere());
50 assertTrue(db.getCapabilities(4).supportsTilt180());
51 assertTrue(db.getCapabilities(4).supportsTiltAnywhere());
52 assertTrue(db.getCapabilities(5).supportsTilt180());
53 assertFalse(db.getCapabilities(5).supportsPrimary());
54 assertTrue(db.getCapabilities(6).isPrimaryInverted());
55 assertTrue(db.getCapabilities(7).supportsSecondary());
56 assertTrue(db.getCapabilities(8).supportsSecondaryOverlapped());
57 assertTrue(db.getCapabilities(9).supportsSecondaryOverlapped());
58 assertTrue(db.getCapabilities(9).supportsTiltOnClosed());
60 assertEquals(db.getType(4).getCapabilities(), 0);
61 assertEquals(db.getType(-1).getCapabilities(), -1);
63 assertFalse(db.isTypeInDatabase(99));
64 assertFalse(db.isCapabilitiesInDatabase(99));
66 assertFalse(db.getCapabilities(0).isPrimaryInverted());
67 assertFalse(db.getCapabilities(-1).isPrimaryInverted());
68 assertFalse(db.getCapabilities(99).isPrimaryInverted());
70 assertFalse(db.getCapabilities(0).supportsSecondary());
71 assertFalse(db.getCapabilities(-1).supportsSecondary());
72 assertFalse(db.getCapabilities(99).supportsSecondary());
76 * Helper method; test if shade position is a PercentType and that its value is correct.
78 * @param position the shade position
79 * @param value the test value to compare with
81 private void assertShadePosition(State position, int value) {
82 assertEquals(PercentType.class, position.getClass());
83 assertEquals(value, ((PercentType) position).intValue());
87 * Test parsing of Capabilities 1 ShadePosition (shade fully up).
91 public void testCaps1ShadePositionParsingFullyUp() {
92 Capabilities capabilities = db.getCapabilities(1);
93 ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
95 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
96 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
97 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
101 * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 1)).
105 public void testCaps1ShadePositionParsingShadeFullyDown1() {
106 Capabilities capabilities = db.getCapabilities(1);
107 ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
109 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
110 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
111 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
115 * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2)).
119 public void testCaps1ShadePositionParsingShadeFullyDown2() {
120 Capabilities capabilities = db.getCapabilities(1);
121 ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
123 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
124 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
125 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
129 * Test parsing of Capabilities 1 ShadePosition (shade fully down (method 2) and vane fully open).
133 public void testCaps1ShadePositionParsingShadeFullyDownVaneOpen() {
134 Capabilities capabilities = db.getCapabilities(1);
135 ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
137 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
138 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
139 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
143 * On dual rail shades, it should not be possible to drive the upper rail below the lower rail, or vice-versa. So
144 * the binding code applies constraints on setting such positions. This test checks that the constraint code is
148 public void testDualRailConstraints() {
149 Capabilities capabilities = db.getCapabilities(7);
150 ShadePosition test = new ShadePosition();
152 // ==== OK !! primary at bottom, secondary at top ====
153 test.setPosition(capabilities, PRIMARY_POSITION, 100).setPosition(capabilities, SECONDARY_POSITION, 0);
154 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
155 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
156 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
158 // ==== OK !! primary at middle, secondary at top ====
159 test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 0);
160 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
161 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
162 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
164 // ==== OK !! primary at middle, secondary at middle ====
165 test.setPosition(capabilities, PRIMARY_POSITION, 50).setPosition(capabilities, SECONDARY_POSITION, 50);
166 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
167 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
168 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
170 // ==== IMPOSSIBLE !! secondary at middle, primary above => test the constraining code ====
171 test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
172 test.setPosition(capabilities, SECONDARY_POSITION, 40).setPosition(capabilities, PRIMARY_POSITION, 25);
173 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 40);
174 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 40);
175 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
177 // ==== OK !! secondary at middle, primary below ====
178 test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
179 test.setPosition(capabilities, SECONDARY_POSITION, 50).setPosition(capabilities, PRIMARY_POSITION, 75);
180 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 75);
181 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
182 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
184 // ==== IMPOSSIBLE !! primary at middle, secondary below => test the constraining code ====
185 test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
186 test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 75);
187 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
188 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 60);
189 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
191 // ==== OK !! primary at middle, secondary above ====
192 test.setPosition(capabilities, SECONDARY_POSITION, 0).setPosition(capabilities, PRIMARY_POSITION, 100);
193 test.setPosition(capabilities, PRIMARY_POSITION, 60).setPosition(capabilities, SECONDARY_POSITION, 25);
194 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 60);
195 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 25);
196 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
200 * Test parsing of DuoLite shades having a secondary blackout shade.
204 public void testDuoliteShadePositionParsing() {
205 // blackout shades have capabilities 8
206 Capabilities capabilities = db.getCapabilities(8);
210 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
212 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
213 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
214 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
216 // front shade 50% down
217 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 50);
219 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 50);
220 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
221 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
223 // front shade 100% down, back shade 0% down
224 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
226 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
227 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
228 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
230 // front shade 100% down, back shade 0% down (ALTERNATE)
231 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
233 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
234 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
235 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
237 // front shade 100% down, back shade 50% down
238 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 50);
240 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
241 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 50);
242 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
244 // front shade 100% down, back shade 100% down
245 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
247 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
248 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
249 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
253 * Test parsing of DuoLite shades having both a secondary blackout shade, and tilt functionality.
257 public void testDuoliteTiltShadePositionParsing() {
258 // blackout shades with tilt have capabilities 9
259 Capabilities capabilities = db.getCapabilities(9);
263 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
265 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
266 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
267 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
269 // front shade 30% down
270 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30);
272 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 30);
273 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
274 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
276 // front shade 100% down
277 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
279 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
280 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
281 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
284 test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 0);
286 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
287 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
288 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 0);
291 test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 30);
293 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
294 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
295 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
298 test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 100);
300 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
301 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
302 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
304 // back shade 0% down
305 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 0);
307 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
308 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
309 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
311 // back shade 30% down
312 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 30);
314 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
315 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
316 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
318 // back shade 100% down
319 test = new ShadePosition().setPosition(capabilities, SECONDARY_POSITION, 100);
321 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
322 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 100);
323 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
325 // test constraints on impossible values: primary 30% => tilt 30%
326 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30).setPosition(capabilities,
327 VANE_TILT_POSITION, 30);
329 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
330 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 0);
331 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 30);
333 // test constraints on impossible values: primary 30% => tilt 30% => back shade 30% down
334 test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 30)
335 .setPosition(capabilities, VANE_TILT_POSITION, 30).setPosition(capabilities, SECONDARY_POSITION, 30);
337 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
338 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), 30);
339 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 100);
343 * Test parsing of Capabilities 0 ShadePosition (shade fully up).
347 public void testCaps0ShadePositionParsingFullyUp() {
348 Capabilities capabilities = db.getCapabilities(0);
349 ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
351 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
352 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
353 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
357 * Test parsing of Capabilities 0 ShadePosition (shade fully down).
361 public void testCap0ShadePositionParsingShadeFullyDown() {
362 Capabilities capabilities = db.getCapabilities(0);
363 ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 100);
365 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
366 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
367 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
371 * Helper method; test if shade State is correct.
373 * @param actual the shade State
374 * @param target the test value to compare with
376 private void assertShadePosition(State actual, State target) {
377 assertTrue(target.equals(actual));
381 * Test parsing of Type 44 ShadePosition (shade fully up).
385 public void testType44ShadePositionParsingFullyUp() {
386 Capabilities capabilities = db.getCapabilities(44, null);
387 ShadePosition test = new ShadePosition().setPosition(capabilities, PRIMARY_POSITION, 0);
389 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 0);
390 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
391 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), UnDefType.UNDEF);
395 * Test parsing of Type 44 ShadePosition (shade fully down (method 2) and vane fully open).
399 public void testType44ShadePositionParsingShadeFullyDownVaneOpen() {
400 Capabilities capabilities = db.getCapabilities(44, null);
401 ShadePosition test = new ShadePosition().setPosition(capabilities, VANE_TILT_POSITION, 88);
403 assertShadePosition(test.getState(capabilities, PRIMARY_POSITION), 100);
404 assertShadePosition(test.getState(capabilities, SECONDARY_POSITION), UnDefType.UNDEF);
405 assertShadePosition(test.getState(capabilities, VANE_TILT_POSITION), 88);
409 * Test the getCapabilities functionality.
412 public void testGetCapabilities() {
415 * - type not in database
416 * - null external capabilities
417 * => return default (0)
419 caps = db.getCapabilities(0, null);
420 assertEquals(0, caps.getValue());
422 * - type not in database
423 * - valid external capabilities (1)
424 * => return external capabilities (1)
426 caps = db.getCapabilities(0, 1);
427 assertEquals(1, caps.getValue());
429 * - type not in database
430 * - external capabilities not in database (99)
431 * => return default (0)
433 caps = db.getCapabilities(0, 99);
434 assertEquals(0, caps.getValue());
436 * - type 62 in database
437 * - inherent capabilities (2)
438 * - null external capabilities
439 * => return inherent capabilities (2)
441 caps = db.getCapabilities(62, null);
442 assertEquals(2, caps.getValue());
444 * - type 62 in database
445 * - inherent capabilities (2)
446 * - non matching external capabilities (1)
447 * => return external capabilities (1)
449 caps = db.getCapabilities(62, 1);
450 assertEquals(1, caps.getValue());
452 * - type 44 in database
453 * - inherent capabilities (0)
454 * - with capabilitiesOverride (1)
455 * - non matching external capabilities (2)
456 * => return capabilitiesOverride (1)
458 caps = db.getCapabilities(44, 2);
459 assertEquals(1, caps.getValue());