2 * Copyright (c) 2010-2022 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.livisismarthome.internal.manager;
15 import static org.openhab.binding.livisismarthome.internal.LivisiBindingConstants.BATTERY_POWERED_DEVICES;
17 import java.io.IOException;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
23 import java.util.Objects;
24 import java.util.Optional;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.openhab.binding.livisismarthome.internal.client.LivisiClient;
29 import org.openhab.binding.livisismarthome.internal.client.api.entity.capability.CapabilityDTO;
30 import org.openhab.binding.livisismarthome.internal.client.api.entity.capability.CapabilityStateDTO;
31 import org.openhab.binding.livisismarthome.internal.client.api.entity.device.DeviceDTO;
32 import org.openhab.binding.livisismarthome.internal.client.api.entity.device.DeviceStateDTO;
33 import org.openhab.binding.livisismarthome.internal.client.api.entity.link.LinkDTO;
34 import org.openhab.binding.livisismarthome.internal.client.api.entity.location.LocationDTO;
35 import org.openhab.binding.livisismarthome.internal.client.api.entity.message.MessageDTO;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
40 * @author Sven Strohschein - Initial contribution
42 * (created by refactoring the LivisiClient class)
45 public class FullDeviceManager {
47 private final Logger logger = LoggerFactory.getLogger(FullDeviceManager.class);
49 private final LivisiClient client;
51 public FullDeviceManager(LivisiClient client) {
56 * Returns a {@link List} of all {@link DeviceDTO}s with the full configuration details, {@link CapabilityDTO}s and
57 * states. Calling this may take a while...
59 public List<DeviceDTO> getFullDevices() throws IOException {
61 final Map<String, LocationDTO> locationMap = createLocationMap(client);
62 final Map<String, CapabilityDTO> capabilityMap = createCapabilityMap(client);
63 final Map<String, DeviceStateDTO> deviceStateMap = createDeviceStateMap(client);
64 final Map<String, List<MessageDTO>> messageMap = createMessageMap(client);
66 final List<DeviceDTO> deviceList = client.getDevices(deviceStateMap.keySet());
67 for (final DeviceDTO device : deviceList) {
68 final String deviceId = device.getId();
69 initializeDevice(device, deviceStateMap.get(deviceId), locationMap, capabilityMap,
70 getMessageList(device, messageMap));
76 * Returns the {@link DeviceDTO} with the given deviceId with full configuration details, {@link CapabilityDTO}s and
77 * states. Calling this may take a little bit longer...
79 public Optional<DeviceDTO> getFullDeviceById(final String deviceId, final boolean isSHCClassic) throws IOException {
80 final Map<String, LocationDTO> locationMap = createLocationMap(client);
81 final Map<String, CapabilityDTO> capabilityMap = createCapabilityMap(deviceId, client);
82 final List<MessageDTO> messageMap = createMessageMap(deviceId, client);
84 final Optional<DeviceDTO> device = client.getDeviceById(deviceId);
85 if (device.isPresent()) {
86 final DeviceStateDTO deviceState = new DeviceStateDTO();
87 deviceState.setId(deviceId);
88 deviceState.setState(client.getDeviceStateByDeviceId(deviceId, isSHCClassic));
90 initializeDevice(device.get(), deviceState, locationMap, capabilityMap, messageMap);
95 private void initializeDevice(DeviceDTO device, @Nullable DeviceStateDTO deviceState,
96 Map<String, LocationDTO> locationMap, Map<String, CapabilityDTO> capabilityMap,
97 List<MessageDTO> messageList) {
99 device.setDeviceState(deviceState);
101 if (isBatteryPowered(device)) {
102 device.setIsBatteryPowered(true);
105 device.setLocation(locationMap.get(device.getLocationId()));
107 device.setCapabilityMap(createDeviceCapabilityMap(device, capabilityMap));
109 device.setMessageList(messageList);
112 private static boolean isBatteryPowered(DeviceDTO device) {
113 return BATTERY_POWERED_DEVICES.contains(device.getType());
116 private List<MessageDTO> getMessageList(DeviceDTO device, Map<String, List<MessageDTO>> messageMap) {
117 return Objects.requireNonNullElse(messageMap.get(device.getId()), Collections.emptyList());
120 private static Map<String, LocationDTO> createLocationMap(LivisiClient client) throws IOException {
121 final List<LocationDTO> locationList = client.getLocations();
122 final Map<String, LocationDTO> locationMap = new HashMap<>(locationList.size());
123 for (final LocationDTO location : locationList) {
124 locationMap.put(location.getId(), location);
129 private static Map<String, CapabilityStateDTO> createCapabilityStateMap(LivisiClient client) throws IOException {
130 final List<CapabilityStateDTO> capabilityStateList = client.getCapabilityStates();
131 final Map<String, CapabilityStateDTO> capabilityStateMap = new HashMap<>(capabilityStateList.size());
132 for (final CapabilityStateDTO capabilityState : capabilityStateList) {
133 capabilityStateMap.put(capabilityState.getId(), capabilityState);
135 return capabilityStateMap;
138 private static Map<String, CapabilityDTO> createCapabilityMap(LivisiClient client) throws IOException {
140 final Map<String, CapabilityStateDTO> capabilityStateMap = createCapabilityStateMap(client);
141 final List<CapabilityDTO> capabilityList = client.getCapabilities();
143 return initializeCapabilities(capabilityStateMap, capabilityList);
146 private static Map<String, CapabilityDTO> createCapabilityMap(String deviceId, LivisiClient client)
149 final Map<String, CapabilityStateDTO> capabilityStateMap = createCapabilityStateMap(client);
150 final List<CapabilityDTO> capabilityList = client.getCapabilitiesForDevice(deviceId);
152 return initializeCapabilities(capabilityStateMap, capabilityList);
155 private static Map<String, CapabilityDTO> initializeCapabilities(Map<String, CapabilityStateDTO> capabilityStateMap,
156 List<CapabilityDTO> capabilityList) {
157 final Map<String, CapabilityDTO> capabilityMap = new HashMap<>(capabilityList.size());
158 for (final CapabilityDTO capability : capabilityList) {
159 String capabilityId = capability.getId();
161 CapabilityStateDTO capabilityState = capabilityStateMap.get(capabilityId);
162 capability.setCapabilityState(capabilityState);
164 capabilityMap.put(capabilityId, capability);
166 return capabilityMap;
169 private static Map<String, CapabilityDTO> createDeviceCapabilityMap(DeviceDTO device,
170 Map<String, CapabilityDTO> capabilityMap) {
172 final HashMap<String, CapabilityDTO> deviceCapabilityMap = new HashMap<>();
173 for (final String capabilityValue : device.getCapabilities()) {
174 final CapabilityDTO capability = capabilityMap.get(LinkDTO.getId(capabilityValue));
175 if (capability != null) {
176 final String capabilityId = capability.getId();
177 deviceCapabilityMap.put(capabilityId, capability);
180 return deviceCapabilityMap;
183 private static Map<String, DeviceStateDTO> createDeviceStateMap(LivisiClient client) throws IOException {
184 final List<DeviceStateDTO> deviceStateList = client.getDeviceStates();
185 final Map<String, DeviceStateDTO> deviceStateMap = new HashMap<>(deviceStateList.size());
186 for (final DeviceStateDTO deviceState : deviceStateList) {
187 deviceStateMap.put(deviceState.getId(), deviceState);
189 return deviceStateMap;
192 private List<MessageDTO> createMessageMap(String deviceId, LivisiClient client) throws IOException {
193 final List<MessageDTO> messages = client.getMessages();
194 final List<MessageDTO> messageList = new ArrayList<>();
195 final String deviceIdPath = "/device/" + deviceId;
197 for (final MessageDTO message : messages) {
198 logger.trace("Message Type {} with ID {}", message.getType(), message.getId());
199 if (message.getDevices() != null && !message.getDevices().isEmpty()) {
200 for (final String li : message.getDevices()) {
201 if (deviceIdPath.equals(li)) {
202 messageList.add(message);
210 private static Map<String, List<MessageDTO>> createMessageMap(LivisiClient client) throws IOException {
211 final List<MessageDTO> messageList = client.getMessages();
212 final Map<String, List<MessageDTO>> deviceMessageMap = new HashMap<>();
213 for (final MessageDTO message : messageList) {
214 if (message.getDevices() != null && !message.getDevices().isEmpty()) {
215 final String deviceId = message.getDevices().get(0).replace("/device/", "");
217 // could get optimized with computeIfAbsent, but the non-null checks doesn't understand that and
218 // produces compiler warnings...
219 List<MessageDTO> ml = deviceMessageMap.get(deviceId);
221 ml = new ArrayList<>();
222 deviceMessageMap.put(deviceId, ml);
227 return deviceMessageMap;