]> git.basschouten.com Git - openhab-addons.git/blob
1fcb7a529b87e23ce5051275289eff02bcdeadbc
[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(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 primaryStateInverted;
152         private boolean tilt180Degrees;
153
154         public Capabilities() {
155         }
156
157         protected Capabilities(int capabilities) {
158             intValue = capabilities;
159         }
160
161         protected Capabilities text(String text) {
162             this.text = text;
163             return this;
164         }
165
166         protected Capabilities primary() {
167             supportsPrimary = true;
168             return this;
169         }
170
171         protected Capabilities tiltOnClosed() {
172             supportsTiltOnClosed = true;
173             return this;
174         }
175
176         protected Capabilities secondary() {
177             supportsSecondary = true;
178             return this;
179         }
180
181         protected Capabilities tiltAnywhere() {
182             supportsTiltAnywhere = true;
183             return this;
184         }
185
186         protected Capabilities primaryStateInverted() {
187             primaryStateInverted = true;
188             return this;
189         }
190
191         protected Capabilities tilt180() {
192             tilt180Degrees = true;
193             return this;
194         }
195
196         /**
197          * Check if the Capabilities class instance supports a primary shade.
198          *
199          * @return true if it supports a primary shade.
200          */
201         public boolean supportsPrimary() {
202             return supportsPrimary;
203         }
204
205         /**
206          * Check if the Capabilities class instance supports a vane/tilt function (by means of a second motor).
207          *
208          * @return true if it supports a vane/tilt function (by means of a second motor).
209          */
210         public boolean supportsTiltAnywhere() {
211             return supportsTiltAnywhere;
212         }
213
214         /**
215          * Check if the Capabilities class instance supports a secondary shade.
216          *
217          * @return true if it supports a secondary shade.
218          */
219         public boolean supportsSecondary() {
220             return supportsSecondary;
221         }
222
223         /**
224          * Check if the Capabilities class instance supports a secondary shade.
225          *
226          * @return true if the primary shade is inverted.
227          */
228         public boolean isPrimaryStateInverted() {
229             return primaryStateInverted;
230         }
231
232         /**
233          * Check if the Capabilities class instance supports 'tilt when closed'.
234          *
235          * Note: Simple bottom up or vertical shades that do not have independent vane controls, can be tilted in a
236          * simple way, only when they are fully closed, by moving the shade motor a bit further.
237          *
238          * @return true if the primary shade is inverted.
239          */
240         public boolean supportsTiltOnClosed() {
241             return supportsTiltOnClosed && !supportsTiltAnywhere;
242         }
243
244         /**
245          * Check if the Capabilities class instance supports 180 degrees tilt.
246          *
247          * @return true if the primary shade supports 180 degrees.
248          */
249         public boolean supportsTilt180() {
250             return tilt180Degrees;
251         }
252     }
253
254     /**
255      * Determines if a given shade 'type' is in the database.
256      *
257      * @param type the shade 'type' parameter.
258      * @return true if the shade 'type' is known.
259      */
260     public boolean isTypeInDatabase(int type) {
261         return TYPE_DATABASE.containsKey(type);
262     }
263
264     /**
265      * Determines if a given 'capabilities' value is in the database.
266      *
267      * @param capabilities the shade 'capabilities' parameter
268      * @return true if the 'capabilities' value is known
269      */
270     public boolean isCapabilitiesInDatabase(int capabilities) {
271         return CAPABILITIES_DATABASE.containsKey(capabilities);
272     }
273
274     /**
275      * Return a Type class instance that corresponds to the given 'type' parameter.
276      *
277      * @param type the shade 'type' parameter.
278      * @return corresponding instance of Type class.
279      */
280     public Type getType(int type) {
281         return TYPE_DATABASE.getOrDefault(type, new Type());
282     }
283
284     /**
285      * Return a Capabilities class instance that corresponds to the given 'capabilities' parameter.
286      *
287      * @param capabilities the shade 'capabilities' parameter.
288      * @return corresponding instance of Capabilities class.
289      */
290     public Capabilities getCapabilities(int capabilities) {
291         return CAPABILITIES_DATABASE.getOrDefault(capabilities, new Capabilities());
292     }
293
294     private static final String REQUEST_DEVELOPERS_TO_UPDATE = " => Please request developers to update the database!";
295
296     /**
297      * Log a message indicating that 'type' is not in database.
298      *
299      * @param type
300      */
301     public void logTypeNotInDatabase(int type) {
302         logger.warn("The shade 'type:{}' is not in the database!{}", type, REQUEST_DEVELOPERS_TO_UPDATE);
303     }
304
305     /**
306      * Log a message indicating that 'capabilities' is not in database.
307      *
308      * @param capabilities
309      */
310     public void logCapabilitiesNotInDatabase(int type, int capabilities) {
311         logger.warn("The 'capabilities:{}' for shade 'type:{}' are not in the database!{}", capabilities, type,
312                 REQUEST_DEVELOPERS_TO_UPDATE);
313     }
314
315     /**
316      * Log a message indicating the type's capabilities and the passed capabilities are not equal.
317      *
318      * @param type
319      * @param capabilities
320      */
321     public void logCapabilitiesMismatch(int type, int capabilities) {
322         logger.warn("The 'capabilities:{}' reported by shade 'type:{}' don't match the database!{}", capabilities, type,
323                 REQUEST_DEVELOPERS_TO_UPDATE);
324     }
325
326     /**
327      * Log a message indicating that a shade's secondary/vanes support, as observed via its actual JSON payload, does
328      * not match the expected value as declared in its 'type' and 'capabilities'.
329      *
330      * @param propertyKey
331      * @param type
332      * @param capabilities
333      * @param propertyValue
334      */
335     public void logPropertyMismatch(String propertyKey, int type, int capabilities, boolean propertyValue) {
336         logger.warn(
337                 "The '{}:{}' property actually reported by shade 'type:{}' is different "
338                         + "than expected from its 'capabilities:{}' in the database!{}",
339                 propertyKey, propertyValue, type, capabilities, REQUEST_DEVELOPERS_TO_UPDATE);
340     }
341 }