]> git.basschouten.com Git - openhab-addons.git/blob
2182b9d82ed8c401248627de404947070ccb82fc
[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.digitalstrom.internal.lib.manager.impl;
14
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.LinkedList;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21
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;
30
31 import com.google.gson.JsonArray;
32 import com.google.gson.JsonObject;
33
34 /**
35  * The {@link StructureManagerImpl} is the implementation of the {@link StructureManager}.
36  *
37  * @author Michael Ochel - Initial contribution
38  * @author Matthias Siegele - Initial contribution
39  */
40 public class StructureManagerImpl implements StructureManager {
41
42     private class ZoneGroupsNameAndIDMap {
43         public final String zoneName;
44         public final int zoneID;
45
46         private final Map<Short, String> groupIdNames;
47         private final Map<String, Short> groupNameIds;
48
49         public ZoneGroupsNameAndIDMap(final int zoneID, final String zoneName, JsonArray groups) {
50             this.zoneID = zoneID;
51             this.zoneName = zoneName;
52
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);
60             }
61         }
62
63         public String getGroupName(Short groupID) {
64             return groupIdNames.get(groupID);
65         }
66
67         public short getGroupID(String groupName) {
68             final Short tmp = groupNameIds.get(groupName);
69             return tmp != null ? tmp : -1;
70         }
71     }
72
73     /**
74      * Query to get all zone and group names. Can be executed with
75      * {@link org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI#query(String, String)} or
76      * {@link org.openhab.binding.digitalstrom.internal.lib.serverconnection.DsAPI#query2(String, String)}.
77      */
78     public static final String ZONE_GROUP_NAMES = "/apartment/zones/*(ZoneID,name)/groups/*(group,name)";
79
80     private final Map<Integer, Map<Short, List<Device>>> zoneGroupDeviceMap = Collections
81             .synchronizedMap(new HashMap<>());
82     private final Map<DSID, Device> deviceMap = Collections.synchronizedMap(new HashMap<>());
83     private final Map<DSID, Circuit> circuitMap = Collections.synchronizedMap(new HashMap<>());
84     private final Map<String, DSID> dSUIDToDSIDMap = Collections.synchronizedMap(new HashMap<>());
85
86     private Map<Integer, ZoneGroupsNameAndIDMap> zoneGroupIdNameMap;
87     private Map<String, ZoneGroupsNameAndIDMap> zoneGroupNameIdMap;
88
89     /**
90      * Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
91      *
92      * @param referenceDeviceList to add
93      */
94     public StructureManagerImpl(List<Device> referenceDeviceList) {
95         handleStructure(referenceDeviceList);
96     }
97
98     /**
99      * Creates a new {@link StructureManagerImpl} with the {@link Device}s of the given referenceDeviceList.
100      *
101      * @param referenceDeviceList to add
102      * @param referenceCircuitList to add
103      */
104     public StructureManagerImpl(List<Device> referenceDeviceList, List<Circuit> referenceCircuitList) {
105         handleStructure(referenceDeviceList);
106         addCircuitList(referenceCircuitList);
107     }
108
109     /**
110      * Creates a new {@link StructureManagerImpl} without {@link Device}s.
111      */
112     public StructureManagerImpl() {
113     }
114
115     @Override
116     public boolean generateZoneGroupNames(ConnectionManager connectionManager) {
117         JsonObject resultJsonObj = connectionManager.getDigitalSTROMAPI().query(connectionManager.getSessionToken(),
118                 ZONE_GROUP_NAMES);
119         if (resultJsonObj != null && resultJsonObj.get("zones") instanceof JsonArray) {
120             JsonArray zones = (JsonArray) resultJsonObj.get("zones");
121             if (zoneGroupIdNameMap == null) {
122                 zoneGroupIdNameMap = new HashMap<>(zones.size());
123                 zoneGroupNameIdMap = new HashMap<>(zones.size());
124             }
125             if (zones != null) {
126                 for (int i = 0; i < zones.size(); i++) {
127                     if (((JsonObject) zones.get(i)).get("groups") instanceof JsonArray) {
128                         JsonArray groups = (JsonArray) ((JsonObject) zones.get(i)).get("groups");
129                         ZoneGroupsNameAndIDMap zoneGoupIdNameMap = new ZoneGroupsNameAndIDMap(
130                                 ((JsonObject) zones.get(i)).get("ZoneID").getAsInt(),
131                                 ((JsonObject) zones.get(i)).get("name").getAsString(), groups);
132
133                         zoneGroupIdNameMap.put(zoneGoupIdNameMap.zoneID, zoneGoupIdNameMap);
134                         zoneGroupNameIdMap.put(zoneGoupIdNameMap.zoneName, zoneGoupIdNameMap);
135                     }
136                 }
137             }
138         }
139         return true;
140     }
141
142     @Override
143     public String getZoneName(int zoneID) {
144         if (zoneGroupIdNameMap == null) {
145             return null;
146         }
147         final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
148         return tmp != null ? tmp.zoneName : null;
149     }
150
151     @Override
152     public String getZoneGroupName(int zoneID, short groupID) {
153         if (zoneGroupIdNameMap == null) {
154             return null;
155         }
156         final ZoneGroupsNameAndIDMap tmp = zoneGroupIdNameMap.get(zoneID);
157         return tmp != null ? tmp.getGroupName(groupID) : null;
158     }
159
160     @Override
161     public int getZoneId(String zoneName) {
162         if (zoneGroupNameIdMap == null) {
163             return -1;
164         }
165         final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
166         return tmp != null ? tmp.zoneID : -1;
167     }
168
169     @Override
170     public boolean checkZoneID(int zoneID) {
171         return getGroupsFromZoneX(zoneID) != null;
172     }
173
174     @Override
175     public boolean checkZoneGroupID(int zoneID, short groupID) {
176         final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
177         return tmp != null ? tmp.get(groupID) != null : false;
178     }
179
180     @Override
181     public short getZoneGroupId(String zoneName, String groupName) {
182         if (zoneGroupNameIdMap == null) {
183             return -1;
184         }
185         final ZoneGroupsNameAndIDMap tmp = zoneGroupNameIdMap.get(zoneName);
186         return tmp != null ? tmp.getGroupID(groupName) : -1;
187     }
188
189     @Override
190     public Map<DSID, Device> getDeviceMap() {
191         return new HashMap<>(deviceMap);
192     }
193
194     private void putDeviceToHashMap(Device device) {
195         if (device.getDSID() != null) {
196             deviceMap.put(device.getDSID(), device);
197             addDSIDtoDSUID((AbstractGeneralDeviceInformations) device);
198         }
199     }
200
201     /**
202      * This method build the digitalSTROM structure as a {@link HashMap} with the zone id as key
203      * and a {@link HashMap} as value. This {@link HashMap} has the group id as key and a {@link List}
204      * with all digitalSTROM {@link Device}s.<br>
205      * <br>
206      * <b>Note:</b> the zone id 0 is the broadcast address and the group id 0, too.
207      */
208     private void handleStructure(List<Device> deviceList) {
209         Map<Short, List<Device>> groupXHashMap = new HashMap<>();
210         groupXHashMap.put((short) 0, deviceList);
211
212         zoneGroupDeviceMap.put(0, groupXHashMap);
213
214         for (Device device : deviceList) {
215             addDeviceToStructure(device);
216         }
217     }
218
219     @Override
220     public Map<DSID, Device> getDeviceHashMapReference() {
221         return deviceMap;
222     }
223
224     @Override
225     public Map<Integer, Map<Short, List<Device>>> getStructureReference() {
226         return zoneGroupDeviceMap;
227     }
228
229     @Override
230     public Map<Short, List<Device>> getGroupsFromZoneX(int zoneID) {
231         return zoneGroupDeviceMap.get(zoneID);
232     }
233
234     @Override
235     public List<Device> getReferenceDeviceListFromZoneXGroupX(int zoneID, short groupID) {
236         final Map<Short, List<Device>> tmp = getGroupsFromZoneX(zoneID);
237         return tmp != null ? tmp.get(groupID) : null;
238     }
239
240     @Override
241     public Device getDeviceByDSID(String dSID) {
242         return getDeviceByDSID(new DSID(dSID));
243     }
244
245     @Override
246     public Device getDeviceByDSID(DSID dSID) {
247         return deviceMap.get(dSID);
248     }
249
250     @Override
251     public Device getDeviceByDSUID(String dSUID) {
252         final DSID tmp = dSUIDToDSIDMap.get(dSUID);
253         return tmp != null ? getDeviceByDSID(tmp) : null;
254     }
255
256     @Override
257     public void updateDevice(int oldZone, List<Short> oldGroups, Device device) {
258         int intOldZoneID = oldZone;
259         if (intOldZoneID == -1) {
260             intOldZoneID = device.getZoneId();
261         }
262         deleteDevice(intOldZoneID, oldGroups, device);
263         addDeviceToStructure(device);
264     }
265
266     @Override
267     public void updateDevice(Device device) {
268         if (device != null) {
269             int oldZoneID = -1;
270             List<Short> oldGroups = null;
271             Device internalDevice = this.getDeviceByDSID(device.getDSID());
272             if (internalDevice != null) {
273                 if (device.getZoneId() != internalDevice.getZoneId()) {
274                     oldZoneID = internalDevice.getZoneId();
275                     internalDevice.setZoneId(device.getZoneId());
276                 }
277
278                 if (!internalDevice.getGroups().equals(device.getGroups())) {
279                     oldGroups = internalDevice.getGroups();
280                     internalDevice.setGroups(device.getGroups());
281                 }
282
283                 if (deleteDevice(oldZoneID, oldGroups, internalDevice)) {
284                     addDeviceToStructure(internalDevice);
285                 }
286             }
287         }
288     }
289
290     @Override
291     public void deleteDevice(Device device) {
292         dSUIDToDSIDMap.remove(device.getDSUID());
293         deviceMap.remove(device.getDSID());
294         deleteDevice(device.getZoneId(), device.getGroups(), device);
295     }
296
297     private boolean deleteDevice(int zoneID, List<Short> groups, Device device) {
298         List<Short> intGroups = groups;
299         int intZoneID = zoneID;
300         if (intGroups != null || intZoneID >= 0) {
301             if (intGroups == null) {
302                 intGroups = device.getGroups();
303             }
304             if (intZoneID == -1) {
305                 intZoneID = device.getZoneId();
306             }
307             for (Short groupID : intGroups) {
308                 List<Device> deviceList = getReferenceDeviceListFromZoneXGroupX(intZoneID, groupID);
309                 if (deviceList != null) {
310                     deviceList.remove(device);
311                 }
312                 deviceList = getReferenceDeviceListFromZoneXGroupX(0, groupID);
313                 if (deviceList != null) {
314                     deviceList.remove(device);
315                 }
316             }
317             return true;
318         }
319         return false;
320     }
321
322     @Override
323     public void addDeviceToStructure(Device device) {
324         putDeviceToHashMap(device);
325
326         addDevicetoZoneXGroupX(0, (short) 0, device);
327         int zoneID = device.getZoneId();
328         addDevicetoZoneXGroupX(zoneID, (short) 0, device);
329
330         for (Short groupID : device.getGroups()) {
331             addDevicetoZoneXGroupX(zoneID, groupID, device);
332
333             if (groupID <= 16) {
334                 addDevicetoZoneXGroupX(0, groupID, device);
335             }
336         }
337     }
338
339     private void addDevicetoZoneXGroupX(int zoneID, short groupID, Device device) {
340         Map<Short, List<Device>> groupXHashMap = zoneGroupDeviceMap.get(zoneID);
341         if (groupXHashMap == null) {
342             groupXHashMap = new HashMap<>();
343             zoneGroupDeviceMap.put(zoneID, groupXHashMap);
344         }
345         List<Device> groupDeviceList = groupXHashMap.get(groupID);
346         if (groupDeviceList == null) {
347             groupDeviceList = new LinkedList<>();
348             groupDeviceList.add(device);
349             groupXHashMap.put(groupID, groupDeviceList);
350         } else {
351             if (!groupDeviceList.contains(device)) {
352                 groupDeviceList.add(device);
353             }
354         }
355     }
356
357     @Override
358     public Set<Integer> getZoneIDs() {
359         return zoneGroupDeviceMap.keySet();
360     }
361
362     @Override
363     public void addCircuitList(List<Circuit> referenceCircuitList) {
364         for (Circuit circuit : referenceCircuitList) {
365             addCircuit(circuit);
366         }
367     }
368
369     @Override
370     public Circuit addCircuit(Circuit circuit) {
371         addDSIDtoDSUID((AbstractGeneralDeviceInformations) circuit);
372         return circuitMap.put(circuit.getDSID(), circuit);
373     }
374
375     private void addDSIDtoDSUID(AbstractGeneralDeviceInformations deviceInfo) {
376         if (deviceInfo.getDSID() != null) {
377             dSUIDToDSIDMap.put(deviceInfo.getDSUID(), deviceInfo.getDSID());
378         }
379     }
380
381     @Override
382     public Circuit getCircuitByDSID(DSID dSID) {
383         return circuitMap.get(dSID);
384     }
385
386     @Override
387     public Circuit getCircuitByDSUID(String dSUID) {
388         final DSID tmp = dSUIDToDSIDMap.get(dSUID);
389         return tmp != null ? getCircuitByDSID(tmp) : null;
390     }
391
392     @Override
393     public Circuit getCircuitByDSUID(DSUID dSUID) {
394         return dSUID != null ? getCircuitByDSUID(dSUID.getValue()) : null;
395     }
396
397     @Override
398     public Circuit getCircuitByDSID(String dSID) {
399         return getCircuitByDSID(new DSID(dSID));
400     }
401
402     @Override
403     public Circuit updateCircuitConfig(Circuit newCircuit) {
404         Circuit intCircuit = circuitMap.get(newCircuit.getDSID());
405         if (intCircuit != null && !intCircuit.equals(newCircuit)) {
406             for (CachedMeteringValue meteringValue : intCircuit.getAllCachedMeteringValues()) {
407                 newCircuit.addMeteringValue(meteringValue);
408             }
409             if (intCircuit.isListenerRegisterd()) {
410                 newCircuit.registerDeviceStatusListener(intCircuit.getDeviceStatusListener());
411             }
412         }
413         return addCircuit(newCircuit);
414     }
415
416     @Override
417     public Circuit deleteCircuit(DSID dSID) {
418         return circuitMap.remove(dSID);
419     }
420
421     @Override
422     public Circuit deleteCircuit(String dSUID) {
423         return deleteCircuit(dSUIDToDSIDMap.get(dSUID));
424     }
425
426     @Override
427     public Map<DSID, Circuit> getCircuitMap() {
428         return new HashMap<>(circuitMap);
429     }
430 }