2 * Copyright (c) 2010-2023 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.digitalstrom.internal.lib.manager.impl;
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.LinkedList;
18 import java.util.List;
22 import org.openhab.binding.digitalstrom.internal.lib.manager.ConnectionManager;
23 import org.openhab.binding.digitalstrom.internal.lib.manager.StructureManager;
24 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.AbstractGeneralDeviceInformations;
25 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Circuit;
26 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.Device;
27 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.CachedMeteringValue;
28 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSID;
29 import org.openhab.binding.digitalstrom.internal.lib.structure.devices.deviceparameters.impl.DSUID;
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonObject;
35 * The {@link StructureManagerImpl} is the implementation of the {@link StructureManager}.
37 * @author Michael Ochel - Initial contribution
38 * @author Matthias Siegele - Initial contribution
40 public class StructureManagerImpl implements StructureManager {
42 private class ZoneGroupsNameAndIDMap {
43 public final String zoneName;
44 public final int zoneID;
46 private final Map<Short, String> groupIdNames;
47 private final Map<String, Short> groupNameIds;
49 public ZoneGroupsNameAndIDMap(final int zoneID, final String zoneName, JsonArray groups) {
51 this.zoneName = zoneName;
53 groupIdNames = new HashMap<>(groups.size());
54 groupNameIds = new HashMap<>(groups.size());
55 for (int k = 0; k < groups.size(); k++) {
56 short groupID = ((JsonObject) groups.get(k)).get("group").getAsShort();
57 String groupName = ((JsonObject) groups.get(k)).get("name").getAsString();
58 groupIdNames.put(groupID, groupName);
59 groupNameIds.put(groupName, groupID);
63 public String getGroupName(Short groupID) {
64 return groupIdNames.get(groupID);
67 public short getGroupID(String groupName) {
68 final Short tmp = groupNameIds.get(groupName);
69 return tmp != null ? tmp : -1;
74 * Query to get all zone and group names. Can be executed with {@link DsAPI#query(String, String)} or
75 * {@link DsAPI#query2(String, String)}.
77 public static final String ZONE_GROUP_NAMES = "/apartment/zones/*(ZoneID,name)/groups/*(group,name)";
79 private final Map<Integer, Map<Short, List<Device>>> zoneGroupDeviceMap = Collections
80 .synchronizedMap(new HashMap<>());
81 private final Map<DSID, Device> deviceMap = Collections.synchronizedMap(new HashMap<>());
82 private final Map<DSID, Circuit> circuitMap = Collections.synchronizedMap(new HashMap<>());
83 private final Map<String, DSID> dSUIDToDSIDMap = Collections.synchronizedMap(new HashMap<>());
85 private Map<Integer, ZoneGroupsNameAndIDMap> zoneGroupIdNameMap;
86 private Map<String, ZoneGroupsNameAndIDMap> zoneGroupNameIdMap;
89 * Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
91 * @param referenceDeviceList to add
93 public StructureManagerImpl(List<Device> referenceDeviceList) {
94 handleStructure(referenceDeviceList);
98 * Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
100 * @param referenceDeviceList to add
101 * @param referenceCircuitList to add
103 public StructureManagerImpl(List<Device> referenceDeviceList, List<Circuit> referenceCircuitList) {
104 handleStructure(referenceDeviceList);
105 addCircuitList(referenceCircuitList);
109 * Creates a new {@link StructureManagerImpl} without {@link Device}s.
111 public StructureManagerImpl() {
115 public boolean generateZoneGroupNames(ConnectionManager connectionManager) {
116 JsonObject resultJsonObj = connectionManager.getDigitalSTROMAPI().query(connectionManager.getSessionToken(),
118 if (resultJsonObj != null && resultJsonObj.get("zones") instanceof JsonArray) {
119 JsonArray zones = (JsonArray) resultJsonObj.get("zones");
120 if (zoneGroupIdNameMap == null) {
121 zoneGroupIdNameMap = new HashMap<>(zones.size());
122 zoneGroupNameIdMap = new HashMap<>(zones.size());
125 for (int i = 0; i < zones.size(); i++) {
126 if (((JsonObject) zones.get(i)).get("groups") instanceof JsonArray) {
127 JsonArray groups = (JsonArray) ((JsonObject) zones.get(i)).get("groups");
128 ZoneGroupsNameAndIDMap zoneGoupIdNameMap = new ZoneGroupsNameAndIDMap(
129 ((JsonObject) zones.get(i)).get("ZoneID").getAsInt(),
130 ((JsonObject) zones.get(i)).get("name").getAsString(), groups);
132 zoneGroupIdNameMap.put(zoneGoupIdNameMap.zoneID, zoneGoupIdNameMap);
133 zoneGroupNameIdMap.put(zoneGoupIdNameMap.zoneName, zoneGoupIdNameMap);
142 public String getZoneName(int zoneID) {
143 if (zoneGroupIdNameMap == null) {
146 final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
147 return tmp != null ? tmp.zoneName : null;
151 public String getZoneGroupName(int zoneID, short groupID) {
152 if (zoneGroupIdNameMap == null) {
155 final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
156 return tmp != null ? tmp.getGroupName(groupID) : null;
160 public int getZoneId(String zoneName) {
161 if (zoneGroupNameIdMap == null) {
164 final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
165 return tmp != null ? tmp.zoneID : -1;
169 public boolean checkZoneID(int zoneID) {
170 return getGroupsFromZoneX(zoneID) != null;
174 public boolean checkZoneGroupID(int zoneID, short groupID) {
175 final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
176 return tmp != null ? tmp.get(groupID) != null : false;
180 public short getZoneGroupId(String zoneName, String groupName) {
181 if (zoneGroupNameIdMap == null) {
184 final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
185 return tmp != null ? tmp.getGroupID(groupName) : -1;
189 public Map<DSID, Device> getDeviceMap() {
190 return new HashMap<>(deviceMap);
193 private void putDeviceToHashMap(Device device) {
194 if (device.getDSID() != null) {
195 deviceMap.put(device.getDSID(), device);
196 addDSIDtoDSUID((AbstractGeneralDeviceInformations) device);
201 * This method build the digitalSTROM structure as a {@link HashMap} with the zone id as key
202 * and a {@link HashMap} as value. This {@link HashMap} has the group id as key and a {@link List}
203 * with all digitalSTROM {@link Device}s.<br>
205 * <b>Note:</b> the zone id 0 is the broadcast address and the group id 0, too.
207 private void handleStructure(List<Device> deviceList) {
208 Map<Short, List<Device>> groupXHashMap = new HashMap<>();
209 groupXHashMap.put((short) 0, deviceList);
211 zoneGroupDeviceMap.put(0, groupXHashMap);
213 for (Device device : deviceList) {
214 addDeviceToStructure(device);
219 public Map<DSID, Device> getDeviceHashMapReference() {
224 public Map<Integer, Map<Short, List<Device>>> getStructureReference() {
225 return zoneGroupDeviceMap;
229 public Map<Short, List<Device>> getGroupsFromZoneX(int zoneID) {
230 return zoneGroupDeviceMap.get(zoneID);
234 public List<Device> getReferenceDeviceListFromZoneXGroupX(int zoneID, short groupID) {
235 final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
236 return tmp != null ? tmp.get(groupID) : null;
240 public Device getDeviceByDSID(String dSID) {
241 return getDeviceByDSID(new DSID(dSID));
245 public Device getDeviceByDSID(DSID dSID) {
246 return deviceMap.get(dSID);
250 public Device getDeviceByDSUID(String dSUID) {
251 final DSID tmp = dSUIDToDSIDMap.get(dSUID);
252 return tmp != null ? getDeviceByDSID(tmp) : null;
256 public void updateDevice(int oldZone, List<Short> oldGroups, Device device) {
257 int intOldZoneID = oldZone;
258 if (intOldZoneID == -1) {
259 intOldZoneID = device.getZoneId();
261 deleteDevice(intOldZoneID, oldGroups, device);
262 addDeviceToStructure(device);
266 public void updateDevice(Device device) {
267 if (device != null) {
269 List<Short> oldGroups = null;
270 Device internalDevice = this.getDeviceByDSID(device.getDSID());
271 if (internalDevice != null) {
272 if (device.getZoneId() != internalDevice.getZoneId()) {
273 oldZoneID = internalDevice.getZoneId();
274 internalDevice.setZoneId(device.getZoneId());
277 if (!internalDevice.getGroups().equals(device.getGroups())) {
278 oldGroups = internalDevice.getGroups();
279 internalDevice.setGroups(device.getGroups());
282 if (deleteDevice(oldZoneID, oldGroups, internalDevice)) {
283 addDeviceToStructure(internalDevice);
290 public void deleteDevice(Device device) {
291 dSUIDToDSIDMap.remove(device.getDSUID());
292 deviceMap.remove(device.getDSID());
293 deleteDevice(device.getZoneId(), device.getGroups(), device);
296 private boolean deleteDevice(int zoneID, List<Short> groups, Device device) {
297 List<Short> intGroups = groups;
298 int intZoneID = zoneID;
299 if (intGroups != null || intZoneID >= 0) {
300 if (intGroups == null) {
301 intGroups = device.getGroups();
303 if (intZoneID == -1) {
304 intZoneID = device.getZoneId();
306 for (Short groupID : intGroups) {
307 List<Device> deviceList = getReferenceDeviceListFromZoneXGroupX(intZoneID, groupID);
308 if (deviceList != null) {
309 deviceList.remove(device);
311 deviceList = getReferenceDeviceListFromZoneXGroupX(0, groupID);
312 if (deviceList != null) {
313 deviceList.remove(device);
322 public void addDeviceToStructure(Device device) {
323 putDeviceToHashMap(device);
325 addDevicetoZoneXGroupX(0, (short) 0, device);
326 int zoneID = device.getZoneId();
327 addDevicetoZoneXGroupX(zoneID, (short) 0, device);
329 for (Short groupID : device.getGroups()) {
330 addDevicetoZoneXGroupX(zoneID, groupID, device);
333 addDevicetoZoneXGroupX(0, groupID, device);
338 private void addDevicetoZoneXGroupX(int zoneID, short groupID, Device device) {
339 Map<Short, List<Device>> groupXHashMap = zoneGroupDeviceMap.get(zoneID);
340 if (groupXHashMap == null) {
341 groupXHashMap = new HashMap<>();
342 zoneGroupDeviceMap.put(zoneID, groupXHashMap);
344 List<Device> groupDeviceList = groupXHashMap.get(groupID);
345 if (groupDeviceList == null) {
346 groupDeviceList = new LinkedList<>();
347 groupDeviceList.add(device);
348 groupXHashMap.put(groupID, groupDeviceList);
350 if (!groupDeviceList.contains(device)) {
351 groupDeviceList.add(device);
357 public Set<Integer> getZoneIDs() {
358 return zoneGroupDeviceMap.keySet();
362 public void addCircuitList(List<Circuit> referenceCircuitList) {
363 for (Circuit circuit : referenceCircuitList) {
369 public Circuit addCircuit(Circuit circuit) {
370 addDSIDtoDSUID((AbstractGeneralDeviceInformations) circuit);
371 return circuitMap.put(circuit.getDSID(), circuit);
374 private void addDSIDtoDSUID(AbstractGeneralDeviceInformations deviceInfo) {
375 if (deviceInfo.getDSID() != null) {
376 dSUIDToDSIDMap.put(deviceInfo.getDSUID(), deviceInfo.getDSID());
381 public Circuit getCircuitByDSID(DSID dSID) {
382 return circuitMap.get(dSID);
386 public Circuit getCircuitByDSUID(String dSUID) {
387 final DSID tmp = dSUIDToDSIDMap.get(dSUID);
388 return tmp != null ? getCircuitByDSID(tmp) : null;
392 public Circuit getCircuitByDSUID(DSUID dSUID) {
393 return dSUID != null ? getCircuitByDSUID(dSUID.getValue()) : null;
397 public Circuit getCircuitByDSID(String dSID) {
398 return getCircuitByDSID(new DSID(dSID));
402 public Circuit updateCircuitConfig(Circuit newCircuit) {
403 Circuit intCircuit = circuitMap.get(newCircuit.getDSID());
404 if (intCircuit != null && !intCircuit.equals(newCircuit)) {
405 for (CachedMeteringValue meteringValue : intCircuit.getAllCachedMeteringValues()) {
406 newCircuit.addMeteringValue(meteringValue);
408 if (intCircuit.isListenerRegisterd()) {
409 newCircuit.registerDeviceStatusListener(intCircuit.getDeviceStatusListener());
412 return addCircuit(newCircuit);
416 public Circuit deleteCircuit(DSID dSID) {
417 return circuitMap.remove(dSID);
421 public Circuit deleteCircuit(String dSUID) {
422 return deleteCircuit(dSUIDToDSIDMap.get(dSUID));
426 public Map<DSID, Circuit> getCircuitMap() {
427 return new HashMap<>(circuitMap);