]> git.basschouten.com Git - openhab-addons.git/blob
a9e5635140826d1335defac313fe46ad1033e0f7
[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.device.cosem;
14
15 import java.text.ParseException;
16 import java.util.ArrayList;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * Factory for constructing Cosem Objects from Strings
28  *
29  * @author M. Volaart - Initial contribution
30  */
31 @NonNullByDefault
32 public class CosemObjectFactory {
33     private final Logger logger = LoggerFactory.getLogger(CosemObjectFactory.class);
34
35     /**
36      * Lookup cache for fixed OBIS Identifiers
37      */
38     private final Map<OBISIdentifier, CosemObjectType> obisLookupTableFixed = new HashMap<>();
39
40     /**
41      * Lookup cache for fixed OBIS Identifiers that has the same id for different data types
42      */
43     private final Map<OBISIdentifier, List<CosemObjectType>> obisLookupTableMultipleFixed = new HashMap<>();
44
45     /**
46      * Creates a new CosemObjectFactory
47      */
48     public CosemObjectFactory() {
49         /*
50          * Fill lookup tables. There are 3 entities:
51          * - obisLookupTableFixed. This lookup table contains all CosemObjectType with a fixed OBISIdentifier
52          * (i.e. groupA != null && groupB != null && groupC != null).
53          * - obisLookupTableDynamic. This lookup table contains all CosemObjectType with a wildcard OBISIdentifier
54          * (i.e. groupA == null || groupB == null || groupC == null). This lookuptable will be filled
55          * dynamically with unique wildcard OBISIdentifiers when values are received and matches a particular real
56          * device (if the device is changed, this lookupTable must be cleared by removing the corresponding DSMRDevice
57          * Thing from the configuration.)
58          * - obisWildCardCosemTypeList. This is the list of all wild card Cosem Object types. Multiple Cosem Object
59          * Types can have the same wild card OBISIdentifer.
60          *
61          * To facilitate autodiscovery the list has all supported CosemObjectTypes. To improve performance once the
62          * correct OBISIdentifier is discovered for a certain OBISMsgType this is added to the obisLookupTableDynamic.
63          */
64         for (CosemObjectType msgType : CosemObjectType.values()) {
65             if (msgType.obisId.isConflict()) {
66                 obisLookupTableMultipleFixed.computeIfAbsent(msgType.obisId, r -> new ArrayList<>()).add(msgType);
67             } else {
68                 obisLookupTableFixed.put(msgType.obisId, msgType);
69             }
70         }
71     }
72
73     /**
74      * Return Cosem Object from specified string or null if string couldn't be
75      * parsed correctly or no corresponding Cosem Object was found
76      *
77      * @param obisIdString String containing the OBIS message identifier
78      * @param cosemStringValues String containing Cosem values
79      * @return CosemObject or null if parsing failed
80      */
81     public @Nullable CosemObject getCosemObject(String obisIdString, String cosemStringValues) {
82         OBISIdentifier obisId;
83         OBISIdentifier reducedObisId;
84         OBISIdentifier reducedObisIdGroupE;
85
86         try {
87             obisId = new OBISIdentifier(obisIdString);
88             reducedObisId = obisId.getReducedOBISIdentifier();
89             reducedObisIdGroupE = obisId.getReducedOBISIdentifierGroupE();
90         } catch (final ParseException pe) {
91             logger.debug("Received invalid OBIS identifier: {}", obisIdString);
92             return null;
93         }
94
95         logger.trace("Received obisIdString {}, obisId: {}, values: {}", obisIdString, obisId, cosemStringValues);
96
97         CosemObjectType objectType = obisLookupTableFixed.get(reducedObisId);
98         if (objectType != null) {
99             logger.trace("Found obisId {} in the fixed lookup table", reducedObisId);
100             return getCosemObjectInternal(objectType, obisId, cosemStringValues);
101         }
102
103         List<CosemObjectType> objectTypeList = obisLookupTableMultipleFixed.get(reducedObisId);
104         if (objectTypeList != null) {
105             for (CosemObjectType cosemObjectType : objectTypeList) {
106                 CosemObject cosemObject = getCosemObjectInternal(cosemObjectType, obisId, cosemStringValues);
107                 if (cosemObject != null) {
108                     logger.trace("Found obisId {} in the fixed lookup table", reducedObisId);
109                     return cosemObject;
110                 }
111             }
112         }
113
114         objectType = obisLookupTableFixed.get(reducedObisIdGroupE);
115         if (objectType != null) {
116             return getCosemObjectInternal(objectType, obisId, cosemStringValues);
117         }
118
119         logger.debug("Received unknown Cosem Object(OBIS id: {})", obisId);
120
121         return null;
122     }
123
124     /**
125      * Constructs a CosemObject from the given type, OBISIdentifier and the values
126      *
127      * @param cosemObjectType the type of the CosemObject
128      * @param obisIdentifier the actual OBISIdentifier how this cosemObjectType is identified
129      * @param cosemStringValues the values of the CosemObject
130      *
131      * @return a CosemObject or null if parsing failed
132      */
133     private @Nullable CosemObject getCosemObjectInternal(CosemObjectType cosemObjectType, OBISIdentifier obisIdentifier,
134             String cosemStringValues) {
135         CosemObject obj = new CosemObject(cosemObjectType, obisIdentifier);
136
137         try {
138             logger.trace("Parse values for Cosem Object type: {}", cosemObjectType);
139             obj.parseCosemValues(cosemStringValues);
140
141             return obj;
142         } catch (ParseException pe) {
143             logger.trace("Failed to construct Cosem Object for type {}, values: {}", cosemObjectType, cosemStringValues,
144                     pe);
145         }
146         return null;
147     }
148 }