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.knx.internal.channel;
15 import java.util.HashSet;
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;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
25 import tuwien.auto.calimero.GroupAddress;
26 import tuwien.auto.calimero.KNXFormatException;
29 * Data structure representing the content of a channel's group address configuration.
31 * @author Simon Kaufmann - Initial contribution and API
35 public class GroupAddressConfiguration {
36 public static final Logger LOGGER = LoggerFactory.getLogger(GroupAddressConfiguration.class);
38 private static final Pattern PATTERN_GA_CONFIGURATION = Pattern.compile(
39 "^((?<dpt>[1-9][0-9]{0,2}\\.[0-9]{3,5}):)?(?<modifier>[<>])?(?<mainGA>[0-9]{1,5}(/[0-9]{1,4}){0,2})(?<listenGAs>(\\+(<?[0-9]{1,5}(/[0-9]{1,4}){0,2}))*)$");
40 private static final Pattern PATTERN_LISTEN_GA = Pattern
41 .compile("\\+((?<read><)?(?<GA>[0-9]{1,5}(/[0-9]{1,4}){0,2}))");
43 private final @Nullable String dpt;
44 private final GroupAddress mainGA;
45 private final Set<GroupAddress> listenGAs;
46 private final Set<GroupAddress> readGAs;
48 private GroupAddressConfiguration(@Nullable String dpt, GroupAddress mainGA, Set<GroupAddress> listenGAs,
49 Set<GroupAddress> readGAs) {
52 this.listenGAs = listenGAs;
53 this.readGAs = readGAs;
56 public @Nullable String getDPT() {
61 * Returns the main GA, which is the GA to send commands to.
63 public GroupAddress getMainGA() {
68 * Returns all GAs to listen to.
69 * This includes the main GA (unless disabled by '>'), and additional listening GAs
70 * (those after the "+" symbol).
72 public Set<GroupAddress> getListenGAs() {
77 * Returns all GAs to read from.
78 * Those GAs accept read requests to the KNX bus, i.e. they respond to a "GroupValueRead" with a
79 * "GroupValueResponse".
80 * The '<' sign sets a GA as read GA.
82 public Set<GroupAddress> getReadGAs() {
86 public static @Nullable GroupAddressConfiguration parse(@Nullable Object configuration) {
87 if (!(configuration instanceof String)) {
91 Matcher matcher = PATTERN_GA_CONFIGURATION.matcher(((String) configuration).replace(" ", ""));
92 if (matcher.matches()) {
94 String input = matcher.group("listenGAs");
95 Matcher m2 = PATTERN_LISTEN_GA.matcher(input);
96 Set<GroupAddress> listenGAs = new HashSet<>();
97 Set<GroupAddress> readGAs = new HashSet<>();
99 String ga = m2.group("GA");
101 GroupAddress groupAddress = new GroupAddress(ga);
102 listenGAs.add(groupAddress);
103 if (m2.group("read") != null) {
104 readGAs.add(groupAddress);
106 } catch (KNXFormatException e) {
107 LOGGER.warn("Failed to create GroupAddress from {}", ga);
113 String mainGA = matcher.group("mainGA");
115 GroupAddress groupAddress = new GroupAddress(mainGA);
117 String modifier = matcher.group("modifier");
118 if (modifier == null) {
119 // default: main GA address writes and listens
120 listenGAs.add(groupAddress);
121 } else if ("<".equals(modifier)) {
122 // configured for read at startup
123 listenGAs.add(groupAddress);
124 readGAs.add(groupAddress);
125 } // else (">").equals(modifier) -> write only, no action
126 if (readGAs.size() > 1) {
128 "Item with mainGA {} has more than one GA configured for read at startup, check configuration",
131 return new GroupAddressConfiguration(matcher.group("dpt"), groupAddress, listenGAs, readGAs);
132 } catch (KNXFormatException e) {
133 LOGGER.warn("Failed to create GroupAddress from {}", mainGA);
137 LOGGER.warn("Failed parsing channel configuration '{}'.", configuration);