]> git.basschouten.com Git - openhab-addons.git/blob
4aef0887da169f0461c67ef13563de64bb4eb635
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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.bridge;
14
15 import java.util.Collections;
16 import java.util.Set;
17
18 import org.eclipse.jdt.annotation.NonNullByDefault;
19 import org.openhab.binding.velux.internal.bridge.common.BridgeAPI;
20 import org.openhab.binding.velux.internal.bridge.common.BridgeCommunicationProtocol;
21 import org.openhab.binding.velux.internal.bridge.common.Login;
22 import org.openhab.binding.velux.internal.bridge.common.Logout;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * 2nd Level I/O interface towards the <B>Velux</B> bridge.
28  * It provides methods for pre- and post-communication
29  * as well as a common method for the real communication.
30  * The following class access methods exist:
31  * <UL>
32  * <LI>{@link VeluxBridge#bridgeLogin} for pre-communication,</LI>
33  * <LI>{@link VeluxBridge#bridgeLogout} for post-communication,</LI>
34  * <LI>{@link VeluxBridge#bridgeCommunicate} as method for the common communication.</LI>
35  * </UL>
36  * <P>
37  * Each protocol-specific implementation provides a publicly visible
38  * set of supported protocols as variable {@link #supportedProtocols}.
39  * As root of several inheritance levels it predefines an
40  * interfacing method {@link VeluxBridge#bridgeAPI} which
41  * has to be implemented by any kind of protocol-specific
42  * communication returning the appropriate base (1st) level
43  * communication method as well as any other gateway
44  * interaction with {@link #bridgeDirectCommunicate}.
45  *
46  * @author Guenther Schreiner - Initial contribution.
47  */
48 @NonNullByDefault
49 public abstract class VeluxBridge {
50     private final Logger logger = LoggerFactory.getLogger(VeluxBridge.class);
51
52     /*
53      * ***************************
54      * ***** Private Objects *****
55      */
56
57     private final String emptyAuthenticationToken = "";
58
59     // Type definitions, variables
60
61     /**
62      * Support protocols for the concrete implementation.
63      * <P>
64      * For protocol-specific implementations this value has to be adapted along the inheritance i.e.
65      * with the protocol-specific class values.
66      */
67     public Set<String> supportedProtocols = Collections.emptySet();
68
69     /** BridgeCommunicationProtocol authentication token for Velux Bridge. */
70     protected String authenticationToken = emptyAuthenticationToken;
71
72     /**
73      * Handler to access global bridge instance methods
74      *
75      */
76     protected VeluxBridgeInstance bridgeInstance;
77
78     /*
79      * ************************
80      * ***** Constructors *****
81      */
82
83     /**
84      * Constructor.
85      * <P>
86      * Initializes the binding-wide instance for dealing with common informations and
87      * the Velux bridge connectivity settings by preparing the configuration settings with help
88      * by VeluxBridgeConfiguration.
89      *
90      * @param bridgeInstance refers to the binding-wide instance for dealing for common informations
91      *            like existing actuators and predefined scenes.
92      */
93     public VeluxBridge(VeluxBridgeInstance bridgeInstance) {
94         logger.trace("VeluxBridge(constructor,bridgeInstance={}) called.", bridgeInstance);
95         this.bridgeInstance = bridgeInstance;
96         logger.trace("VeluxBridge(constructor) done.");
97     }
98
99     // Destructor methods
100
101     /**
102      * Destructor.
103      * <P>
104      * Deinitializes the binding-wide instance.
105      *
106      */
107     public void shutdown() {
108         logger.trace("shutdown() called.");
109     }
110
111     // Class access methods
112
113     /**
114      * Determines whether the binding is already authenticated against the bridge so that
115      * any other communication can occur without an additional care about authentication.
116      * <P>
117      * This method automatically decides on availability of the stored authentication
118      * information {@link VeluxBridge#authenticationToken} whether a (re-)authentication is possible.
119      *
120      * @return true if the bridge is authenticated; false otherwise.
121      */
122     private boolean isAuthenticated() {
123         boolean success = (authenticationToken.length() > 0);
124         logger.trace("isAuthenticated() returns {}.", success);
125         return success;
126     }
127
128     /**
129      * Declares the binding as unauthenticated against the bridge so that the next
130      * communication will take care about (re-)authentication.
131      */
132     protected void resetAuthentication() {
133         logger.trace("resetAuthentication() called.");
134         authenticationToken = emptyAuthenticationToken;
135         return;
136     }
137
138     /**
139      * Prepare an authorization request and communicate it with the <b>Velux</b> veluxBridge.
140      * If login is successful, the returned authorization token will be stored within this class
141      * for any further communication via {@link#bridgeCommunicate} up
142      * to an authorization with method {@link VeluxBridge#bridgeLogout}.
143      *
144      * @return true if the login was successful, and false otherwise.
145      */
146     public synchronized boolean bridgeLogin() {
147         logger.trace("bridgeLogin() called.");
148
149         Login bcp = bridgeAPI().login();
150         bcp.setPassword(bridgeInstance.veluxBridgeConfiguration().password);
151         if (bridgeCommunicate(bcp, false)) {
152             logger.trace("bridgeLogin(): communication succeeded.");
153             if (bcp.isCommunicationSuccessful()) {
154                 logger.trace("bridgeLogin(): storing authentication token for further access.");
155                 authenticationToken = bcp.getAuthToken();
156                 return true;
157             }
158         }
159         return false;
160     }
161
162     /**
163      * Prepare an authenticated deauthorization request and communicate it with the <b>Velux</b> veluxBridge.
164      * The authorization token stored in this class will be destroyed, so that the
165      * next communication has to start with {@link VeluxBridge#bridgeLogin}.
166      *
167      * @return true if the logout was successful, and false otherwise.
168      */
169     public synchronized boolean bridgeLogout() {
170         logger.trace("bridgeLogout() called: emptying authentication token.");
171         authenticationToken = "";
172
173         Logout bcp = bridgeAPI().logout();
174         if (bridgeCommunicate(bcp, false)) {
175             logger.trace("bridgeLogout(): communication succeeded.");
176             if (bcp.isCommunicationSuccessful()) {
177                 logger.trace("bridgeLogout(): logout successful.");
178                 return true;
179             }
180         }
181         return false;
182     }
183
184     /**
185      * Initializes a client/server communication towards <b>Velux</b> veluxBridge
186      * based on the Basic I/O interface {@link VeluxBridge} and parameters
187      * passed as arguments (see below) and provided by VeluxBridgeConfiguration.
188      *
189      * @param communication the intended communication,
190      *            that is request and response interactions as well as appropriate URL definition.
191      * @param useAuthentication whether to use authenticated communication.
192      * @return true if communication was successful, and false otherwise.
193      */
194     private synchronized boolean bridgeCommunicate(BridgeCommunicationProtocol communication,
195             boolean useAuthentication) {
196         logger.trace("bridgeCommunicate({},{}authenticated) called.", communication.name(),
197                 useAuthentication ? "" : "un");
198
199         if (!isAuthenticated()) {
200             if (useAuthentication) {
201                 logger.trace("bridgeCommunicate(): no auth token available, aborting.");
202                 return false;
203             } else {
204                 logger.trace("bridgeCommunicate(): no auth token available, continuing.");
205             }
206         }
207         return bridgeDirectCommunicate(communication, useAuthentication);
208     }
209
210     /**
211      * Initializes a client/server communication towards <b>Velux</b> Bridge
212      * based on the Basic I/O interface {@link VeluxBridge} and parameters
213      * passed as arguments (see below) and provided by VeluxBridgeConfiguration.
214      * This method automatically decides to invoke a login communication before the
215      * intended request if there has not been an authentication before.
216      *
217      * @param communication the intended communication, that is request and response interactions as well as appropriate
218      *            URL definition.
219      * @return true if communication was successful, and false otherwise.
220      */
221     public synchronized boolean bridgeCommunicate(BridgeCommunicationProtocol communication) {
222         logger.trace("bridgeCommunicate({}) called.", communication.name());
223         if (!isAuthenticated()) {
224             bridgeLogin();
225         }
226         return bridgeCommunicate(communication, true);
227     }
228
229     /**
230      * Returns the timestamp in milliseconds since Unix epoch
231      * of last communication.
232      * <P>
233      * If possible, it should be overwritten by protocol specific implementation.
234      * </P>
235      *
236      * @return timestamp (default zero).
237      */
238     public long lastCommunication() {
239         logger.trace("lastCommunication() returns zero.");
240         return 0L;
241     }
242
243     /**
244      * Returns the timestamp in milliseconds since Unix epoch
245      * of last successful communication.
246      * <P>
247      * If possible, it should be overwritten by protocol specific implementation.
248      * </P>
249      *
250      * @return timestamp (default zero).
251      */
252     public long lastSuccessfulCommunication() {
253         logger.trace("lastSuccessfulCommunication() returns zero.");
254         return 0L;
255     }
256
257     /**
258      * Provides information about the base-level communication method and
259      * any kind of available gateway interaction.
260      * <P>
261      * For protocol-specific implementations this method has to be overwritten along the inheritance i.e.
262      * with the protocol-specific class implementations.
263      *
264      * @return bridgeAPI of type {@link org.openhab.binding.velux.internal.bridge.common.BridgeAPI BridgeAPI}.
265      */
266     public abstract BridgeAPI bridgeAPI();
267
268     /**
269      * Initializes a client/server communication towards <b>Velux</b> veluxBridge
270      * based on the protocol-specific implementations with common parameters
271      * passed as arguments (see below) and provided by VeluxBridgeConfiguration.
272      * <P>
273      * For protocol-specific implementations this method has to be overwritten along the inheritance i.e.
274      * with the protocol-specific class implementations.
275      *
276      * @param communication Structure of interface type {@link BridgeCommunicationProtocol} describing the
277      *            intended communication.
278      * @param useAuthentication boolean flag to decide whether to use authenticated communication.
279      * @return <b>success</b> of type boolean which signals the success of the communication.
280      */
281     protected abstract boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication,
282             boolean useAuthentication);
283 }