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