]> git.basschouten.com Git - openhab-addons.git/blob
a28a8291bb9ce43d685c0e041bb13ac200f8a315
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2022 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.hdpowerview.internal.database;
14
15 import java.util.Arrays;
16 import java.util.Map;
17 import java.util.function.Function;
18 import java.util.stream.Collectors;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * Class containing the database of all known shade 'types' and their respective 'capabilities'.
26  *
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.
30  *
31  * @author Andrew Fiddian-Green - Initial Contribution
32  */
33 @NonNullByDefault
34 public class ShadeCapabilitiesDatabase {
35
36     private final Logger logger = LoggerFactory.getLogger(ShadeCapabilitiesDatabase.class);
37
38     /*
39      * Database of known shade capabilities.
40      */
41     private static final Map<Integer, Capabilities> CAPABILITIES_DATABASE = Arrays.asList(
42     // @formatter:off
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("Duolite Lift"),
52             new Capabilities(9).primary()        .tiltAnywhere()          .secondaryOverlapped().text("Duolite Lift and Tilt 90°"),
53     // @formatter:on
54             new Capabilities()).stream().collect(Collectors.toMap(Capabilities::getValue, Function.identity()));
55
56     /*
57      * Database of known shade types and corresponding capabilities.
58      */
59     private static final Map<Integer, Type> TYPE_DATABASE = Arrays.asList(
60     // @formatter:off
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(69).capabilities(3).text("Curtain Left Stack"),
82             new Type(70).capabilities(3).text("Curtain Right Stack"),
83             new Type(71).capabilities(3).text("Curtain Split Stack"),
84             new Type(79).capabilities(8).text("Duolite Lift"),
85     // @formatter:on
86             new Type()).stream().collect(Collectors.toMap(Type::getValue, Function.identity()));
87
88     /**
89      * Base class that is extended by Type and Capabilities classes.
90      *
91      * @author Andrew Fiddian-Green - Initial Contribution
92      */
93     private static class Base {
94         protected int intValue = -1;
95         protected String text = "-- not in database --";
96
97         public Integer getValue() {
98             return intValue;
99         }
100
101         @Override
102         public String toString() {
103             return String.format("%s (%d)", text, intValue);
104         }
105     }
106
107     /**
108      * Describes a shade type entry in the database; implements 'capabilities' parameter.
109      *
110      * @author Andrew Fiddian-Green - Initial Contribution
111      */
112     public static class Type extends Base {
113         private int capabilities = -1;
114
115         protected Type() {
116         }
117
118         protected Type(int type) {
119             intValue = type;
120         }
121
122         protected Type text(String text) {
123             this.text = text;
124             return this;
125         }
126
127         protected Type capabilities(int capabilities) {
128             this.capabilities = capabilities;
129             return this;
130         }
131
132         /**
133          * Get shade types's 'capabilities'.
134          *
135          * @return 'capabilities'.
136          */
137         public int getCapabilities() {
138             return capabilities;
139         }
140     }
141
142     /**
143      * Describes a shade 'capabilities' entry in the database; adds properties indicating its supported functionality.
144      *
145      * @author Andrew Fiddian-Green - Initial Contribution
146      */
147     public static class Capabilities extends Base {
148         private boolean supportsPrimary;
149         private boolean supportsSecondary;
150         private boolean supportsTiltOnClosed;
151         private boolean supportsTiltAnywhere;
152         private boolean supportsSecondaryOverlapped;
153         private boolean primaryInverted;
154         private boolean tilt180Degrees;
155
156         public Capabilities() {
157         }
158
159         protected Capabilities secondaryOverlapped() {
160             supportsSecondaryOverlapped = true;
161             return this;
162         }
163
164         protected Capabilities(int capabilities) {
165             intValue = capabilities;
166         }
167
168         protected Capabilities text(String text) {
169             this.text = text;
170             return this;
171         }
172
173         protected Capabilities primary() {
174             supportsPrimary = true;
175             return this;
176         }
177
178         protected Capabilities tiltOnClosed() {
179             supportsTiltOnClosed = true;
180             return this;
181         }
182
183         protected Capabilities secondary() {
184             supportsSecondary = true;
185             return this;
186         }
187
188         protected Capabilities tiltAnywhere() {
189             supportsTiltAnywhere = true;
190             return this;
191         }
192
193         protected Capabilities primaryInverted() {
194             supportsPrimary = true;
195             primaryInverted = true;
196             return this;
197         }
198
199         protected Capabilities tilt180() {
200             tilt180Degrees = true;
201             return this;
202         }
203
204         /**
205          * Check if the Capabilities class instance supports a primary shade.
206          *
207          * @return true if it supports a primary shade.
208          */
209         public boolean supportsPrimary() {
210             return supportsPrimary;
211         }
212
213         /**
214          * Check if the Capabilities class instance supports a vane/tilt function (by means of a second motor).
215          *
216          * @return true if it supports a vane/tilt function (by means of a second motor).
217          */
218         public boolean supportsTiltAnywhere() {
219             return supportsTiltAnywhere;
220         }
221
222         /**
223          * Check if the Capabilities class instance supports a secondary shade.
224          *
225          * @return true if it supports a secondary shade.
226          */
227         public boolean supportsSecondary() {
228             return supportsSecondary;
229         }
230
231         /**
232          * Check if the Capabilities class instance if the primary shade is inverted.
233          *
234          * @return true if the primary shade is inverted.
235          */
236         public boolean isPrimaryInverted() {
237             return primaryInverted;
238         }
239
240         /**
241          * Check if the Capabilities class instance supports 'tilt on closed'.
242          *
243          * Note: Simple bottom up or vertical shades that do not have independent vane controls, can be tilted in a
244          * simple way, only when they are fully closed, by moving the shade motor a bit further.
245          *
246          * @return true if the it supports tilt on closed.
247          */
248         public boolean supportsTiltOnClosed() {
249             return supportsTiltOnClosed && !supportsTiltAnywhere;
250         }
251
252         /**
253          * Check if the Capabilities class instance supports 180 degrees tilt.
254          *
255          * @return true if the tilt range is 180 degrees.
256          */
257         public boolean supportsTilt180() {
258             return tilt180Degrees;
259         }
260
261         /**
262          * Check if the Capabilities class instance supports an overlapped secondary shade.
263          * e.g. a 'DuoLite' or blackout shade.
264          *
265          * @return true if the shade supports a secondary overlapped shade.
266          */
267         public boolean supportsSecondaryOverlapped() {
268             return supportsSecondaryOverlapped;
269         }
270     }
271
272     /**
273      * Determines if a given shade 'type' is in the database.
274      *
275      * @param type the shade 'type' parameter.
276      * @return true if the shade 'type' is known.
277      */
278     public boolean isTypeInDatabase(int type) {
279         return TYPE_DATABASE.containsKey(type);
280     }
281
282     /**
283      * Determines if a given 'capabilities' value is in the database.
284      *
285      * @param capabilities the shade 'capabilities' parameter
286      * @return true if the 'capabilities' value is known
287      */
288     public boolean isCapabilitiesInDatabase(int capabilities) {
289         return CAPABILITIES_DATABASE.containsKey(capabilities);
290     }
291
292     /**
293      * Return a Type class instance that corresponds to the given 'type' parameter.
294      *
295      * @param type the shade 'type' parameter.
296      * @return corresponding instance of Type class.
297      */
298     public Type getType(int type) {
299         return TYPE_DATABASE.getOrDefault(type, new Type());
300     }
301
302     /**
303      * Return a Capabilities class instance that corresponds to the given 'capabilities' parameter.
304      *
305      * @param capabilities the shade 'capabilities' parameter.
306      * @return corresponding instance of Capabilities class.
307      */
308     public Capabilities getCapabilities(int capabilities) {
309         return CAPABILITIES_DATABASE.getOrDefault(capabilities, new Capabilities());
310     }
311
312     private static final String REQUEST_DEVELOPERS_TO_UPDATE = " => Please request developers to update the database!";
313
314     /**
315      * Log a message indicating that 'type' is not in database.
316      *
317      * @param type
318      */
319     public void logTypeNotInDatabase(int type) {
320         logger.warn("The shade 'type:{}' is not in the database!{}", type, REQUEST_DEVELOPERS_TO_UPDATE);
321     }
322
323     /**
324      * Log a message indicating that 'capabilities' is not in database.
325      *
326      * @param capabilities
327      */
328     public void logCapabilitiesNotInDatabase(int type, int capabilities) {
329         logger.warn("The 'capabilities:{}' for shade 'type:{}' are not in the database!{}", capabilities, type,
330                 REQUEST_DEVELOPERS_TO_UPDATE);
331     }
332
333     /**
334      * Log a message indicating the type's capabilities and the passed capabilities are not equal.
335      *
336      * @param type
337      * @param capabilities
338      */
339     public void logCapabilitiesMismatch(int type, int capabilities) {
340         logger.warn("The 'capabilities:{}' reported by shade 'type:{}' don't match the database!{}", capabilities, type,
341                 REQUEST_DEVELOPERS_TO_UPDATE);
342     }
343
344     /**
345      * Log a message indicating that a shade's secondary/vanes support, as observed via its actual JSON payload, does
346      * not match the expected value as declared in its 'type' and 'capabilities'.
347      *
348      * @param propertyKey
349      * @param type
350      * @param capabilities
351      * @param propertyValue
352      */
353     public void logPropertyMismatch(String propertyKey, int type, int capabilities, boolean propertyValue) {
354         logger.warn(
355                 "The '{}:{}' property actually reported by shade 'type:{}' is different "
356                         + "than expected from its 'capabilities:{}' in the database!{}",
357                 propertyKey, propertyValue, type, capabilities, REQUEST_DEVELOPERS_TO_UPDATE);
358     }
359 }