2 * Copyright (c) 2010-2021 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.innogysmarthome.internal.manager;
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;
21 import java.util.concurrent.ConcurrentHashMap;
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.capability.State;
29 import org.openhab.binding.innogysmarthome.internal.client.entity.device.Device;
30 import org.openhab.binding.innogysmarthome.internal.client.entity.link.Link;
31 import org.openhab.binding.innogysmarthome.internal.client.entity.message.Message;
32 import org.openhab.binding.innogysmarthome.internal.client.exception.ApiException;
33 import org.openhab.binding.innogysmarthome.internal.client.exception.AuthenticationException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * Manages the structure of the {@link Device}s and the calls to the {@link InnogyClient} to load the {@link Device}
39 * data from the innogy SmartHome web service.
41 * @author Oliver Kuhl - Initial contribution
45 public class DeviceStructureManager {
47 private final Logger logger = LoggerFactory.getLogger(DeviceStructureManager.class);
49 private final FullDeviceManager deviceManager;
50 private final Map<String, Device> deviceMap;
51 private final Map<String, Device> capabilityIdToDeviceMap;
52 private String bridgeDeviceId = "";
55 * Constructs the {@link DeviceStructureManager}.
57 * @param deviceManager the {@link FullDeviceManager}
59 public DeviceStructureManager(FullDeviceManager deviceManager) {
60 this.deviceManager = deviceManager;
61 deviceMap = Collections.synchronizedMap(new HashMap<>());
62 capabilityIdToDeviceMap = new ConcurrentHashMap<>();
66 * Returns the {@link #deviceMap}, a map with the device id and the device.
70 public Map<String, Device> getDeviceMap() {
75 * Loads all device data from the bridge and stores the {@link Device}s and their states in the
76 * {@link DeviceStructureManager}.
79 * @throws ApiException
80 * @throws AuthenticationException
82 public void refreshDevices() throws IOException, ApiException, AuthenticationException {
84 capabilityIdToDeviceMap.clear();
85 List<Device> devices = deviceManager.getFullDevices();
86 for (Device d : devices) {
87 handleRefreshedDevice(d);
92 * Refreshs the {@link Device} with the given id and stores it in the {@link DeviceStructureManager}.
96 * @throws ApiException
97 * @throws AuthenticationException
99 public void refreshDevice(String deviceId) throws IOException, ApiException, AuthenticationException {
100 logger.trace("Refreshing Device with id '{}'", deviceId);
101 Device d = deviceManager.getFullDeviceById(deviceId);
102 handleRefreshedDevice(d);
106 * Stores the newly refreshed {@link Device} in the {@link DeviceStructureManager} structure and logs the
107 * {@link Device}s details and state, if the debug logging is enabled.
109 * @param d the {@link Device}
111 private void handleRefreshedDevice(Device d) {
112 if (InnogyBindingConstants.SUPPORTED_DEVICES.contains(d.getType())) {
113 addDeviceToStructure(d);
115 logger.debug("Device {}:'{}' by {} ({}) ignored - UNSUPPORTED.", d.getType(), d.getConfig().getName(),
116 d.getManufacturer(), d.getId());
117 logger.debug("====================================");
121 if (d.isController()) {
122 bridgeDeviceId = d.getId();
125 if (logger.isDebugEnabled()) {
127 logger.debug("Device {}:'{}@{}' by {} ({}) loaded.", d.getType(), d.getConfig().getName(),
128 d.getLocation() != null ? d.getLocation().getName() : "<none>", d.getManufacturer(), d.getId());
129 for (Capability c : d.getCapabilityMap().values()) {
130 logger.debug("> CAP: {}/{} ({})", c.getType(), c.getName(), c.getId());
131 if (d.isRadioDevice() && !d.isReachable()) {
132 logger.debug(">> CAP-State: unknown (device NOT REACHABLE).");
135 final State state = c.getCapabilityState().getState();
137 logger.debug(">> CAP-State: unknown (NULL)");
141 } catch (RuntimeException e) {
142 logger.debug("Error during logging: ", e);
144 logger.debug("====================================");
149 * Adds the {@link Device} to the structure.
153 public void addDeviceToStructure(Device device) {
154 if (device.getId() != null) {
155 getDeviceMap().put(device.getId(), device);
158 for (String cl : device.getCapabilities()) {
159 capabilityIdToDeviceMap.put(Link.getId(cl), device);
164 * Returns the {@link Device} with the given id.
167 * @return the {@link Device} or null, if it does not exist
169 public @Nullable Device getDeviceById(String id) {
170 logger.debug("getDeviceById {}:{}", id, getDeviceMap().containsKey(id));
171 return getDeviceMap().get(id);
175 * Returns the {@link Device}, that provides the given capability.
177 * @param capabilityId
178 * @return {@link Device} or null
180 public @Nullable Device getDeviceByCapabilityId(String capabilityId) {
181 return capabilityIdToDeviceMap.get(capabilityId);
185 * Returns the bridge {@link Device}.
189 public @Nullable Device getBridgeDevice() {
190 return getDeviceMap().get(bridgeDeviceId);
194 * Returns a {@link Collection} of all {@link Device}s handled by the {@link DeviceStructureManager}.
198 public Collection<Device> getDeviceList() {
199 return Collections.unmodifiableCollection(getDeviceMap().values());
203 * Returns the {@link Device}, that has the {@link Message} with the given messageId.
205 * @param messageId the id of the {@link Message}
206 * @return the {@link Device} or null if none found
208 public @Nullable Device getDeviceWithMessageId(String messageId) {
209 logger.trace("Getting Device with MessageId '{}'", messageId);
210 for (Device d : getDeviceMap().values()) {
211 if (d.hasMessages()) {
212 for (Message m : d.getMessageList()) {
213 if (messageId.equals(m.getId())) {
223 * Returns the id of the {@link Capability} for {@link Device} with the given id and the given capabilityType.
226 * @param capabilityType
227 * @return the id of the found {@link Capability} or null
229 public @Nullable String getCapabilityId(String deviceId, String capabilityType) {
230 Device device = getDeviceMap().get(deviceId);
231 for (Capability c : device.getCapabilityMap().values()) {
232 if (c.getType().equals(capabilityType)) {