]> git.basschouten.com Git - openhab-addons.git/blob
69fa11e634743d89ca35f53f801056ed754a4a72
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.innogysmarthome.internal.manager;
14
15 import java.io.IOException;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.concurrent.ConcurrentHashMap;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.innogysmarthome.internal.InnogyBindingConstants;
26 import org.openhab.binding.innogysmarthome.internal.client.InnogyClient;
27 import org.openhab.binding.innogysmarthome.internal.client.entity.capability.Capability;
28 import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device;
29 import org.openhab.binding.innogysmarthome.internal.client.entity.link.Link;
30 import org.openhab.binding.innogysmarthome.internal.client.entity.message.Message;
31 import org.openhab.binding.innogysmarthome.internal.client.exception.ApiException;
32 import org.openhab.binding.innogysmarthome.internal.client.exception.AuthenticationException;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * Manages the structure of the {@link Device}s and the calls to the {@link InnogyClient} to load the {@link Device}
38  * data from the innogy SmartHome web service.
39  *
40  * @author Oliver Kuhl - Initial contribution
41  *
42  */
43 @NonNullByDefault
44 public class DeviceStructureManager {
45
46     private final Logger logger = LoggerFactory.getLogger(DeviceStructureManager.class);
47
48     private final FullDeviceManager deviceManager;
49     private final Map<String, Device> deviceMap;
50     private final Map<String, Device> capabilityIdToDeviceMap;
51     private String bridgeDeviceId = "";
52
53     /**
54      * Constructs the {@link DeviceStructureManager}.
55      *
56      * @param deviceManager the {@link FullDeviceManager}
57      */
58     public DeviceStructureManager(FullDeviceManager deviceManager) {
59         this.deviceManager = deviceManager;
60         deviceMap = Collections.synchronizedMap(new HashMap<>());
61         capabilityIdToDeviceMap = new ConcurrentHashMap<>();
62     }
63
64     /**
65      * Returns the {@link #deviceMap}, a map with the device id and the device.
66      *
67      * @return
68      */
69     public Map<String, Device> getDeviceMap() {
70         return deviceMap;
71     }
72
73     /**
74      * Loads all device data from the bridge and stores the {@link Device}s and their states in the
75      * {@link DeviceStructureManager}.
76      *
77      * @throws IOException
78      * @throws ApiException
79      * @throws AuthenticationException
80      */
81     public void refreshDevices() throws IOException, ApiException, AuthenticationException {
82         deviceMap.clear();
83         capabilityIdToDeviceMap.clear();
84         List<Device> devices = deviceManager.getFullDevices();
85         for (Device d : devices) {
86             handleRefreshedDevice(d);
87         }
88     }
89
90     /**
91      * Refreshs the {@link Device} with the given id and stores it in the {@link DeviceStructureManager}.
92      *
93      * @param deviceId
94      * @throws IOException
95      * @throws ApiException
96      * @throws AuthenticationException
97      */
98     public void refreshDevice(String deviceId) throws IOException, ApiException, AuthenticationException {
99         logger.trace("Refreshing Device with id '{}'", deviceId);
100         Device d = deviceManager.getFullDeviceById(deviceId);
101         handleRefreshedDevice(d);
102     }
103
104     /**
105      * Stores the newly refreshed {@link Device} in the {@link DeviceStructureManager} structure and logs the
106      * {@link Device}s details and state, if the debug logging is enabled.
107      *
108      * @param d the {@link Device}
109      */
110     private void handleRefreshedDevice(Device d) {
111         if (InnogyBindingConstants.SUPPORTED_DEVICES.contains(d.getType())) {
112             addDeviceToStructure(d);
113         } else {
114             logger.debug("Device {}:'{}' by {} ({}) ignored - UNSUPPORTED.", d.getType(), d.getConfig().getName(),
115                     d.getManufacturer(), d.getId());
116             logger.debug("====================================");
117             return;
118         }
119
120         if (d.isController()) {
121             bridgeDeviceId = d.getId();
122         }
123
124         if (logger.isDebugEnabled()) {
125             try {
126                 logger.debug("Device {}:'{}@{}' by {} ({}) loaded.", d.getType(), d.getConfig().getName(),
127                         d.getLocation() != null ? d.getLocation().getName() : "<none>", d.getManufacturer(), d.getId());
128                 for (Capability c : d.getCapabilityMap().values()) {
129                     logger.debug("> CAP: {}/{} ({})", c.getType(), c.getName(), c.getId());
130                     if (d.isRadioDevice() && !d.isReachable()) {
131                         logger.debug(">> CAP-State: unknown (device NOT REACHABLE).");
132                     } else {
133                         if (!c.hasState()) {
134                             logger.debug(">> CAP-State: unknown (NULL)");
135                         }
136                     }
137                 }
138             } catch (RuntimeException e) {
139                 logger.debug("Error during logging: ", e);
140             }
141             logger.debug("====================================");
142         }
143     }
144
145     /**
146      * Adds the {@link Device} to the structure.
147      *
148      * @param device
149      */
150     public void addDeviceToStructure(Device device) {
151         if (device.getId() != null) {
152             getDeviceMap().put(device.getId(), device);
153         }
154
155         for (String cl : device.getCapabilities()) {
156             capabilityIdToDeviceMap.put(Link.getId(cl), device);
157         }
158     }
159
160     /**
161      * Returns the {@link Device} with the given id.
162      *
163      * @param id
164      * @return the {@link Device} or null, if it does not exist
165      */
166     public @Nullable Device getDeviceById(String id) {
167         logger.debug("getDeviceById {}:{}", id, getDeviceMap().containsKey(id));
168         return getDeviceMap().get(id);
169     }
170
171     /**
172      * Returns the {@link Device}, that provides the given capability.
173      *
174      * @param capabilityId
175      * @return {@link Device} or null
176      */
177     public @Nullable Device getDeviceByCapabilityId(String capabilityId) {
178         return capabilityIdToDeviceMap.get(capabilityId);
179     }
180
181     /**
182      * Returns the bridge {@link Device}.
183      *
184      * @return
185      */
186     public @Nullable Device getBridgeDevice() {
187         return getDeviceMap().get(bridgeDeviceId);
188     }
189
190     /**
191      * Returns a {@link Collection} of all {@link Device}s handled by the {@link DeviceStructureManager}.
192      *
193      * @return
194      */
195     public Collection<Device> getDeviceList() {
196         return Collections.unmodifiableCollection(getDeviceMap().values());
197     }
198
199     /**
200      * Returns the {@link Device}, that has the {@link Message} with the given messageId.
201      *
202      * @param messageId the id of the {@link Message}
203      * @return the {@link Device} or null if none found
204      */
205     public @Nullable Device getDeviceWithMessageId(String messageId) {
206         logger.trace("Getting Device with MessageId '{}'", messageId);
207         for (Device d : getDeviceMap().values()) {
208             if (d.hasMessages()) {
209                 for (Message m : d.getMessageList()) {
210                     if (messageId.equals(m.getId())) {
211                         return d;
212                     }
213                 }
214             }
215         }
216         return null;
217     }
218
219     /**
220      * Returns the id of the {@link Capability} for {@link Device} with the given id and the given capabilityType.
221      *
222      * @param deviceId
223      * @param capabilityType
224      * @return the id of the found {@link Capability} or null
225      */
226     public @Nullable String getCapabilityId(String deviceId, String capabilityType) {
227         Device device = getDeviceMap().get(deviceId);
228         for (Capability c : device.getCapabilityMap().values()) {
229             if (c.getType().equals(capabilityType)) {
230                 return c.getId();
231             }
232         }
233         return null;
234     }
235 }