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 org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.openhab.binding.velux.internal.bridge.common.GetProduct;
17 import org.openhab.binding.velux.internal.bridge.common.GetProducts;
18 import org.openhab.binding.velux.internal.things.VeluxExistingProducts;
19 import org.openhab.binding.velux.internal.things.VeluxKLFAPI;
20 import org.openhab.binding.velux.internal.things.VeluxProduct;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * The {@link VeluxBridgeActuators} represents a complete set of transactions
26 * for retrieving of any available products into a structure {@link #channel}
27 * defined on the <B>Velux</B> bridge.
29 * It provides the methods:
31 * <LI>{@link #getProducts} for retrieval of information from the bridge.
32 * <LI>{@link #getChannel} for accessing the retrieved information.
33 * <LI>{@link #autoRefresh} for retrieval of information for supporting the update the corresponding openHAB items.
37 * @see VeluxExistingProducts
38 * @see VeluxBridgeProvider
40 * @author Guenther Schreiner - Initial contribution
43 public class VeluxBridgeActuators {
44 private final Logger logger = LoggerFactory.getLogger(VeluxBridgeActuators.class);
46 // Configuration constants
49 * Limitation of Discovery on parts of the System table
51 * Whereas the parameter {@link org.openhab.binding.velux.internal.things.VeluxKLFAPI#KLF_SYSTEMTABLE_MAX}
53 * maximum size of the system table in general, for speed up of the discovery process
54 * a binding-internal limitation of number of possible devices is introduced.
56 private static final int VELUXBINDING_SYSTEMTABLE_MAX = 16;
58 // Type definitions, class-internal variables
61 * Actuator information consisting of:
63 * <li>isRetrieved (boolean),
64 * <li>existingProducts ({@link VeluxExistingProducts}).
68 public class Channel {
69 public VeluxExistingProducts existingProducts = new VeluxExistingProducts();
72 private Channel channel;
74 // Constructor methods
79 * Initializes the internal data structure {@link #channel} of Velux actuators/products,
80 * which is publicly accessible via the method {@link #getChannel()}.
82 public VeluxBridgeActuators() {
83 logger.trace("VeluxBridgeActuators(constructor) called.");
84 channel = new Channel();
85 logger.trace("VeluxBridgeActuators(constructor) done.");
88 // Class access methods
91 * Provide access to the internal structure of actuators/products.
93 * @return a channel describing the overall actuator situation.
95 public Channel getChannel() {
100 * Login into bridge, retrieve all products and logout from bridge based
101 * on a well-prepared environment of a {@link VeluxBridgeProvider}. The results
102 * are stored within {@link org.openhab.binding.velux.internal.things.VeluxExistingProducts
103 * VeluxExistingProducts}.
105 * @param bridge Initialized Velux bridge (communication) handler.
106 * @return true if successful, and false otherwise.
108 public boolean getProducts(VeluxBridge bridge) {
109 logger.trace("getProducts() called.");
111 GetProducts bcp = bridge.bridgeAPI().getProducts();
112 GetProduct bcpSbS = bridge.bridgeAPI().getProduct();
113 if ((bcpSbS != null) && !bridge.bridgeInstance.veluxBridgeConfiguration().isBulkRetrievalEnabled) {
114 logger.trace("getProducts() working on step-by-step retrieval.");
115 for (int nodeId = 0; nodeId < VeluxKLFAPI.KLF_SYSTEMTABLE_MAX
116 && nodeId < VELUXBINDING_SYSTEMTABLE_MAX; nodeId++) {
117 logger.trace("getProducts() working on product number {}.", nodeId);
118 bcpSbS.setProductId(nodeId);
119 if (bridge.bridgeCommunicate(bcpSbS) && bcpSbS.isCommunicationSuccessful()) {
120 VeluxProduct veluxProduct = bcpSbS.getProduct();
121 if (bcpSbS.isCommunicationSuccessful()) {
122 logger.debug("getProducts() found product {}.", veluxProduct);
123 if (!channel.existingProducts.isRegistered(veluxProduct)) {
124 channel.existingProducts.register(veluxProduct);
130 logger.trace("getProducts() working on bulk retrieval.");
131 if (bridge.bridgeCommunicate(bcp) && bcp.isCommunicationSuccessful()) {
132 for (VeluxProduct product : bcp.getProducts()) {
133 logger.trace("getProducts() found product {} (type {}).", product.getProductName(),
134 product.getProductType());
135 if (!channel.existingProducts.isRegistered(product)) {
136 logger.debug("getProducts() storing new product {}.", product);
137 channel.existingProducts.register(product);
139 logger.debug("getProducts() storing updates for product {}.", product);
140 channel.existingProducts.update(product);
144 logger.trace("getProducts() finished with failure.");
148 logger.debug("getProducts() finally has found products {}.", channel.existingProducts);
153 * In case of an empty list of recognized products, the method will
154 * initiate a product retrieval using {@link #getProducts(VeluxBridge)}.
156 * @param bridge Initialized Velux bridge (communication) handler.
157 * @return true if at least one product was found, and false otherwise.
159 public boolean autoRefresh(VeluxBridge bridge) {
160 int numberOfActuators = channel.existingProducts.getNoMembers();
161 if (numberOfActuators == 0) {
162 logger.trace("autoRefresh(): is about to fetch existing products.");
165 return (numberOfActuators > 0);