2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.velux.internal.bridge;
15 import java.util.Collections;
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;
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:
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>
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}.
46 * @author Guenther Schreiner - Initial contribution.
49 public abstract class VeluxBridge {
50 private final Logger logger = LoggerFactory.getLogger(VeluxBridge.class);
53 * ***************************
54 * ***** Private Objects *****
57 private final String emptyAuthenticationToken = "";
59 // Type definitions, variables
62 * Support protocols for the concrete implementation.
64 * For protocol-specific implementations this value has to be adapted along the inheritance i.e.
65 * with the protocol-specific class values.
67 public Set<String> supportedProtocols = Collections.emptySet();
69 /** BridgeCommunicationProtocol authentication token for Velux Bridge. */
70 protected String authenticationToken = emptyAuthenticationToken;
73 * Handler to access global bridge instance methods
76 protected VeluxBridgeInstance bridgeInstance;
79 * ************************
80 * ***** Constructors *****
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.
90 * @param bridgeInstance refers to the binding-wide instance for dealing for common informations
91 * like existing actuators and predefined scenes.
93 public VeluxBridge(VeluxBridgeInstance bridgeInstance) {
94 logger.trace("VeluxBridge(constructor,bridgeInstance={}) called.", bridgeInstance);
95 this.bridgeInstance = bridgeInstance;
96 logger.trace("VeluxBridge(constructor) done.");
104 * Deinitializes the binding-wide instance.
107 public void shutdown() {
108 logger.trace("shutdown() called.");
111 // Class access methods
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.
117 * This method automatically decides on availability of the stored authentication
118 * information {@link VeluxBridge#authenticationToken} whether a (re-)authentication is possible.
120 * @return true if the bridge is authenticated; false otherwise.
122 private boolean isAuthenticated() {
123 boolean success = (authenticationToken.length() > 0);
124 logger.trace("isAuthenticated() returns {}.", success);
129 * Declares the binding as unauthenticated against the bridge so that the next
130 * communication will take care about (re-)authentication.
132 protected void resetAuthentication() {
133 logger.trace("resetAuthentication() called.");
134 authenticationToken = emptyAuthenticationToken;
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}.
144 * @return true if the login was successful, and false otherwise.
146 public synchronized boolean bridgeLogin() {
147 logger.trace("bridgeLogin() called.");
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();
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}.
167 * @return true if the logout was successful, and false otherwise.
169 public synchronized boolean bridgeLogout() {
170 logger.trace("bridgeLogout() called: emptying authentication token.");
171 authenticationToken = "";
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.");
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.
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.
194 private synchronized boolean bridgeCommunicate(BridgeCommunicationProtocol communication,
195 boolean useAuthentication) {
196 logger.trace("bridgeCommunicate({},{}authenticated) called.", communication.name(),
197 useAuthentication ? "" : "un");
199 if (!isAuthenticated()) {
200 if (useAuthentication) {
201 logger.trace("bridgeCommunicate(): no auth token available, aborting.");
204 logger.trace("bridgeCommunicate(): no auth token available, continuing.");
207 return bridgeDirectCommunicate(communication, useAuthentication);
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.
217 * @param communication the intended communication, that is request and response interactions as well as appropriate
219 * @return true if communication was successful, and false otherwise.
221 public synchronized boolean bridgeCommunicate(BridgeCommunicationProtocol communication) {
222 logger.trace("bridgeCommunicate({}) called.", communication.name());
223 if (!isAuthenticated()) {
226 return bridgeCommunicate(communication, true);
230 * Returns the timestamp in milliseconds since Unix epoch
231 * of last communication.
233 * If possible, it should be overwritten by protocol specific implementation.
236 * @return timestamp (default zero).
238 public long lastCommunication() {
239 logger.trace("lastCommunication() returns zero.");
244 * Returns the timestamp in milliseconds since Unix epoch
245 * of last successful communication.
247 * If possible, it should be overwritten by protocol specific implementation.
250 * @return timestamp (default zero).
252 public long lastSuccessfulCommunication() {
253 logger.trace("lastSuccessfulCommunication() returns zero.");
258 * Provides information about the base-level communication method and
259 * any kind of available gateway interaction.
261 * For protocol-specific implementations this method has to be overwritten along the inheritance i.e.
262 * with the protocol-specific class implementations.
264 * @return bridgeAPI of type {@link org.openhab.binding.velux.internal.bridge.common.BridgeAPI BridgeAPI}.
266 public abstract BridgeAPI bridgeAPI();
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.
273 * For protocol-specific implementations this method has to be overwritten along the inheritance i.e.
274 * with the protocol-specific class implementations.
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.
281 protected abstract boolean bridgeDirectCommunicate(BridgeCommunicationProtocol communication,
282 boolean useAuthentication);