]> git.basschouten.com Git - openhab-addons.git/blob
85a47d6da058f98868fd538b9e1df30b40bc51be
[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.velux.internal;
14
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.core.items.GenericItem;
20 import org.openhab.core.library.items.NumberItem;
21 import org.openhab.core.library.items.RollershutterItem;
22 import org.openhab.core.library.items.StringItem;
23 import org.openhab.core.library.items.SwitchItem;
24 import org.openhab.core.thing.ThingTypeUID;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 /**
29  * Enumeration of Types of a Velux item.
30  * <br>
31  * Provides information about:
32  * <ul>
33  * <li>associated thing identified by String</li>
34  * <li>defined channel identified by String</li>
35  * <li>{@link #getItemClass} item class,</li>
36  * <li>{@link #isReadable} about a read possibility,</li>
37  * <li>{@link #isWritable} about a write possibility,</li>
38  * <li>{@link #isExecutable} about an execute possibility,</li>
39  * <li>{@link #isToBeRefreshed} about necessarily to be refreshed,</li>
40  * <li>{@link #isToBeRefreshedNow} about necessarily to be refreshed at this time,</li>
41  * <li>{@link #isChannel} as indication of being handled as Channel of a thing,</li>
42  * <li>{@link #isProperty} as indication of being handled as property of a thing.</li>
43  * </ul>
44  *
45  * In addition there are helper methods providing information about:
46  *
47  * <ul>
48  * <li>{@link #getIdentifier} returning the common identifier string,</li>
49  * <li>{@link #getByThingAndChannel} to retrieve an enum instance selected by Thing
50  * and Channel identifier,</li>
51  * <li>{@link #getPropertyEntriesByThing} to retrieve any Thing identifiers as array of
52  * String,</li>
53  * </ul>
54  * <p>
55  * Within this enumeration, the expected behaviour of the OpenHAB item (resp. Channel or Property) is set. For each kind
56  * of Channel (i.e. bridge or device) parameter a set of information is defined:
57  * <ul>
58  * <li>
59  * Unique identification by:
60  * <ul>
61  * <li>Thing name as string,</li>
62  * <li>Channel name as string,</li>
63  * </ul>
64  * </li>
65  * <li>Channel type as OpenHAB type,</li>
66  * <li>ability flag whether this item is to be read,</li>
67  * <li>ability flag whether this item is able to be modified,</li>
68  * <li>ability flag whether this item is to be used as execution trigger.</li>
69  * </ul>
70  *
71  * @author Guenther Schreiner - Initial contribution
72  *
73  */
74 @NonNullByDefault
75 public enum VeluxItemType {
76     // @formatter:off
77     UNKNOWN(VeluxBindingConstants.THING_TYPE_BRIDGE,                            VeluxBindingConstants.UNKNOWN,                       TypeFlavor.UNUSABLE),
78     //
79     BINDING_INFORMATION(VeluxBindingConstants.THING_TYPE_BINDING,               VeluxBindingConstants.CHANNEL_BINDING_INFORMATION,   TypeFlavor.READONLY_VOLATILE_STRING),
80     //
81     BRIDGE_STATUS(VeluxBindingConstants.THING_TYPE_BRIDGE,                      VeluxBindingConstants.CHANNEL_BRIDGE_STATUS,         TypeFlavor.READONLY_VOLATILE_STRING),
82     BRIDGE_DOWNTIME(VeluxBindingConstants.THING_TYPE_BRIDGE,                    VeluxBindingConstants.CHANNEL_BRIDGE_DOWNTIME,       TypeFlavor.READONLY_VOLATILE_NUMBER),
83     BRIDGE_RELOAD(VeluxBindingConstants.THING_TYPE_BRIDGE,                      VeluxBindingConstants.CHANNEL_BRIDGE_RELOAD,         TypeFlavor.INITIATOR),
84     BRIDGE_DO_DETECTION(VeluxBindingConstants.THING_TYPE_BRIDGE,                VeluxBindingConstants.CHANNEL_BRIDGE_DO_DETECTION,   TypeFlavor.INITIATOR),
85
86     BRIDGE_FIRMWARE(VeluxBindingConstants.THING_TYPE_BRIDGE,                    VeluxBindingConstants.PROPERTY_BRIDGE_FIRMWARE,      TypeFlavor.PROPERTY),
87     BRIDGE_ADDRESS(VeluxBindingConstants.THING_TYPE_BRIDGE,                     VeluxBindingConstants.PROPERTY_BRIDGE_ADDRESS,       TypeFlavor.PROPERTY),
88     BRIDGE_SUBNETMASK(VeluxBindingConstants.THING_TYPE_BRIDGE,                  VeluxBindingConstants.PROPERTY_BRIDGE_SUBNETMASK,    TypeFlavor.PROPERTY),
89     BRIDGE_DEFAULTGW(VeluxBindingConstants.THING_TYPE_BRIDGE,                   VeluxBindingConstants.PROPERTY_BRIDGE_DEFAULTGW,     TypeFlavor.PROPERTY),
90     BRIDGE_DHCP(VeluxBindingConstants.THING_TYPE_BRIDGE,                        VeluxBindingConstants.PROPERTY_BRIDGE_DHCP,          TypeFlavor.PROPERTY),
91     BRIDGE_WLANSSID(VeluxBindingConstants.THING_TYPE_BRIDGE,                    VeluxBindingConstants.PROPERTY_BRIDGE_WLANSSID,      TypeFlavor.PROPERTY),
92     BRIDGE_WLANPASSWORD(VeluxBindingConstants.THING_TYPE_BRIDGE,                VeluxBindingConstants.PROPERTY_BRIDGE_WLANPASSWORD,  TypeFlavor.PROPERTY),
93     BRIDGE_PRODUCTS(VeluxBindingConstants.THING_TYPE_BRIDGE,                    VeluxBindingConstants.PROPERTY_BRIDGE_PRODUCTS,      TypeFlavor.PROPERTY),
94     BRIDGE_SCENES(VeluxBindingConstants.THING_TYPE_BRIDGE,                      VeluxBindingConstants.PROPERTY_BRIDGE_SCENES,        TypeFlavor.PROPERTY),
95     BRIDGE_CHECK(VeluxBindingConstants.THING_TYPE_BRIDGE,                       VeluxBindingConstants.PROPERTY_BRIDGE_CHECK,         TypeFlavor.PROPERTY),
96     //
97     ACTUATOR_POSITION(VeluxBindingConstants.THING_TYPE_VELUX_ACTUATOR,          VeluxBindingConstants.CHANNEL_ACTUATOR_POSITION,     TypeFlavor.MANIPULATOR_SHUTTER),
98     ACTUATOR_STATE(VeluxBindingConstants.THING_TYPE_VELUX_ACTUATOR,             VeluxBindingConstants.CHANNEL_ACTUATOR_STATE,        TypeFlavor.MANIPULATOR_SWITCH),
99     ACTUATOR_LIMIT_MINIMUM(VeluxBindingConstants.THING_TYPE_VELUX_ACTUATOR,     VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MINIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
100     ACTUATOR_LIMIT_MAXIMUM(VeluxBindingConstants.THING_TYPE_VELUX_ACTUATOR,     VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MAXIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
101     //
102     ROLLERSHUTTER_POSITION(VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER,VeluxBindingConstants.CHANNEL_ACTUATOR_POSITION,     TypeFlavor.MANIPULATOR_SHUTTER),
103     ROLLERSHUTTER_LIMIT_MINIMUM(VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER,VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MINIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
104     ROLLERSHUTTER_LIMIT_MAXIMUM(VeluxBindingConstants.THING_TYPE_VELUX_ROLLERSHUTTER,VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MAXIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
105     //
106     WINDOW_POSITION(VeluxBindingConstants.THING_TYPE_VELUX_WINDOW,              VeluxBindingConstants.CHANNEL_ACTUATOR_POSITION,     TypeFlavor.MANIPULATOR_SHUTTER),
107     WINDOW_LIMIT_MINIMUM(VeluxBindingConstants.THING_TYPE_VELUX_WINDOW,         VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MINIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
108     WINDOW_LIMIT_MAXIMUM(VeluxBindingConstants.THING_TYPE_VELUX_WINDOW,         VeluxBindingConstants.CHANNEL_ACTUATOR_LIMIT_MAXIMUM,TypeFlavor.MANIPULATOR_SHUTTER),
109     //
110     SCENE_ACTION(VeluxBindingConstants.THING_TYPE_VELUX_SCENE,                  VeluxBindingConstants.CHANNEL_SCENE_ACTION,          TypeFlavor.INITIATOR),
111     SCENE_SILENTMODE(VeluxBindingConstants.THING_TYPE_VELUX_SCENE,              VeluxBindingConstants.CHANNEL_SCENE_SILENTMODE,      TypeFlavor.WRITEONLY_VOLATILE_SWITCH),
112     //
113     VSHUTTER_POSITION(VeluxBindingConstants.THING_TYPE_VELUX_VSHUTTER,          VeluxBindingConstants.CHANNEL_VSHUTTER_POSITION,     TypeFlavor.MANIPULATOR_SHUTTER),
114     ;
115     // @formatter:on
116
117     private enum TypeFlavor {
118         /**
119          * Used to present read-only non-volatile configuration parameters as StringItem.
120          */
121         READONLY_STATIC_STRING,
122         /**
123          * Used to present read-only non-volatile configuration parameters as SwitchItem.
124          */
125         READONLY_STATIC_SWITCH,
126         /**
127          * Used to present volatile configuration parameters as StringItem.
128          */
129         READONLY_VOLATILE_STRING,
130         /**
131          * Used to present volatile configuration parameters as NumberItem.
132          */
133         READONLY_VOLATILE_NUMBER,
134         /**
135          * Used to present volatile configuration parameters as NumberItem.
136          */
137         WRITEONLY_VOLATILE_SWITCH,
138         /**
139          * Used to present volatile configuration parameters as SwitchItem.
140          */
141         READWRITE_VOLATILE_SWITCH,
142         /**
143          * Used to initiate an action.
144          */
145         INITIATOR,
146         /**
147          * Used to manipulate an actuator.
148          */
149         MANIPULATOR_SHUTTER,
150         /**
151          * Used to manipulate an actuator.
152          */
153         MANIPULATOR_SWITCH,
154         /**
155          * Used to present read-only non-volatile configuration parameter (being handled as property of aThing).
156          */
157         PROPERTY,
158         /**
159          * Used to define an UNUSABLE entry.
160          */
161         UNUSABLE,
162     }
163
164     /*
165      * ***************************
166      * ***** Private Objects *****
167      */
168
169     private ThingTypeUID thingIdentifier;
170     private String channelIdentifier;
171     private Class<? extends GenericItem> itemClass;
172     private boolean itemIsReadable;
173     private boolean itemIsWritable;
174     private boolean itemIsExecutable;
175     private boolean itemIsToBeRefreshed;
176     private int itemsRefreshDivider;
177     private boolean itemIsChannel;
178     private boolean itemIsProperty;
179
180     private static final Logger LOGGER = LoggerFactory.getLogger(VeluxItemType.class);
181
182     private static final int REFRESH_CYCLE_FIRST_TIME = 0;
183     private static final int REFRESH_ONCE_A_DAY = 8640;
184     private static final int REFRESH_EACH_HOUR = 360;
185     private static final int REFRESH_EACH_MINUTE = 6;
186     private static final int REFRESH_EVERY_CYCLE = 1;
187
188     /*
189      * ************************
190      * ***** Constructors *****
191      */
192
193     VeluxItemType(ThingTypeUID thingIdentifier, String channelIdentifier, TypeFlavor typeFlavor) {
194         this.thingIdentifier = thingIdentifier;
195         this.channelIdentifier = channelIdentifier;
196         this.itemIsChannel = true;
197         this.itemIsProperty = false;
198         switch (typeFlavor) {
199             case READONLY_STATIC_STRING:
200                 this.itemClass = StringItem.class;
201                 this.itemIsReadable = true;
202                 this.itemIsWritable = false;
203                 this.itemIsExecutable = false;
204                 this.itemIsToBeRefreshed = true;
205                 this.itemsRefreshDivider = REFRESH_ONCE_A_DAY;
206                 break;
207             case READONLY_STATIC_SWITCH:
208                 this.itemClass = SwitchItem.class;
209                 this.itemIsReadable = true;
210                 this.itemIsWritable = false;
211                 this.itemIsExecutable = false;
212                 this.itemIsToBeRefreshed = true;
213                 this.itemsRefreshDivider = REFRESH_ONCE_A_DAY;
214                 break;
215
216             case READONLY_VOLATILE_STRING:
217                 this.itemClass = StringItem.class;
218                 this.itemIsReadable = true;
219                 this.itemIsWritable = false;
220                 this.itemIsExecutable = false;
221                 this.itemIsToBeRefreshed = true;
222                 this.itemsRefreshDivider = REFRESH_EACH_MINUTE;
223                 break;
224             case READONLY_VOLATILE_NUMBER:
225                 this.itemClass = NumberItem.class;
226                 this.itemIsReadable = true;
227                 this.itemIsWritable = false;
228                 this.itemIsExecutable = false;
229                 this.itemIsToBeRefreshed = true;
230                 this.itemsRefreshDivider = REFRESH_EVERY_CYCLE;
231                 break;
232             case WRITEONLY_VOLATILE_SWITCH:
233                 this.itemClass = SwitchItem.class;
234                 this.itemIsReadable = false;
235                 this.itemIsWritable = true;
236                 this.itemIsExecutable = false;
237                 this.itemIsToBeRefreshed = false;
238                 this.itemsRefreshDivider = REFRESH_EACH_MINUTE;
239                 break;
240             case READWRITE_VOLATILE_SWITCH:
241                 this.itemClass = SwitchItem.class;
242                 this.itemIsReadable = true;
243                 this.itemIsWritable = true;
244                 this.itemIsExecutable = false;
245                 this.itemIsToBeRefreshed = true;
246                 this.itemsRefreshDivider = REFRESH_EVERY_CYCLE;
247                 break;
248
249             case INITIATOR:
250                 this.itemClass = SwitchItem.class;
251                 this.itemIsReadable = false;
252                 this.itemIsWritable = false;
253                 this.itemIsExecutable = true;
254                 this.itemIsToBeRefreshed = false;
255                 this.itemsRefreshDivider = 1;
256                 break;
257
258             case MANIPULATOR_SHUTTER:
259                 this.itemClass = RollershutterItem.class;
260                 this.itemIsReadable = true;
261                 this.itemIsWritable = true;
262                 this.itemIsExecutable = false;
263                 this.itemIsToBeRefreshed = true;
264                 this.itemsRefreshDivider = REFRESH_EACH_MINUTE;
265                 break;
266
267             case MANIPULATOR_SWITCH:
268                 this.itemClass = SwitchItem.class;
269                 this.itemIsReadable = true;
270                 this.itemIsWritable = true;
271                 this.itemIsExecutable = false;
272                 this.itemIsToBeRefreshed = true;
273                 this.itemsRefreshDivider = REFRESH_EACH_MINUTE;
274                 break;
275
276             case PROPERTY:
277                 this.itemClass = StringItem.class;
278                 this.itemIsReadable = true;
279                 this.itemIsWritable = false;
280                 this.itemIsExecutable = false;
281                 this.itemIsToBeRefreshed = true;
282                 this.itemsRefreshDivider = REFRESH_EACH_HOUR;
283                 this.itemIsChannel = false;
284                 this.itemIsProperty = true;
285                 break;
286
287             case UNUSABLE:
288             default:
289                 this.itemClass = StringItem.class;
290                 this.itemIsReadable = false;
291                 this.itemIsWritable = false;
292                 this.itemIsExecutable = false;
293                 this.itemIsToBeRefreshed = false;
294                 this.itemsRefreshDivider = REFRESH_ONCE_A_DAY;
295                 this.itemIsChannel = false;
296         }
297     }
298
299     /*
300      * ********************************
301      * ***** Class access methods *****
302      */
303
304     @Override
305     public String toString() {
306         return this.thingIdentifier + "/" + this.channelIdentifier;
307     }
308
309     /**
310      * {@link VeluxItemType} access method to query Identifier on this type of item.
311      *
312      * @return <b>thingIdentifier</b> of type String describing the value of the enum {@link VeluxItemType}
313      *         return
314      */
315     public ThingTypeUID getThingTypeUID() {
316         return this.thingIdentifier;
317     }
318
319     /**
320      * {@link VeluxItemType} access method to query common (channel/property) identifier on this type of item.
321      *
322      * @return <b>channelIdentifier</b> of type String describing the value of the enum {@link VeluxItemType}.
323      */
324     public String getIdentifier() {
325         return this.channelIdentifier;
326     }
327
328     /**
329      * {@link VeluxItemType} access method to query the appropriate type of item.
330      *
331      * @return <b>itemClass</b> of type Item describing the possible type of this item.
332      */
333     public Class<? extends GenericItem> getItemClass() {
334         return this.itemClass;
335     }
336
337     /**
338      * {@link VeluxItemType} access method to query Read possibility on this type of item.
339      *
340      * @return <b>itemIsReadable</b> of type boolean describing the ability to perform a write operation.
341      */
342     public boolean isReadable() {
343         return this.itemIsReadable;
344     }
345
346     /**
347      * {@link VeluxItemType} access method to query Write possibility on this type of item.
348      *
349      * @return <b>itemIsWritable</b> of type boolean describing the ability to perform a write operation.
350      */
351     public boolean isWritable() {
352         return this.itemIsWritable;
353     }
354
355     /**
356      * {@link VeluxItemType} access method to query Execute possibility on this type of item.
357      *
358      * @return <b>isExecute</b> of type boolean describing the ability to perform a write operation.
359      */
360     public boolean isExecutable() {
361         return this.itemIsExecutable;
362     }
363
364     /**
365      * {@link VeluxItemType} access method to query the need of refresh on this type of item.
366      *
367      * @return <b>isExecute</b> of type boolean describing the ability to perform a write operation.
368      */
369     public boolean isToBeRefreshed() {
370         return this.itemIsToBeRefreshed;
371     }
372
373     /**
374      * {@link VeluxItemType} access method to query the refreshMSecs interval on this type of item.
375      *
376      * @return <b>refreshDivider</b> of type int describing the factor.
377      */
378     public int getRefreshDivider() {
379         return this.itemsRefreshDivider;
380     }
381
382     /**
383      * {@link VeluxItemType} access method to query the type of this item.
384      *
385      * @return <b>isChannel</b> of type boolean describing the need to be handled as channel.
386      */
387     public boolean isChannel() {
388         return this.itemIsChannel;
389     }
390
391     /**
392      * {@link VeluxItemType} access method to query the type of this item.
393      *
394      * @return <b>itemIsProperty</b> of type boolean describing the need to be handled as property.
395      */
396     public boolean isProperty() {
397         return this.itemIsProperty;
398     }
399
400     /**
401      * {@link VeluxItemType} access method to find an enum by itemTypeName.
402      *
403      * @param itemTypeName as name of requested Thing of type String.
404      *
405      * @return <b>veluxItemType</b> of type VeluxItemType describing the appropriate enum.
406      */
407     public VeluxItemType getByString(String itemTypeName) {
408         try {
409             return VeluxItemType.valueOf(itemTypeName);
410         } catch (IllegalArgumentException e) {
411             return UNKNOWN;
412         }
413     }
414
415     /**
416      * {@link VeluxItemType} access method to find an enum by name.
417      *
418      * @param thingIdentifier as name of requested Thing of type String.
419      * @param channelIdentifier as name of requested Channel of type String.
420      *
421      * @return <b>veluxItemType</b> of type VeluxItemType describing the appropriate enum.
422      */
423     public static VeluxItemType getByThingAndChannel(ThingTypeUID thingIdentifier, String channelIdentifier) {
424         for (VeluxItemType v : VeluxItemType.values()) {
425             if (thingIdentifier.equals(v.thingIdentifier) && channelIdentifier.equals(v.channelIdentifier)) {
426                 LOGGER.trace("getByThingAndChannel({},{}) returns enum {}.", thingIdentifier, channelIdentifier, v);
427                 return v;
428             }
429         }
430         LOGGER.trace("getByThingAndChannel({},{}) returns enum UNKNOWN.", thingIdentifier, channelIdentifier);
431         return UNKNOWN;
432     }
433
434     /**
435      * {@link VeluxItemType} access method to find similar enum entries by thingIdentifier.
436      *
437      * @param thingIdentifier as name of requested Thing of type String.
438      *
439      * @return <b>listOfveluxItemType</b> of type List of VeluxItemType containing all similar enum entries.
440      */
441     public static List<VeluxItemType> getPropertyEntriesByThing(ThingTypeUID thingIdentifier) {
442         List<VeluxItemType> list = new ArrayList<>();
443         for (VeluxItemType v : VeluxItemType.values()) {
444             if (thingIdentifier.equals(v.thingIdentifier) && v.itemIsProperty) {
445                 list.add(v);
446             }
447         }
448         LOGGER.trace("getPropertyEntriesByThing({}) returns {}.", thingIdentifier, list);
449         return list;
450     }
451
452     /**
453      * Helper function: Calculate modulo.
454      *
455      * @param a as dividend.
456      * @param b as divisor.
457      *
458      * @return <b>true</b> if zero is remainder after division.
459      */
460     private static boolean isModulo(int a, int b) {
461         return (a % b) == 0;
462     }
463
464     /**
465      * {@link VeluxItemType} access method to determine the necessity of being refreshed
466      * within the current refresh cycle.
467      *
468      * @param refreshCycleCounter as identification of the refresh round.
469      * @param thingIdentifier as name of requested Thing.
470      * @param channelIdentifier as name of requested Channel.
471      *
472      * @return <b>boolean</b> value which expresses the need.
473      */
474     public static boolean isToBeRefreshedNow(int refreshCycleCounter, ThingTypeUID thingIdentifier,
475             String channelIdentifier) {
476         VeluxItemType itemType = getByThingAndChannel(thingIdentifier, channelIdentifier);
477
478         if (itemType == VeluxItemType.UNKNOWN) {
479             LOGGER.warn("isToBeRefreshedNow({},{},{}): returning false, as item is not found.", refreshCycleCounter,
480                     thingIdentifier, channelIdentifier);
481             return false;
482         }
483
484         if (((refreshCycleCounter == REFRESH_CYCLE_FIRST_TIME) && (itemType.isReadable()))
485                 || (itemType.isToBeRefreshed())) {
486             if ((refreshCycleCounter == REFRESH_CYCLE_FIRST_TIME)
487                     || (isModulo(refreshCycleCounter, itemType.getRefreshDivider()))) {
488                 LOGGER.trace("isToBeRefreshedNow(): returning true, as item is to be refreshed, now.");
489                 return true;
490             } else {
491                 LOGGER.trace("isToBeRefreshedNow(): returning false, as refresh cycle has not yet come for this item.");
492             }
493         } else {
494             LOGGER.trace("isToBeRefreshedNow(): returning false, as item is not refreshable.");
495         }
496         return false;
497     }
498 }