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