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