]> git.basschouten.com Git - openhab-addons.git/blob
a1f665c1aee5c09910f614639d3dc5ec5ebffe8a
[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().tiltAnywhere()                      .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).primary()                                     .text("Top Down")                 .primaryStateInverted(),
50             new Capabilities(7).primary()                         .secondary().text("Top Down Bottom Up"),
51             new Capabilities(8).primary()                                     .text("Duolite Lift")             .withBlackoutShade(),
52             new Capabilities(9).primary().tiltAnywhere()                      .text("Duolite Lift and Tilt 90°").withBlackoutShade(),
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(42).capabilities(0).text("M25T Roller Blind"),
70             new Type(43).capabilities(1).text("Facette"),
71             new Type(44).capabilities(0).text("Twist"),
72             new Type(47).capabilities(7).text("Pleated Top Down Bottom Up"),
73             new Type(49).capabilities(0).text("AC Roller"),
74             new Type(51).capabilities(2).text("Venetian"),
75             new Type(54).capabilities(3).text("Vertical Slats Left Stack"),
76             new Type(55).capabilities(3).text("Vertical Slats Right Stack"),
77             new Type(56).capabilities(3).text("Vertical Slats Split Stack"),
78             new Type(62).capabilities(2).text("Venetian"),
79             new Type(65).capabilities(8).text("Vignette Duolite"),
80             new Type(69).capabilities(3).text("Curtain Left Stack"),
81             new Type(70).capabilities(3).text("Curtain Right Stack"),
82             new Type(71).capabilities(3).text("Curtain Split Stack"),
83             new Type(79).capabilities(8).text("Duolite Lift"),
84     // @formatter:on
85             new Type()).stream().collect(Collectors.toMap(Type::getValue, Function.identity()));
86
87     /**
88      * Base class that is extended by Type and Capabilities classes.
89      *
90      * @author Andrew Fiddian-Green - Initial Contribution
91      */
92     private static class Base {
93         protected int intValue = -1;
94         protected String text = "-- not in database --";
95
96         public Integer getValue() {
97             return intValue;
98         }
99
100         @Override
101         public String toString() {
102             return String.format("%s (%d)", text, intValue);
103         }
104     }
105
106     /**
107      * Describes a shade type entry in the database; implements 'capabilities' parameter.
108      *
109      * @author Andrew Fiddian-Green - Initial Contribution
110      */
111     public static class Type extends Base {
112         private int capabilities = -1;
113
114         protected Type() {
115         }
116
117         protected Type(int type) {
118             intValue = type;
119         }
120
121         protected Type text(String text) {
122             this.text = text;
123             return this;
124         }
125
126         protected Type capabilities(int capabilities) {
127             this.capabilities = capabilities;
128             return this;
129         }
130
131         /**
132          * Get shade types's 'capabilities'.
133          *
134          * @return 'capabilities'.
135          */
136         public int getCapabilities() {
137             return capabilities;
138         }
139     }
140
141     /**
142      * Describes a shade 'capabilities' entry in the database; adds properties indicating its supported functionality.
143      *
144      * @author Andrew Fiddian-Green - Initial Contribution
145      */
146     public static class Capabilities extends Base {
147         private boolean supportsPrimary;
148         private boolean supportsSecondary;
149         private boolean supportsTiltOnClosed;
150         private boolean supportsTiltAnywhere;
151         private boolean supportsBlackoutShade;
152         private boolean primaryStateInverted;
153         private boolean tilt180Degrees;
154
155         public Capabilities() {
156         }
157
158         protected Capabilities withBlackoutShade() {
159             supportsBlackoutShade = true;
160             return this;
161         }
162
163         protected Capabilities(int capabilities) {
164             intValue = capabilities;
165         }
166
167         protected Capabilities text(String text) {
168             this.text = text;
169             return this;
170         }
171
172         protected Capabilities primary() {
173             supportsPrimary = true;
174             return this;
175         }
176
177         protected Capabilities tiltOnClosed() {
178             supportsTiltOnClosed = true;
179             return this;
180         }
181
182         protected Capabilities secondary() {
183             supportsSecondary = true;
184             return this;
185         }
186
187         protected Capabilities tiltAnywhere() {
188             supportsTiltAnywhere = true;
189             return this;
190         }
191
192         protected Capabilities primaryStateInverted() {
193             primaryStateInverted = true;
194             return this;
195         }
196
197         protected Capabilities tilt180() {
198             tilt180Degrees = true;
199             return this;
200         }
201
202         /**
203          * Check if the Capabilities class instance supports a primary shade.
204          *
205          * @return true if it supports a primary shade.
206          */
207         public boolean supportsPrimary() {
208             return supportsPrimary;
209         }
210
211         /**
212          * Check if the Capabilities class instance supports a vane/tilt function (by means of a second motor).
213          *
214          * @return true if it supports a vane/tilt function (by means of a second motor).
215          */
216         public boolean supportsTiltAnywhere() {
217             return supportsTiltAnywhere;
218         }
219
220         /**
221          * Check if the Capabilities class instance supports a secondary shade.
222          *
223          * @return true if it supports a secondary shade.
224          */
225         public boolean supportsSecondary() {
226             return supportsSecondary;
227         }
228
229         /**
230          * Check if the Capabilities class instance supports a secondary shade.
231          *
232          * @return true if the primary shade is inverted.
233          */
234         public boolean isPrimaryStateInverted() {
235             return primaryStateInverted;
236         }
237
238         /**
239          * Check if the Capabilities class instance supports 'tilt when closed'.
240          *
241          * Note: Simple bottom up or vertical shades that do not have independent vane controls, can be tilted in a
242          * simple way, only when they are fully closed, by moving the shade motor a bit further.
243          *
244          * @return true if the primary shade is inverted.
245          */
246         public boolean supportsTiltOnClosed() {
247             return supportsTiltOnClosed && !supportsTiltAnywhere;
248         }
249
250         /**
251          * Check if the Capabilities class instance supports 180 degrees tilt.
252          *
253          * @return true if the primary shade supports 180 degrees.
254          */
255         public boolean supportsTilt180() {
256             return tilt180Degrees;
257         }
258
259         /**
260          * Check if the Capabilities class instance supports a secondary 'DuoLite' blackout shade.
261          *
262          * @return true if the primary shade supports a secondary blackout shade.
263          */
264         public boolean supportsBlackoutShade() {
265             return supportsBlackoutShade;
266         }
267     }
268
269     /**
270      * Determines if a given shade 'type' is in the database.
271      *
272      * @param type the shade 'type' parameter.
273      * @return true if the shade 'type' is known.
274      */
275     public boolean isTypeInDatabase(int type) {
276         return TYPE_DATABASE.containsKey(type);
277     }
278
279     /**
280      * Determines if a given 'capabilities' value is in the database.
281      *
282      * @param capabilities the shade 'capabilities' parameter
283      * @return true if the 'capabilities' value is known
284      */
285     public boolean isCapabilitiesInDatabase(int capabilities) {
286         return CAPABILITIES_DATABASE.containsKey(capabilities);
287     }
288
289     /**
290      * Return a Type class instance that corresponds to the given 'type' parameter.
291      *
292      * @param type the shade 'type' parameter.
293      * @return corresponding instance of Type class.
294      */
295     public Type getType(int type) {
296         return TYPE_DATABASE.getOrDefault(type, new Type());
297     }
298
299     /**
300      * Return a Capabilities class instance that corresponds to the given 'capabilities' parameter.
301      *
302      * @param capabilities the shade 'capabilities' parameter.
303      * @return corresponding instance of Capabilities class.
304      */
305     public Capabilities getCapabilities(int capabilities) {
306         return CAPABILITIES_DATABASE.getOrDefault(capabilities, new Capabilities());
307     }
308
309     private static final String REQUEST_DEVELOPERS_TO_UPDATE = " => Please request developers to update the database!";
310
311     /**
312      * Log a message indicating that 'type' is not in database.
313      *
314      * @param type
315      */
316     public void logTypeNotInDatabase(int type) {
317         logger.warn("The shade 'type:{}' is not in the database!{}", type, REQUEST_DEVELOPERS_TO_UPDATE);
318     }
319
320     /**
321      * Log a message indicating that 'capabilities' is not in database.
322      *
323      * @param capabilities
324      */
325     public void logCapabilitiesNotInDatabase(int type, int capabilities) {
326         logger.warn("The 'capabilities:{}' for shade 'type:{}' are not in the database!{}", capabilities, type,
327                 REQUEST_DEVELOPERS_TO_UPDATE);
328     }
329
330     /**
331      * Log a message indicating the type's capabilities and the passed capabilities are not equal.
332      *
333      * @param type
334      * @param capabilities
335      */
336     public void logCapabilitiesMismatch(int type, int capabilities) {
337         logger.warn("The 'capabilities:{}' reported by shade 'type:{}' don't match the database!{}", capabilities, type,
338                 REQUEST_DEVELOPERS_TO_UPDATE);
339     }
340
341     /**
342      * Log a message indicating that a shade's secondary/vanes support, as observed via its actual JSON payload, does
343      * not match the expected value as declared in its 'type' and 'capabilities'.
344      *
345      * @param propertyKey
346      * @param type
347      * @param capabilities
348      * @param propertyValue
349      */
350     public void logPropertyMismatch(String propertyKey, int type, int capabilities, boolean propertyValue) {
351         logger.warn(
352                 "The '{}:{}' property actually reported by shade 'type:{}' is different "
353                         + "than expected from its 'capabilities:{}' in the database!{}",
354                 propertyKey, propertyValue, type, capabilities, REQUEST_DEVELOPERS_TO_UPDATE);
355     }
356 }