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