2 * Copyright (c) 2010-2022 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.database;
15 import java.util.Arrays;
17 import java.util.function.Function;
18 import java.util.stream.Collectors;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Class containing the database of all known shade 'types' and their respective 'capabilities'.
27 * If user systems detect shade types that are not in the database, then this class can issue logger warning messages
28 * indicating such absence, and prompting the user to report it to developers so that the database and the respective
29 * binding functionality can (hopefully) be extended over time.
31 * @author Andrew Fiddian-Green - Initial Contribution
34 public class ShadeCapabilitiesDatabase {
36 private final Logger logger = LoggerFactory.getLogger(ShadeCapabilitiesDatabase.class);
39 * Database of known shade capabilities.
41 private static final Map<Integer, Capabilities> CAPABILITIES_DATABASE = Arrays.asList(
43 new Capabilities(0).primary() .tiltOnClosed() .text("Bottom Up"),
44 new Capabilities(1).primary() .tiltOnClosed() .text("Bottom Up Tilt 90°"),
45 new Capabilities(2).primary() .tiltAnywhere().tilt180() .text("Bottom Up Tilt 180°"),
46 new Capabilities(3).primary() .tiltOnClosed() .text("Vertical"),
47 new Capabilities(4).primary() .tiltAnywhere().tilt180() .text("Vertical Tilt 180°"),
48 new Capabilities(5) .tiltAnywhere().tilt180() .text("Tilt Only 180°"),
49 new Capabilities(6).primaryInverted() .text("Top Down"),
50 new Capabilities(7).primary() .secondary() .text("Top Down Bottom Up"),
51 new Capabilities(8).primary() .secondaryOverlapped().text("Dual Overlapped"),
52 new Capabilities(9).primary() .tiltAnywhere() .secondaryOverlapped().text("Dual Overlapped Tilt 90°"),
54 new Capabilities()).stream().collect(Collectors.toMap(Capabilities::getValue, Function.identity()));
57 * Database of known shade types and corresponding capabilities.
59 private static final Map<Integer, Type> TYPE_DATABASE = Arrays.asList(
61 new Type( 4).capabilities(0).text("Roman"),
62 new Type( 5).capabilities(0).text("Bottom Up"),
63 new Type( 6).capabilities(0).text("Duette"),
64 new Type( 7).capabilities(6).text("Top Down"),
65 new Type( 8).capabilities(7).text("Duette Top Down Bottom Up"),
66 new Type( 9).capabilities(7).text("Duette DuoLite Top Down Bottom Up"),
67 new Type(18).capabilities(1).text("Silhouette"),
68 new Type(23).capabilities(1).text("Silhouette"),
69 new Type(38).capabilities(9).text("Silhouette Duolite"),
70 new Type(42).capabilities(0).text("M25T Roller Blind"),
71 new Type(43).capabilities(1).text("Facette"),
72 new Type(44).capabilities(0).text("Twist"),
73 new Type(47).capabilities(7).text("Pleated Top Down Bottom Up"),
74 new Type(49).capabilities(0).text("AC Roller"),
75 new Type(51).capabilities(2).text("Venetian"),
76 new Type(54).capabilities(3).text("Vertical Slats Left Stack"),
77 new Type(55).capabilities(3).text("Vertical Slats Right Stack"),
78 new Type(56).capabilities(3).text("Vertical Slats Split Stack"),
79 new Type(62).capabilities(2).text("Venetian"),
80 new Type(65).capabilities(8).text("Vignette Duolite"),
81 new Type(66).capabilities(5).text("Shutter"),
82 new Type(69).capabilities(3).text("Curtain Left Stack"),
83 new Type(70).capabilities(3).text("Curtain Right Stack"),
84 new Type(71).capabilities(3).text("Curtain Split Stack"),
85 new Type(79).capabilities(8).text("Duolite Lift"),
87 new Type()).stream().collect(Collectors.toMap(Type::getValue, Function.identity()));
90 * Base class that is extended by Type and Capabilities classes.
92 * @author Andrew Fiddian-Green - Initial Contribution
94 private static class Base {
95 protected int intValue = -1;
96 protected String text = "-- not in database --";
98 public Integer getValue() {
103 public String toString() {
104 return String.format("%s (%d)", text, intValue);
109 * Describes a shade type entry in the database; implements 'capabilities' parameter.
111 * @author Andrew Fiddian-Green - Initial Contribution
113 public static class Type extends Base {
114 private int capabilities = -1;
119 protected Type(int type) {
123 protected Type text(String text) {
128 protected Type capabilities(int capabilities) {
129 this.capabilities = capabilities;
134 * Get shade types's 'capabilities'.
136 * @return 'capabilities'.
138 public int getCapabilities() {
144 * Describes a shade 'capabilities' entry in the database; adds properties indicating its supported functionality.
146 * @author Andrew Fiddian-Green - Initial Contribution
148 public static class Capabilities extends Base {
149 private boolean supportsPrimary;
150 private boolean supportsSecondary;
151 private boolean supportsTiltOnClosed;
152 private boolean supportsTiltAnywhere;
153 private boolean supportsSecondaryOverlapped;
154 private boolean primaryInverted;
155 private boolean tilt180Degrees;
157 public Capabilities() {
160 protected Capabilities secondaryOverlapped() {
161 supportsSecondaryOverlapped = true;
165 protected Capabilities(int capabilities) {
166 intValue = capabilities;
169 protected Capabilities text(String text) {
174 protected Capabilities primary() {
175 supportsPrimary = true;
179 protected Capabilities tiltOnClosed() {
180 supportsTiltOnClosed = true;
184 protected Capabilities secondary() {
185 supportsSecondary = true;
189 protected Capabilities tiltAnywhere() {
190 supportsTiltAnywhere = true;
194 protected Capabilities primaryInverted() {
195 supportsPrimary = true;
196 primaryInverted = true;
200 protected Capabilities tilt180() {
201 tilt180Degrees = true;
206 * Check if the Capabilities class instance supports a primary shade.
208 * @return true if it supports a primary shade.
210 public boolean supportsPrimary() {
211 return supportsPrimary;
215 * Check if the Capabilities class instance supports a vane/tilt function (by means of a second motor).
217 * @return true if it supports a vane/tilt function (by means of a second motor).
219 public boolean supportsTiltAnywhere() {
220 return supportsTiltAnywhere;
224 * Check if the Capabilities class instance supports a secondary shade.
226 * @return true if it supports a secondary shade.
228 public boolean supportsSecondary() {
229 return supportsSecondary;
233 * Check if the Capabilities class instance if the primary shade is inverted.
235 * @return true if the primary shade is inverted.
237 public boolean isPrimaryInverted() {
238 return primaryInverted;
242 * Check if the Capabilities class instance supports 'tilt on closed'.
244 * Note: Simple bottom up or vertical shades that do not have independent vane controls, can be tilted in a
245 * simple way, only when they are fully closed, by moving the shade motor a bit further.
247 * @return true if the it supports tilt on closed.
249 public boolean supportsTiltOnClosed() {
250 return supportsTiltOnClosed && !supportsTiltAnywhere;
254 * Check if the Capabilities class instance supports 180 degrees tilt.
256 * @return true if the tilt range is 180 degrees.
258 public boolean supportsTilt180() {
259 return tilt180Degrees;
263 * Check if the Capabilities class instance supports an overlapped secondary shade.
264 * e.g. a 'DuoLite' or blackout shade.
266 * @return true if the shade supports a secondary overlapped shade.
268 public boolean supportsSecondaryOverlapped() {
269 return supportsSecondaryOverlapped;
274 * Determines if a given shade 'type' is in the database.
276 * @param type the shade 'type' parameter.
277 * @return true if the shade 'type' is known.
279 public boolean isTypeInDatabase(int type) {
280 return TYPE_DATABASE.containsKey(type);
284 * Determines if a given 'capabilities' value is in the database.
286 * @param capabilities the shade 'capabilities' parameter
287 * @return true if the 'capabilities' value is known
289 public boolean isCapabilitiesInDatabase(int capabilities) {
290 return CAPABILITIES_DATABASE.containsKey(capabilities);
294 * Return a Type class instance that corresponds to the given 'type' parameter.
296 * @param type the shade 'type' parameter.
297 * @return corresponding instance of Type class.
299 public Type getType(int type) {
300 return TYPE_DATABASE.getOrDefault(type, new Type());
304 * Return a Capabilities class instance that corresponds to the given 'capabilities' parameter.
306 * @param capabilities the shade 'capabilities' parameter.
307 * @return corresponding instance of Capabilities class.
309 public Capabilities getCapabilities(int capabilities) {
310 return CAPABILITIES_DATABASE.getOrDefault(capabilities, new Capabilities());
313 private static final String REQUEST_DEVELOPERS_TO_UPDATE = " => Please request developers to update the database!";
316 * Log a message indicating that 'type' is not in database.
320 public void logTypeNotInDatabase(int type) {
321 logger.warn("The shade 'type:{}' is not in the database!{}", type, REQUEST_DEVELOPERS_TO_UPDATE);
325 * Log a message indicating that 'capabilities' is not in database.
327 * @param capabilities
329 public void logCapabilitiesNotInDatabase(int type, int capabilities) {
330 logger.warn("The 'capabilities:{}' for shade 'type:{}' are not in the database!{}", capabilities, type,
331 REQUEST_DEVELOPERS_TO_UPDATE);
335 * Log a message indicating the type's capabilities and the passed capabilities are not equal.
338 * @param capabilities
340 public void logCapabilitiesMismatch(int type, int capabilities) {
341 logger.warn("The 'capabilities:{}' reported by shade 'type:{}' don't match the database!{}", capabilities, type,
342 REQUEST_DEVELOPERS_TO_UPDATE);
346 * Log a message indicating that a shade's secondary/vanes support, as observed via its actual JSON payload, does
347 * not match the expected value as declared in its 'type' and 'capabilities'.
351 * @param capabilities
352 * @param propertyValue
354 public void logPropertyMismatch(String propertyKey, int type, int capabilities, boolean propertyValue) {
356 "The '{}:{}' property actually reported by shade 'type:{}' is different "
357 + "than expected from its 'capabilities:{}' in the database!{}",
358 propertyKey, propertyValue, type, capabilities, REQUEST_DEVELOPERS_TO_UPDATE);