]> git.basschouten.com Git - openhab-addons.git/blob
e5a446677de6e6aa81b969f14f3d8c34319c25c9
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 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.dsmr.internal.discovery;
14
15 import java.util.AbstractMap.SimpleEntry;
16 import java.util.Collection;
17 import java.util.HashMap;
18 import java.util.Map;
19 import java.util.Map.Entry;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.openhab.binding.dsmr.internal.device.cosem.CosemObject;
23 import org.openhab.binding.dsmr.internal.device.cosem.CosemObjectType;
24 import org.openhab.binding.dsmr.internal.device.p1telegram.P1Telegram;
25 import org.openhab.binding.dsmr.internal.meter.DSMRMeterDescriptor;
26 import org.openhab.binding.dsmr.internal.meter.DSMRMeterKind;
27 import org.openhab.binding.dsmr.internal.meter.DSMRMeterType;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * The {@link DSMRMeterDetector} class contains the logic to discover DSMR Meters from a list of CosemObjects.
33  *
34  * @author M. Volaart - Initial contribution
35  * @author Hilbrand Bouwkamp - Refactored code to detect meters during actual discovery phase.
36  */
37 @NonNullByDefault
38 class DSMRMeterDetector {
39     private final Logger logger = LoggerFactory.getLogger(DSMRMeterDetector.class);
40
41     /**
42      * Returns a collection of {@link DSMRMeterDescriptor} that can handle the supplied list of CosemObjects.
43      *
44      * If no meters are detected an empty collection is returned.
45      *
46      * @param telegram The received telegram
47      * @return collection of detected {@link DSMRMeterDescriptor}
48      */
49     public Entry<Collection<DSMRMeterDescriptor>, Map<CosemObjectType, CosemObject>> detectMeters(P1Telegram telegram) {
50         final Map<DSMRMeterKind, DSMRMeterDescriptor> detectedMeters = new HashMap<>();
51         final Map<CosemObjectType, CosemObject> availableCosemObjects = new HashMap<>();
52         final Map<CosemObjectType, CosemObject> undetectedCosemObjects = new HashMap<>();
53
54         // Fill hashmap for fast comparing the set of received Cosem objects to the required set of Cosem Objects
55         telegram.getCosemObjects().forEach(msg -> availableCosemObjects.put(msg.getType(), msg));
56         undetectedCosemObjects.putAll(availableCosemObjects);
57
58         // Find compatible meters
59         for (DSMRMeterType meterType : DSMRMeterType.values()) {
60             logger.trace("Trying if meter type {} is compatible", meterType);
61             final DSMRMeterDescriptor meterDescriptor = meterType.isCompatible(availableCosemObjects);
62
63             if (meterDescriptor == null) {
64                 logger.trace("Meter type {} is not compatible", meterType);
65             } else {
66                 logger.debug("Meter type {} is compatible", meterType);
67
68                 final DSMRMeterDescriptor prevDetectedMeter = detectedMeters.get(meterType.meterKind);
69
70                 if (prevDetectedMeter == null // First meter of this kind, add it
71                         || (prevDetectedMeter.getChannel() == meterDescriptor.getChannel())
72                                 && meterType.requiredCosemObjects.length > prevDetectedMeter
73                                         .getMeterType().requiredCosemObjects.length) {
74                     logger.debug("New compatible meter: {}", meterDescriptor);
75                     detectedMeters.put(meterType.meterKind, meterDescriptor);
76                     for (CosemObjectType cot : meterDescriptor.getMeterType().supportedCosemObjects) {
77                         undetectedCosemObjects.remove(cot);
78                     }
79                 }
80             }
81         }
82         logger.trace("Telegram as received from the device:\n{}\n", telegram.getRawTelegram());
83         return new SimpleEntry<>(detectedMeters.values(), undetectedCosemObjects);
84     }
85 }