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.Objects;
17 import java.util.regex.Matcher;
18 import java.util.regex.Pattern;
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.eclipse.jdt.annotation.Nullable;
24 * Class representing an OBISIdentifier
26 * @author M. Volaart - Initial contribution
27 * @author Hilbrand Bouwkamp - Simplified, groupF not relevant, and groupB renamed to channel.
30 public class OBISIdentifier {
32 * String representing a-channel:c.d.e.f OBIS ID
34 private static final String OBISID_REGEX = "((\\d+)\\-)?((\\d+):)?((\\d+)\\.)(\\d+)(\\.(\\d+))?(.(\\d+))?";
39 private static final Pattern OBIS_ID_PATTERN = Pattern.compile(OBISID_REGEX);
42 * Value to return when an invalid int was read.
44 private static final int INVALID_INT_READ = -1;
46 /* the six individual group values of the OBIS ID */
47 private final int groupA;
48 private final @Nullable Integer channel;
49 private final int groupC;
50 private final int groupD;
51 private final @Nullable Integer groupE;
52 private final @Nullable Integer groupF;
54 private boolean conflict;
57 * Constructs a new OBIS Identifier (A-x:C.D.E.x)
59 * @param groupA A value
60 * @param groupC C value
61 * @param groupD D value
62 * @param groupE E value
64 public OBISIdentifier(final int groupA, final int groupC, final int groupD, @Nullable final Integer groupE) {
65 this(groupA, groupC, groupD, groupE, false);
69 * Constructs a new OBIS Identifier (A-x:C.D.E.x)
71 * @param groupA A value
72 * @param groupC C value
73 * @param groupD D value
74 * @param groupE E value
75 * @param conflict if true indicates this OBIS Identifier is used for different types of data.
77 public OBISIdentifier(final int groupA, final int groupC, final int groupD, @Nullable final Integer groupE,
78 final boolean conflict) {
85 this.conflict = conflict;
89 * Creates a new {@link OBISIdentifier} of the specified String
91 * @param obisIDString the OBIS String ID
92 * @throws ParseException if obisIDString is not a valid OBIS Identifier
94 public OBISIdentifier(final String obisIDString) throws ParseException {
95 final Matcher m = OBIS_ID_PATTERN.matcher(obisIDString);
99 this.groupA = safeInt(m.group(2));
102 this.channel = safeInteger(m.group(4));
104 // Required value C & D
105 this.groupC = safeInt(m.group(6));
106 this.groupD = safeInt(m.group(7));
109 this.groupE = safeInteger(m.group(9));
112 this.groupF = safeInteger(m.group(11));
114 throw new ParseException("Invalid OBIS identifier:" + obisIDString, 0);
118 private static int safeInt(final @Nullable String value) {
120 return value == null ? INVALID_INT_READ : Integer.parseInt(value);
121 } catch (final NumberFormatException e) {
122 return INVALID_INT_READ;
126 private static @Nullable Integer safeInteger(final @Nullable String value) {
128 return value == null ? null : Integer.valueOf(value);
129 } catch (final NumberFormatException e) {
134 public boolean isConflict() {
141 public int getGroupA() {
146 * @return the M-bus channel
148 public @Nullable Integer getChannel() {
155 public int getGroupC() {
162 public int getGroupD() {
169 public @Nullable Integer getGroupE() {
176 public @Nullable Integer getGroupF() {
181 public String toString() {
182 return groupA + "-" + (channel == null ? "" : (channel + ":")) + groupC + "." + groupD
183 + (groupE == null ? "" : ("." + groupE)) + (groupF == null ? "" : ("*" + groupF));
187 * Returns whether or not both {@link OBISIdentifier} are exact equal (all identifiers match).
189 * If wild card matching is needed (since some fields are null in case of a wildcard) use
190 * {@link #equalsWildCard(OBISIdentifier)} instead
192 * @return true if both OBISIdentifiers match, false otherwise
195 public boolean equals(@Nullable final Object other) {
197 if (other != null && other instanceof OBISIdentifier identifier) {
202 boolean result = true;
204 result &= groupA == o.groupA;
205 if (channel != null && o.channel != null) {
206 result &= (channel.equals(o.channel));
207 } else if (!(channel == null && o.channel == null)) {
210 result &= groupC == o.groupC;
211 result &= groupD == o.groupD;
212 if (groupE != null && o.groupE != null) {
213 result &= groupE.equals(o.groupE);
214 } else if (!(groupE == null && o.groupE == null)) {
217 if (groupF != null && o.groupF != null) {
218 result &= (groupF.equals(o.groupF));
219 } else if (!(groupF == null && o.groupF == null)) {
227 * Checks whether this OBIS Identifier and the other identifier equals taking the wildcards into account
229 * @param o OBISIdentifier to compare to
231 * @return true if identifiers match fully or against a wildcard, false otherwise
233 public boolean equalsWildCard(final OBISIdentifier o) {
234 boolean result = true;
236 result &= groupA == o.groupA;
237 if (channel != null && o.channel != null) {
238 result &= (channel.equals(o.channel));
240 result &= groupC == o.groupC;
241 result &= groupD == o.groupD;
242 if (groupE != null && o.groupE != null) {
243 result &= (groupE.equals(o.groupE));
245 if (groupF != null && o.groupF != null) {
246 result &= (groupF.equals(o.groupF));
253 public int hashCode() {
254 return Objects.hash(groupA, (channel != null ? channel : 0), groupC, groupD, (groupE != null ? groupE : 0),
255 (groupF != null ? groupF : 0));
259 * Returns a reduced OBIS Identifier.
261 * @return reduced OBIS Identifier
263 public OBISIdentifier getReducedOBISIdentifier() {
264 return new OBISIdentifier(groupA, groupC, groupD, groupE);
268 * Returns a reduced OBIS Identifier with group E set to null (.i.e. not applicable)
270 * @return reduced OBIS Identifier
272 public OBISIdentifier getReducedOBISIdentifierGroupE() {
273 return new OBISIdentifier(groupA, groupC, groupD, null);