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 {
60 final Map<String, LocationDTO> locationMap = createLocationMap(client);
61 final Map<String, CapabilityDTO> capabilityMap = createCapabilityMap(client);
62 final Map<String, DeviceStateDTO> deviceStateMap = createDeviceStateMap(client);
63 final Map<String, List<MessageDTO>> messageMap = createMessageMap(client);
65 final List<DeviceDTO> deviceList = client.getDevices(deviceStateMap.keySet());
66 for (final DeviceDTO device : deviceList) {
67 final String deviceId = device.getId();
68 initializeDevice(device, deviceStateMap.get(deviceId), locationMap, capabilityMap,
69 getMessageList(device, messageMap));
75 * Returns the {@link DeviceDTO} with the given deviceId with full configuration details, {@link CapabilityDTO}s and
76 * states. Calling this may take a little bit longer...
78 public Optional<DeviceDTO> getFullDeviceById(final String deviceId, final boolean isSHCClassic) throws IOException {
79 final Map<String, LocationDTO> locationMap = createLocationMap(client);
80 final Map<String, CapabilityDTO> capabilityMap = createCapabilityMap(deviceId, client);
81 final List<MessageDTO> messageMap = createMessageMap(deviceId, client);
83 final Optional<DeviceDTO> device = client.getDeviceById(deviceId);
84 if (device.isPresent()) {
85 final DeviceStateDTO deviceState = new DeviceStateDTO();
86 deviceState.setId(deviceId);
87 deviceState.setState(client.getDeviceStateByDeviceId(deviceId, isSHCClassic));
89 initializeDevice(device.get(), deviceState, locationMap, capabilityMap, messageMap);
94 private void initializeDevice(DeviceDTO device, @Nullable DeviceStateDTO deviceState,
95 Map<String, LocationDTO> locationMap, Map<String, CapabilityDTO> capabilityMap,
96 List<MessageDTO> messageList) {
97 device.setDeviceState(deviceState);
99 if (isBatteryPowered(device)) {
100 device.setIsBatteryPowered(true);
103 device.setLocation(locationMap.get(device.getLocationId()));
105 device.setCapabilityMap(createDeviceCapabilityMap(device, capabilityMap));
107 device.setMessageList(messageList);
110 private static boolean isBatteryPowered(DeviceDTO device) {
111 return BATTERY_POWERED_DEVICES.contains(device.getType());
114 private List<MessageDTO> getMessageList(DeviceDTO device, Map<String, List<MessageDTO>> messageMap) {
115 return Objects.requireNonNullElse(messageMap.get(device.getId()), Collections.emptyList());
118 private static Map<String, LocationDTO> createLocationMap(LivisiClient client) throws IOException {
119 final List<LocationDTO> locationList = client.getLocations();
120 final Map<String, LocationDTO> locationMap = new HashMap<>(locationList.size());
121 for (final LocationDTO location : locationList) {
122 locationMap.put(location.getId(), location);
127 private static Map<String, CapabilityStateDTO> createCapabilityStateMap(LivisiClient client) throws IOException {
128 final List<CapabilityStateDTO> capabilityStateList = client.getCapabilityStates();
129 final Map<String, CapabilityStateDTO> capabilityStateMap = new HashMap<>(capabilityStateList.size());
130 for (final CapabilityStateDTO capabilityState : capabilityStateList) {
131 capabilityStateMap.put(capabilityState.getId(), capabilityState);
133 return capabilityStateMap;
136 private static Map<String, CapabilityDTO> createCapabilityMap(LivisiClient client) throws IOException {
137 final Map<String, CapabilityStateDTO> capabilityStateMap = createCapabilityStateMap(client);
138 final List<CapabilityDTO> capabilityList = client.getCapabilities();
140 return initializeCapabilities(capabilityStateMap, capabilityList);
143 private static Map<String, CapabilityDTO> createCapabilityMap(String deviceId, LivisiClient client)
145 final Map<String, CapabilityStateDTO> capabilityStateMap = createCapabilityStateMap(client);
146 final List<CapabilityDTO> capabilityList = client.getCapabilitiesForDevice(deviceId);
148 return initializeCapabilities(capabilityStateMap, capabilityList);
151 private static Map<String, CapabilityDTO> initializeCapabilities(Map<String, CapabilityStateDTO> capabilityStateMap,
152 List<CapabilityDTO> capabilityList) {
153 final Map<String, CapabilityDTO> capabilityMap = new HashMap<>(capabilityList.size());
154 for (final CapabilityDTO capability : capabilityList) {
155 String capabilityId = capability.getId();
157 CapabilityStateDTO capabilityState = capabilityStateMap.get(capabilityId);
158 capability.setCapabilityState(capabilityState);
160 capabilityMap.put(capabilityId, capability);
162 return capabilityMap;
165 private static Map<String, CapabilityDTO> createDeviceCapabilityMap(DeviceDTO device,
166 Map<String, CapabilityDTO> capabilityMap) {
167 final HashMap<String, CapabilityDTO> deviceCapabilityMap = new HashMap<>();
168 for (final String capabilityValue : device.getCapabilities()) {
169 final CapabilityDTO capability = capabilityMap.get(LinkDTO.getId(capabilityValue));
170 if (capability != null) {
171 final String capabilityId = capability.getId();
172 deviceCapabilityMap.put(capabilityId, capability);
175 return deviceCapabilityMap;
178 private static Map<String, DeviceStateDTO> createDeviceStateMap(LivisiClient client) throws IOException {
179 final List<DeviceStateDTO> deviceStateList = client.getDeviceStates();
180 final Map<String, DeviceStateDTO> deviceStateMap = new HashMap<>(deviceStateList.size());
181 for (final DeviceStateDTO deviceState : deviceStateList) {
182 deviceStateMap.put(deviceState.getId(), deviceState);
184 return deviceStateMap;
187 private List<MessageDTO> createMessageMap(String deviceId, LivisiClient client) throws IOException {
188 final List<MessageDTO> messages = client.getMessages();
189 final List<MessageDTO> messageList = new ArrayList<>();
190 final String deviceIdPath = "/device/" + deviceId;
192 for (final MessageDTO message : messages) {
193 logger.trace("Message Type {} with ID {}", message.getType(), message.getId());
194 if (message.getDevices() != null && !message.getDevices().isEmpty()) {
195 for (final String li : message.getDevices()) {
196 if (deviceIdPath.equals(li)) {
197 messageList.add(message);
205 private static Map<String, List<MessageDTO>> createMessageMap(LivisiClient client) throws IOException {
206 final List<MessageDTO> messageList = client.getMessages();
207 final Map<String, List<MessageDTO>> deviceMessageMap = new HashMap<>();
208 for (final MessageDTO message : messageList) {
209 if (message.getDevices() != null && !message.getDevices().isEmpty()) {
210 final String deviceId = message.getDevices().get(0).replace("/device/", "");
212 // could get optimized with computeIfAbsent, but the non-null checks doesn't understand that and
213 // produces compiler warnings...
214 List<MessageDTO> ml = deviceMessageMap.get(deviceId);
216 ml = new ArrayList<>();
217 deviceMessageMap.put(deviceId, ml);
222 return deviceMessageMap;