#### Group Address Notation
```text
-<config>="[<dpt>:][<]<mainGA>[[+[<]<listeningGA>][+[<]<listeningGA>..]]"
+<config>="[<dpt>:][<>]<mainGA>[[+[<]<listeningGA>][+[<]<listeningGA>..]]"
```
where parts in brackets `[]` denote optional information.
+**Each configuration parameter has a `mainGA` where commands are written to and optionally several `listeningGA`s.**
+
+`mainGA` also listens to incoming packets, unless prefixed with a `>` character.
+This is recommended if you have a dedicated status group address which is added as `listeningGA`.
+
The optional `<` sign tells whether the group address of the datapoint accepts read requests on the KNX bus (it does, if the sign is there).
-All group addresses marked with `<` are read by openHAB during startup.
+The group addresses marked with `<` are read by openHAB during startup.
+Future versions might support reading from one GA only.
With `*-control` channels, the state is not owned by any device on the KNX bus, therefore no read requests will be sent by the binding, i.e. `<` signs will be ignored for them.
-Each configuration parameter has a `mainGA` where commands are written to and optionally several `listeningGA`s.
-
-The `dpt` element is optional. If omitted, the corresponding default value will be used (see the channel descriptions above).
+The element `dpt` is highly recommended and may change to a mandatory element in future versions.
+If omitted, the corresponding default value will be used (see the channel descriptions above).
## KNX Secure
/**
* Data structure representing the content of a channel's group address configuration.
*
- * @author Simon Kaufmann - initial contribution and API.
+ * @author Simon Kaufmann - Initial contribution and API
*
*/
@NonNullByDefault
public static final Logger LOGGER = LoggerFactory.getLogger(GroupAddressConfiguration.class);
private static final Pattern PATTERN_GA_CONFIGURATION = Pattern.compile(
- "^((?<dpt>[1-9][0-9]{0,2}\\.[0-9]{3,5}):)?(?<read><)?(?<mainGA>[0-9]{1,5}(/[0-9]{1,4}){0,2})(?<listenGAs>(\\+(<?[0-9]{1,5}(/[0-9]{1,4}){0,2}))*)$");
+ "^((?<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}))*)$");
private static final Pattern PATTERN_LISTEN_GA = Pattern
.compile("\\+((?<read><)?(?<GA>[0-9]{1,5}(/[0-9]{1,4}){0,2}))");
return dpt;
}
+ /**
+ * Returns the main GA, which is the GA to send commands to.
+ */
public GroupAddress getMainGA() {
return mainGA;
}
+ /**
+ * Returns all GAs to listen to.
+ * This includes the main GA (unless disabled by '>'), and additional listening GAs
+ * (those after the "+" symbol).
+ */
public Set<GroupAddress> getListenGAs() {
return listenGAs;
}
+ /**
+ * Returns all GAs to read from.
+ * Those GAs accept read requests to the KNX bus, i.e. they respond to a "GroupValueRead" with a
+ * "GroupValueResponse".
+ * The '<' sign sets a GA as read GA.
+ */
public Set<GroupAddress> getReadGAs() {
return readGAs;
}
String mainGA = matcher.group("mainGA");
try {
GroupAddress groupAddress = new GroupAddress(mainGA);
- listenGAs.add(groupAddress); // also listening to main GA
- if (matcher.group("read") != null) {
- readGAs.add(groupAddress); // also reading main GA
+ @Nullable
+ String modifier = matcher.group("modifier");
+ if (modifier == null) {
+ // default: main GA address writes and listens
+ listenGAs.add(groupAddress);
+ } else if ("<".equals(modifier)) {
+ // configured for read at startup
+ listenGAs.add(groupAddress);
+ readGAs.add(groupAddress);
+ } // else (">").equals(modifier) -> write only, no action
+ if (readGAs.size() > 1) {
+ LOGGER.info(
+ "Item with mainGA {} has more than one GA configured for read at startup, check configuration",
+ groupAddress);
}
return new GroupAddressConfiguration(matcher.group("dpt"), groupAddress, listenGAs, readGAs);
} catch (KNXFormatException e) {
}
} else {
if (value instanceof Command command) {
- logger.trace("processDataReceived postCommand new value '{}' for GA '{}'", asdu, address);
+ logger.trace("processDataReceived postCommand to channel '{}' new value '{}' for GA '{}'",
+ channelUID, asdu, destination);
postCommand(channelUID, command);
}
}
} else {
if (value instanceof State state && !(value instanceof UnDefType)) {
+ logger.trace("processDataReceived updateState to channel '{}' new value '{}' for GA '{}'",
+ knxChannel.getChannelUID(), value, destination);
updateState(knxChannel.getChannelUID(), state);
}
}