2 * Copyright (c) 2010-2023 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}).
67 public class Channel {
68 public VeluxExistingProducts existingProducts = new VeluxExistingProducts();
71 private Channel channel;
73 // Constructor methods
78 * Initializes the internal data structure {@link #channel} of Velux actuators/products,
79 * which is publicly accessible via the method {@link #getChannel()}.
81 public VeluxBridgeActuators() {
82 logger.trace("VeluxBridgeActuators(constructor) called.");
83 channel = new Channel();
84 logger.trace("VeluxBridgeActuators(constructor) done.");
87 // Class access methods
90 * Provide access to the internal structure of actuators/products.
92 * @return a channel describing the overall actuator situation.
94 public Channel getChannel() {
99 * Login into bridge, retrieve all products and logout from bridge based
100 * on a well-prepared environment of a {@link VeluxBridgeProvider}. The results
101 * are stored within {@link org.openhab.binding.velux.internal.things.VeluxExistingProducts
102 * VeluxExistingProducts}.
104 * @param bridge Initialized Velux bridge (communication) handler.
105 * @return true if successful, and false otherwise.
107 public boolean getProducts(VeluxBridge bridge) {
108 logger.trace("getProducts() called.");
110 GetProducts bcp = bridge.bridgeAPI().getProducts();
111 GetProduct bcpSbS = bridge.bridgeAPI().getProduct();
112 if ((bcpSbS != null) && !bridge.bridgeInstance.veluxBridgeConfiguration().isBulkRetrievalEnabled) {
113 logger.trace("getProducts() working on step-by-step retrieval.");
114 for (int nodeId = 0; nodeId < VeluxKLFAPI.KLF_SYSTEMTABLE_MAX
115 && nodeId < VELUXBINDING_SYSTEMTABLE_MAX; nodeId++) {
116 logger.trace("getProducts() working on product number {}.", nodeId);
117 bcpSbS.setProductId(nodeId);
118 if (bridge.bridgeCommunicate(bcpSbS) && bcpSbS.isCommunicationSuccessful()) {
119 VeluxProduct veluxProduct = bcpSbS.getProduct();
120 if (bcpSbS.isCommunicationSuccessful()) {
121 logger.debug("getProducts() found product {}.", veluxProduct);
122 if (!channel.existingProducts.isRegistered(veluxProduct)) {
123 channel.existingProducts.register(veluxProduct);
129 logger.trace("getProducts() working on bulk retrieval.");
130 if (bridge.bridgeCommunicate(bcp) && bcp.isCommunicationSuccessful()) {
131 for (VeluxProduct product : bcp.getProducts()) {
132 logger.trace("getProducts() found product {} (type {}).", product.getProductName(),
133 product.getProductType());
134 if (!channel.existingProducts.isRegistered(product)) {
135 logger.debug("getProducts() storing new product {}.", product);
136 channel.existingProducts.register(product);
138 logger.debug("getProducts() storing updates for product {}.", product);
139 channel.existingProducts.update(product);
143 logger.trace("getProducts() finished with failure.");
147 logger.debug("getProducts() finally has found products {}.", channel.existingProducts);
152 * In case of an empty list of recognized products, the method will
153 * initiate a product retrieval using {@link #getProducts(VeluxBridge)}.
155 * @param bridge Initialized Velux bridge (communication) handler.
156 * @return true if at least one product was found, and false otherwise.
158 public boolean autoRefresh(VeluxBridge bridge) {
159 int numberOfActuators = channel.existingProducts.getNoMembers();
160 if (numberOfActuators == 0) {
161 logger.trace("autoRefresh(): is about to fetch existing products.");
164 return (numberOfActuators > 0);