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