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.dsmr.internal.device.cosem;
15 import java.text.ParseException;
16 import java.util.HashMap;
18 import java.util.Map.Entry;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.openhab.core.types.State;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
28 * Class for Cosem Object implementation
30 * @author M. Volaart - Initial contribution
33 public class CosemObject {
36 * Regular expression for finding CosemValues
38 private static final Pattern COSEM_VALUES_PATTERN = Pattern.compile("(\\(([^\\(\\)]*)\\))");
40 private final Logger logger = LoggerFactory.getLogger(CosemObject.class);
45 private final CosemObjectType type;
48 * The actual OBISIdentifier for this CosemObject
50 private final OBISIdentifier obisIdentifier;
53 * List of COSEM value in this message
55 private Map<String, State> cosemValues;
58 * Construct a new CosemObject with the specified OBIS Message Type
61 * {@link CosemObjectType}
63 public CosemObject(CosemObjectType msgType, OBISIdentifier obisIdentifier) {
65 this.obisIdentifier = obisIdentifier;
67 cosemValues = new HashMap<>();
71 * Return the {@link CosemObjectType} for this Cosem Object
73 * @return the {@link CosemObjectType} for this Cosem Object
75 public CosemObjectType getType() {
80 * @return the obisIdentifier
82 public OBISIdentifier getObisIdentifier() {
83 return obisIdentifier;
87 * Returns string representation of this Cosem Object
89 * @return string representation of this Cosem Object
92 public String toString() {
93 return "Cosem Object(type:" + type + ", cosemValues:" + cosemValues + ")";
97 * Returns the Cosem values that are part of this Cosem Object
99 * @return Map of channel keys with state values that are part of this Cosem Object
101 public Map<String, ? extends State> getCosemValues() {
106 * Parses the List of COSEM String value to COSEM objects values.
108 * When the parser has problems it throws a {@link ParseException}. The
109 * already parsed values will still be available. It is up to the caller how
110 * to handle a partially parsed message.
112 * @param cosemValueString the List of COSEM String values
113 * @throws ParseException if parsing fails
115 public void parseCosemValues(String cosemValueString) throws ParseException {
116 logger.trace("Parsing CosemValue string {}", cosemValueString);
118 Matcher cosemValueMatcher = COSEM_VALUES_PATTERN.matcher(cosemValueString);
119 int nrOfCosemValues = countCosemValues(cosemValueMatcher);
121 if (type.supportsNrOfValues(nrOfCosemValues)) {
122 logger.trace("Received items: {} is supported", nrOfCosemValues);
124 int cosemValueItr = 0;
125 while (cosemValueMatcher.find()) {
126 final Entry<String, CosemValueDescriptor<?>> valueDescriptorEntry = type.getDescriptor(cosemValueItr);
127 final State cosemValue = valueDescriptorEntry.getValue().getStateValue(cosemValueMatcher.group(2));
129 if (!cosemValues.containsKey(valueDescriptorEntry.getKey())) {
130 cosemValues.put(valueDescriptorEntry.getKey(), cosemValue);
132 logger.warn("Value for descriptor {} already exists, dropping value {}", valueDescriptorEntry,
138 throw new ParseException(type + " does not support " + nrOfCosemValues + " items", 0);
142 private int countCosemValues(Matcher cosemValueMatcher) {
143 int nrOfCosemValues = 0;
145 while (cosemValueMatcher.find()) {
148 // We need the matcher again, reset to initial state
149 cosemValueMatcher.reset();
150 return nrOfCosemValues;