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