diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/AbstractSpec.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/AbstractSpec.java
deleted file mode 100644
index 551a3e4135..0000000000
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/AbstractSpec.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- * Copyright (c) 2021 Contributors to the SmartHome/J project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.smarthomej.binding.knx.internal.channel;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-import tuwien.auto.calimero.GroupAddress;
-import tuwien.auto.calimero.KNXFormatException;
-
-/**
- * Base class for telegram meta-data
- *
- * @author Simon Kaufmann - initial contribution and API.
- *
- */
-@NonNullByDefault
-public abstract class AbstractSpec {
-
- private String dpt;
-
- protected AbstractSpec(@Nullable ChannelConfiguration channelConfiguration, String defaultDPT) {
- if (channelConfiguration != null) {
- String configuredDPT = channelConfiguration.getDPT();
- this.dpt = configuredDPT != null ? configuredDPT : defaultDPT;
- } else {
- this.dpt = defaultDPT;
- }
- }
-
- /**
- * Helper method to convert a {@link GroupAddressConfiguration} into a {@link GroupAddress}.
- *
- * @param ga the group address configuration
- * @return a group address object
- */
- protected final GroupAddress toGroupAddress(GroupAddressConfiguration ga) {
- try {
- return new GroupAddress(ga.getGA());
- } catch (KNXFormatException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Return the data point type.
- *
- * See {@link org.smarthomej.binding.knx.internal.client.InboundSpec#getDPT()} and
- * {@link org.smarthomej.binding.knx.internal.client.OutboundSpec#getDPT()}.
- *
- * @return the data point type.
- */
- public final String getDPT() {
- return dpt;
- }
-}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ChannelConfiguration.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ChannelConfiguration.java
deleted file mode 100644
index ea0dfe01e6..0000000000
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ChannelConfiguration.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- * Copyright (c) 2021 Contributors to the SmartHome/J project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.smarthomej.binding.knx.internal.channel;
-
-import static java.util.stream.Collectors.toList;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-
-/**
- * Data structure representing the content of a channel's group address configuration.
- *
- * @author Simon Kaufmann - initial contribution and API.
- *
- */
-@NonNullByDefault
-public class ChannelConfiguration {
-
- private final @Nullable String dpt;
- private final GroupAddressConfiguration mainGA;
- private final List listenGAs;
-
- public ChannelConfiguration(@Nullable String dpt, GroupAddressConfiguration mainGA,
- List listenGAs) {
- this.dpt = dpt;
- this.mainGA = mainGA;
- this.listenGAs = listenGAs;
- }
-
- public @Nullable String getDPT() {
- return dpt;
- }
-
- public GroupAddressConfiguration getMainGA() {
- return mainGA;
- }
-
- public List getListenGAs() {
- return Stream.concat(Stream.of(mainGA), listenGAs.stream()).collect(toList());
- }
-
- public List getReadGAs() {
- return getListenGAs().stream().filter(ga -> ga.isRead()).collect(toList());
- }
-}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/GroupAddressConfiguration.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/GroupAddressConfiguration.java
index 67653d35a8..055e7da676 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/GroupAddressConfiguration.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/GroupAddressConfiguration.java
@@ -13,41 +13,107 @@
*/
package org.smarthomej.binding.knx.internal.channel;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import tuwien.auto.calimero.GroupAddress;
+import tuwien.auto.calimero.KNXFormatException;
/**
- * Data structure representing a single group address configuration within a channel configuration parameter.
+ * Data structure representing the content of a channel's group address configuration.
*
* @author Simon Kaufmann - initial contribution and API.
*
*/
@NonNullByDefault
public class GroupAddressConfiguration {
+ public static final Logger LOGGER = LoggerFactory.getLogger(GroupAddressConfiguration.class);
+
+ private static final Pattern PATTERN_GA_CONFIGURATION = Pattern.compile(
+ "^((?[1-9][0-9]{0,2}\\.[0-9]{3,4}):)?(?\\<)?(?[0-9]{1,5}(/[0-9]{1,4}){0,2})(?(\\+(\\[0-9]{1,5}(/[0-9]{1,4}){0,2}))*)$");
+ private static final Pattern PATTERN_LISTEN_GA = Pattern
+ .compile("\\+((?\\<)?(?[0-9]{1,5}(/[0-9]{1,4}){0,2}))");
+
+ private final @Nullable String dpt;
+ private final GroupAddress mainGA;
+ private final Set listenGAs;
+ private final Set readGAs;
- private final String ga;
- private final boolean read;
+ private GroupAddressConfiguration(@Nullable String dpt, GroupAddress mainGA, Set listenGAs,
+ Set readGAs) {
+ this.dpt = dpt;
+ this.mainGA = mainGA;
+ this.listenGAs = listenGAs;
+ this.readGAs = readGAs;
+ }
+
+ public @Nullable String getDPT() {
+ return dpt;
+ }
- public GroupAddressConfiguration(String ga, boolean read) {
- super();
- this.ga = ga;
- this.read = read;
+ public GroupAddress getMainGA() {
+ return mainGA;
}
- /**
- * The group address.
- *
- * @return the group address.
- */
- public String getGA() {
- return ga;
+ public Set getListenGAs() {
+ return listenGAs;
}
- /**
- * Denotes whether the group address is marked to be actively read from.
- *
- * @return {@code true} if read requests should be issued to this address
- */
- public boolean isRead() {
- return read;
+ public Set getReadGAs() {
+ return readGAs;
+ }
+
+ public static @Nullable GroupAddressConfiguration parse(@Nullable Object configuration) {
+ if (!(configuration instanceof String)) {
+ return null;
+ }
+
+ Matcher matcher = PATTERN_GA_CONFIGURATION.matcher(((String) configuration).replace(" ", ""));
+ if (matcher.matches()) {
+ // Listen GAs
+ String input = matcher.group("listenGAs");
+ Matcher m2 = PATTERN_LISTEN_GA.matcher(input);
+ Set listenGAs = new HashSet<>();
+ Set readGAs = new HashSet<>();
+ while (m2.find()) {
+ String ga = m2.group("GA");
+ try {
+ GroupAddress groupAddress = new GroupAddress(ga);
+ listenGAs.add(groupAddress);
+ if (m2.group("read") != null) {
+ readGAs.add(groupAddress);
+ }
+ } catch (KNXFormatException e) {
+ LOGGER.warn("Failed to create GroupAddress from {}", ga);
+ return null;
+ }
+ }
+
+ // Main GA
+ 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
+ }
+ return new GroupAddressConfiguration(matcher.group("dpt"), groupAddress, listenGAs, readGAs);
+ } catch (KNXFormatException e) {
+ LOGGER.warn("Failed to create GroupAddress from {}", mainGA);
+ return null;
+ }
+
+ } else {
+ LOGGER.warn("Failed parsing channel configuration '{}'.", configuration);
+ }
+
+ return null;
}
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannel.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannel.java
new file mode 100644
index 0000000000..6b54548d9d
--- /dev/null
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannel.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ * Copyright (c) 2021 Contributors to the SmartHome/J project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.smarthomej.binding.knx.internal.channel;
+
+import static java.util.stream.Collectors.*;
+import static org.smarthomej.binding.knx.internal.KNXBindingConstants.CONTROL_CHANNEL_TYPES;
+import static org.smarthomej.binding.knx.internal.KNXBindingConstants.GA;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.openhab.core.config.core.Configuration;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.ChannelUID;
+import org.openhab.core.types.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.smarthomej.binding.knx.internal.client.InboundSpec;
+import org.smarthomej.binding.knx.internal.client.OutboundSpec;
+import org.smarthomej.binding.knx.internal.dpt.KNXCoreTypeMapper;
+
+import tuwien.auto.calimero.GroupAddress;
+
+/**
+ * Meta-data abstraction for the KNX channel configurations.
+ *
+ * @author Simon Kaufmann - initial contribution and API
+ * @author Jan N. Klug - refactored from type definition to channel instance
+ *
+ */
+@NonNullByDefault
+public abstract class KNXChannel {
+ private final Logger logger = LoggerFactory.getLogger(KNXChannel.class);
+ private final Set gaKeys;
+
+ private final Map groupAddressConfigurations = new HashMap<>();
+ private final Set listenAddresses = new HashSet<>();
+ private final Set writeAddresses = new HashSet<>();
+ private final String channelType;
+ private final ChannelUID channelUID;
+ private final boolean isControl;
+
+ KNXChannel(Channel channel) {
+ this(Set.of(GA), channel);
+ }
+
+ KNXChannel(Set gaKeys, Channel channel) {
+ this.gaKeys = gaKeys;
+
+ // this is safe because we already checked the presence of the ChannelTypeUID before
+ this.channelType = Objects.requireNonNull(channel.getChannelTypeUID()).getId();
+ this.channelUID = channel.getUID();
+ this.isControl = CONTROL_CHANNEL_TYPES.contains(channelType);
+
+ // build map of ChannelConfigurations and GA lists
+ Configuration configuration = channel.getConfiguration();
+ gaKeys.forEach(key -> {
+ GroupAddressConfiguration groupAddressConfiguration = GroupAddressConfiguration
+ .parse(configuration.get(key));
+ if (groupAddressConfiguration != null) {
+ groupAddressConfigurations.put(key, groupAddressConfiguration);
+ // store address configuration for re-use
+ listenAddresses.addAll(groupAddressConfiguration.getListenGAs());
+ writeAddresses.add(groupAddressConfiguration.getMainGA());
+ }
+ });
+ }
+
+ public String getChannelType() {
+ return channelType;
+ }
+
+ public ChannelUID getChannelUID() {
+ return channelUID;
+ }
+
+ public boolean isControl() {
+ return isControl;
+ }
+
+ public final Set getAllGroupAddresses() {
+ return listenAddresses;
+ }
+
+ public final Set getWriteAddresses() {
+ return writeAddresses;
+ }
+
+ public final @Nullable OutboundSpec getCommandSpec(Type command) {
+ logger.trace("getCommandSpec checking keys '{}' for command '{}' ({})", gaKeys, command, command.getClass());
+ for (Map.Entry entry : groupAddressConfigurations.entrySet()) {
+ String dpt = Objects.requireNonNullElse(entry.getValue().getDPT(), getDefaultDPT(entry.getKey()));
+ Set> expectedTypeClass = KNXCoreTypeMapper.getAllowedTypes(dpt);
+ if (expectedTypeClass.contains(command.getClass())) {
+ logger.trace("getCommandSpec key '{}' has expectedTypeClass '{}', matching command '{}' and dpt '{}'",
+ entry.getKey(), expectedTypeClass, command, dpt);
+ return new WriteSpecImpl(entry.getValue(), dpt, command);
+ }
+ }
+ logger.trace("getCommandSpec no Spec found!");
+ return null;
+ }
+
+ public final List getReadSpec() {
+ return groupAddressConfigurations.entrySet().stream()
+ .map(entry -> new ReadRequestSpecImpl(entry.getValue(), getDefaultDPT(entry.getKey())))
+ .filter(spec -> !spec.getGroupAddresses().isEmpty()).collect(toList());
+ }
+
+ public final @Nullable InboundSpec getListenSpec(GroupAddress groupAddress) {
+ return groupAddressConfigurations.entrySet().stream()
+ .map(entry -> new ListenSpecImpl(entry.getValue(), getDefaultDPT(entry.getKey())))
+ .filter(spec -> spec.getGroupAddresses().contains(groupAddress)).findFirst().orElse(null);
+ }
+
+ public final @Nullable OutboundSpec getResponseSpec(GroupAddress groupAddress, Type value) {
+ return groupAddressConfigurations.entrySet().stream()
+ .map(entry -> new ReadResponseSpecImpl(entry.getValue(), getDefaultDPT(entry.getKey()), value))
+ .filter(spec -> spec.matchesDestination(groupAddress)).findFirst().orElse(null);
+ }
+
+ protected abstract String getDefaultDPT(String gaConfigKey);
+}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelFactory.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelFactory.java
new file mode 100644
index 0000000000..f57c0b12b9
--- /dev/null
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelFactory.java
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2010-2021 Contributors to the openHAB project
+ * Copyright (c) 2021 Contributors to the SmartHome/J project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.smarthomej.binding.knx.internal.channel;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.type.ChannelTypeUID;
+
+/**
+ * Helper class to find the matching {@link KNXChannel} for any given {@link ChannelTypeUID}.
+ *
+ * @author Simon Kaufmann - initial contribution and API
+ * @author Jan N. Klug - refactored ro factory class
+ *
+ */
+@NonNullByDefault
+public final class KNXChannelFactory {
+
+ private static final Map, Function> TYPES = Map.ofEntries( //
+ Map.entry(TypeColor.SUPPORTED_CHANNEL_TYPES, TypeColor::new), //
+ Map.entry(TypeContact.SUPPORTED_CHANNEL_TYPES, TypeContact::new), //
+ Map.entry(TypeDateTime.SUPPORTED_CHANNEL_TYPES, TypeDateTime::new), //
+ Map.entry(TypeDimmer.SUPPORTED_CHANNEL_TYPES, TypeDimmer::new), //
+ Map.entry(TypeNumber.SUPPORTED_CHANNEL_TYPES, TypeNumber::new), //
+ Map.entry(TypeRollershutter.SUPPORTED_CHANNEL_TYPES, TypeRollershutter::new), //
+ Map.entry(TypeString.SUPPORTED_CHANNEL_TYPES, TypeString::new), //
+ Map.entry(TypeSwitch.SUPPORTED_CHANNEL_TYPES, TypeSwitch::new));
+
+ private KNXChannelFactory() {
+ // prevent instantiation
+ }
+
+ public static KNXChannel createKnxChannel(Channel channel) throws IllegalArgumentException {
+ ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
+ if (channelTypeUID == null) {
+ throw new IllegalArgumentException("Could not determine ChannelTypeUID for channel " + channel.getUID());
+ }
+
+ String channelType = channelTypeUID.getId();
+
+ Function supplier = TYPES.entrySet().stream().filter(e -> e.getKey().contains(channelType))
+ .map(Map.Entry::getValue).findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(channelTypeUID + " is not a valid channel type ID"));
+
+ KNXChannel knxChannel = supplier.apply(channel);
+
+ return knxChannel;
+ }
+}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelType.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelType.java
deleted file mode 100644
index 7484a80074..0000000000
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelType.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- * Copyright (c) 2021 Contributors to the SmartHome/J project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.smarthomej.binding.knx.internal.channel;
-
-import static java.util.stream.Collectors.*;
-import static org.smarthomej.binding.knx.internal.KNXBindingConstants.GA;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
-import org.openhab.core.config.core.Configuration;
-import org.openhab.core.types.Type;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.smarthomej.binding.knx.internal.client.InboundSpec;
-import org.smarthomej.binding.knx.internal.client.OutboundSpec;
-import org.smarthomej.binding.knx.internal.dpt.KNXCoreTypeMapper;
-
-import tuwien.auto.calimero.GroupAddress;
-import tuwien.auto.calimero.KNXFormatException;
-
-/**
- * Meta-data abstraction for the KNX channel configurations.
- *
- * @author Simon Kaufmann - initial contribution and API.
- *
- */
-@NonNullByDefault
-public abstract class KNXChannelType {
-
- private static final Pattern PATTERN = Pattern.compile(
- "^((?[1-9][0-9]{0,2}\\.[0-9]{3,4}):)?(?\\<)?(?[0-9]{1,5}(/[0-9]{1,4}){0,2})(?(\\+(\\[0-9]{1,5}(/[0-9]{1,4}){0,2}))*)$");
-
- private static final Pattern PATTERN_LISTEN = Pattern
- .compile("\\+((?\\<)?(?[0-9]{1,5}(/[0-9]{1,4}){0,2}))");
-
- private final Logger logger = LoggerFactory.getLogger(KNXChannelType.class);
- private final Set channelTypeIDs;
- private final Set gaKeys;
-
- KNXChannelType(String... channelTypeIDs) {
- this(Set.of(GA), channelTypeIDs);
- }
-
- KNXChannelType(Set gaKeys, String... channelTypeIDs) {
- this.gaKeys = gaKeys;
- this.channelTypeIDs = Set.of(channelTypeIDs);
- }
-
- final Set getChannelIDs() {
- return channelTypeIDs;
- }
-
- @Nullable
- protected final ChannelConfiguration parse(@Nullable Object fancy) {
- if (!(fancy instanceof String)) {
- return null;
- }
- Matcher matcher = PATTERN.matcher(((String) fancy).replace(" ", ""));
-
- if (matcher.matches()) {
- // Listen GAs
- String input = matcher.group("listenGAs");
- Matcher m2 = PATTERN_LISTEN.matcher(input);
- List listenGAs = new LinkedList<>();
- while (m2.find()) {
- listenGAs.add(new GroupAddressConfiguration(m2.group("GA"), m2.group("read") != null));
- }
-
- // Main GA
- GroupAddressConfiguration mainGA = new GroupAddressConfiguration(matcher.group("mainGA"),
- matcher.group("read") != null);
-
- return new ChannelConfiguration(matcher.group("dpt"), mainGA, listenGAs);
- } else {
- logger.warn("Failed parsing channel configuration '{}'.", fancy);
- }
-
- return null;
- }
-
- private Set filterGroupAddresses(Configuration channelConfiguration,
- Function> filter) {
- return gaKeys.stream().map(channelConfiguration::get).map(this::parse).filter(Objects::nonNull)
- .map(Objects::requireNonNull).map(filter).flatMap(List::stream).map(this::toGroupAddress)
- .flatMap(Optional::stream).collect(Collectors.toSet());
- }
-
- public final Set getAllGroupAddresses(Configuration channelConfiguration) {
- return filterGroupAddresses(channelConfiguration, ChannelConfiguration::getListenGAs);
- }
-
- public final Set getWriteAddresses(Configuration channelConfiguration) {
- return filterGroupAddresses(channelConfiguration, configuration -> List.of(configuration.getMainGA()));
- }
-
- private Optional toGroupAddress(GroupAddressConfiguration ga) {
- try {
- return Optional.of(new GroupAddress(ga.getGA()));
- } catch (KNXFormatException e) {
- logger.warn("Could not parse group address '{}'", ga.getGA());
- }
- return Optional.empty();
- }
-
- public final @Nullable OutboundSpec getCommandSpec(Configuration configuration, Type command)
- throws KNXFormatException {
- logger.trace("getCommandSpec checking keys '{}' for command '{}' ({})", gaKeys, command, command.getClass());
- for (String key : gaKeys) {
- ChannelConfiguration config = parse(configuration.get(key));
- if (config != null) {
- String dpt = Objects.requireNonNullElse(config.getDPT(), getDefaultDPT(key));
- Set> expectedTypeClass = KNXCoreTypeMapper.getAllowedTypes(dpt);
- if (expectedTypeClass.contains(command.getClass())) {
- logger.trace(
- "getCommandSpec key '{}' has expectedTypeClass '{}', matching command '{}' and dpt '{}'",
- key, expectedTypeClass, command, dpt);
- return new WriteSpecImpl(config, dpt, command);
- }
- }
- }
- logger.trace("getCommandSpec no Spec found!");
- return null;
- }
-
- public final List getReadSpec(Configuration configuration) throws KNXFormatException {
- return gaKeys.stream().map(key -> new ReadRequestSpecImpl(parse(configuration.get(key)), getDefaultDPT(key)))
- .filter(spec -> !spec.getGroupAddresses().isEmpty()).collect(toList());
- }
-
- public final @Nullable InboundSpec getListenSpec(Configuration configuration, GroupAddress groupAddress) {
- return gaKeys.stream().map(key -> new ListenSpecImpl(parse(configuration.get(key)), getDefaultDPT(key)))
- .filter(spec -> !spec.getGroupAddresses().isEmpty())
- .filter(spec -> spec.getGroupAddresses().contains(groupAddress)).findFirst().orElse(null);
- }
-
- public final @Nullable OutboundSpec getResponseSpec(Configuration configuration, GroupAddress groupAddress,
- Type value) {
- return gaKeys.stream()
- .map(key -> new ReadResponseSpecImpl(parse(configuration.get(key)), getDefaultDPT(key), value))
- .filter(spec -> spec.matchesDestination(groupAddress)).findFirst().orElse(null);
- }
-
- protected abstract String getDefaultDPT(String gaConfigKey);
-
- @Override
- public String toString() {
- return channelTypeIDs.toString();
- }
-}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypes.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypes.java
deleted file mode 100644
index f231172509..0000000000
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypes.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Copyright (c) 2010-2021 Contributors to the openHAB project
- * Copyright (c) 2021 Contributors to the SmartHome/J project
- *
- * See the NOTICE file(s) distributed with this work for additional
- * information.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License 2.0 which is available at
- * http://www.eclipse.org/legal/epl-2.0
- *
- * SPDX-License-Identifier: EPL-2.0
- */
-package org.smarthomej.binding.knx.internal.channel;
-
-import java.util.Set;
-
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.thing.Channel;
-import org.openhab.core.thing.type.ChannelTypeUID;
-
-/**
- * Helper class to find the matching {@link KNXChannelType} for any given {@link ChannelTypeUID}.
- *
- * @author Simon Kaufmann - initial contribution and API.
- *
- */
-@NonNullByDefault
-public final class KNXChannelTypes {
-
- private static final Set TYPES = Set.of(//
- new TypeColor(), //
- new TypeContact(), //
- new TypeDateTime(), //
- new TypeDimmer(), //
- new TypeNumber(), //
- new TypeRollershutter(), //
- new TypeString(), //
- new TypeSwitch() //
- );
-
- private KNXChannelTypes() {
- // prevent instantiation
- }
-
- public static KNXChannelType getKnxChannelType(Channel channel) throws IllegalArgumentException {
- ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
- if (channelTypeUID == null) {
- throw new IllegalArgumentException("Could not determine ChannelTypeUID for channel " + channel.getUID());
- }
-
- for (KNXChannelType c : TYPES) {
- if (c.getChannelIDs().contains(channelTypeUID.getId())) {
- return c;
- }
- }
- throw new IllegalArgumentException(channelTypeUID.getId() + " is not a valid value channel type ID");
- }
-}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ListenSpecImpl.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ListenSpecImpl.java
index e4a36e9986..48a1e7bea5 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ListenSpecImpl.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ListenSpecImpl.java
@@ -13,13 +13,10 @@
*/
package org.smarthomej.binding.knx.internal.channel;
-import static java.util.stream.Collectors.toList;
-
-import java.util.Collections;
-import java.util.List;
+import java.util.Objects;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.smarthomej.binding.knx.internal.client.InboundSpec;
import tuwien.auto.calimero.GroupAddress;
@@ -31,21 +28,22 @@
*
*/
@NonNullByDefault
-public class ListenSpecImpl extends AbstractSpec implements InboundSpec {
+public class ListenSpecImpl implements InboundSpec {
+ private final String dpt;
+ private final Set listenAddresses;
- private final List listenAddresses;
+ public ListenSpecImpl(GroupAddressConfiguration groupAddressConfiguration, String defaultDPT) {
+ this.dpt = Objects.requireNonNullElse(groupAddressConfiguration.getDPT(), defaultDPT);
+ this.listenAddresses = groupAddressConfiguration.getListenGAs();
+ }
- public ListenSpecImpl(@Nullable ChannelConfiguration channelConfiguration, String defaultDPT) {
- super(channelConfiguration, defaultDPT);
- if (channelConfiguration != null) {
- this.listenAddresses = channelConfiguration.getListenGAs().stream().map(this::toGroupAddress)
- .collect(toList());
- } else {
- this.listenAddresses = Collections.emptyList();
- }
+ @Override
+ public String getDPT() {
+ return dpt;
}
- public List getGroupAddresses() {
+ @Override
+ public Set getGroupAddresses() {
return listenAddresses;
}
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadRequestSpecImpl.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadRequestSpecImpl.java
index 20a0a6956e..103aa74982 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadRequestSpecImpl.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadRequestSpecImpl.java
@@ -13,13 +13,10 @@
*/
package org.smarthomej.binding.knx.internal.channel;
-import static java.util.stream.Collectors.toList;
-
-import java.util.Collections;
-import java.util.List;
+import java.util.Objects;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.smarthomej.binding.knx.internal.client.InboundSpec;
import tuwien.auto.calimero.GroupAddress;
@@ -31,21 +28,22 @@
*
*/
@NonNullByDefault
-public class ReadRequestSpecImpl extends AbstractSpec implements InboundSpec {
+public class ReadRequestSpecImpl implements InboundSpec {
+ private final String dpt;
+ private final Set readAddresses;
- private final List readAddresses;
+ public ReadRequestSpecImpl(GroupAddressConfiguration groupAddressConfiguration, String defaultDPT) {
+ this.dpt = Objects.requireNonNullElse(groupAddressConfiguration.getDPT(), defaultDPT);
+ this.readAddresses = groupAddressConfiguration.getReadGAs();
+ }
- public ReadRequestSpecImpl(@Nullable ChannelConfiguration channelConfiguration, String defaultDPT) {
- super(channelConfiguration, defaultDPT);
- if (channelConfiguration != null) {
- this.readAddresses = channelConfiguration.getReadGAs().stream().map(this::toGroupAddress).collect(toList());
- } else {
- this.readAddresses = Collections.emptyList();
- }
+ @Override
+ public String getDPT() {
+ return dpt;
}
@Override
- public List getGroupAddresses() {
+ public Set getGroupAddresses() {
return readAddresses;
}
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadResponseSpecImpl.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadResponseSpecImpl.java
index 5f5aebca13..aefa0d100d 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadResponseSpecImpl.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/ReadResponseSpecImpl.java
@@ -13,8 +13,9 @@
*/
package org.smarthomej.binding.knx.internal.channel;
+import java.util.Objects;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.Type;
import org.smarthomej.binding.knx.internal.client.OutboundSpec;
@@ -27,23 +28,24 @@
*
*/
@NonNullByDefault
-public class ReadResponseSpecImpl extends AbstractSpec implements OutboundSpec {
-
- private final @Nullable GroupAddress groupAddress;
+public class ReadResponseSpecImpl implements OutboundSpec {
+ private final String dpt;
+ private final GroupAddress groupAddress;
private final Type value;
- public ReadResponseSpecImpl(@Nullable ChannelConfiguration channelConfiguration, String defaultDPT, Type state) {
- super(channelConfiguration, defaultDPT);
- if (channelConfiguration != null) {
- this.groupAddress = toGroupAddress(channelConfiguration.getMainGA());
- } else {
- this.groupAddress = null;
- }
+ public ReadResponseSpecImpl(GroupAddressConfiguration groupAddressConfiguration, String defaultDPT, Type state) {
+ this.dpt = Objects.requireNonNullElse(groupAddressConfiguration.getDPT(), defaultDPT);
+ this.groupAddress = groupAddressConfiguration.getMainGA();
this.value = state;
}
@Override
- public @Nullable GroupAddress getGroupAddress() {
+ public String getDPT() {
+ return dpt;
+ }
+
+ @Override
+ public GroupAddress getGroupAddress() {
return groupAddress;
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeColor.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeColor.java
index 33d16f0548..8cb2777ac0 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeColor.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeColor.java
@@ -18,6 +18,7 @@
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlator3BitControlled;
import tuwien.auto.calimero.dptxlator.DPTXlator8BitUnsigned;
@@ -31,10 +32,11 @@
*
*/
@NonNullByDefault
-class TypeColor extends KNXChannelType {
+class TypeColor extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_COLOR, CHANNEL_COLOR_CONTROL);
- TypeColor() {
- super(Set.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA, HSB_GA), CHANNEL_COLOR, CHANNEL_COLOR_CONTROL);
+ TypeColor(Channel channel) {
+ super(Set.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA, HSB_GA), channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeContact.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeContact.java
index 96caf014a3..d3360f1530 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeContact.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeContact.java
@@ -15,7 +15,10 @@
import static org.smarthomej.binding.knx.internal.KNXBindingConstants.*;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlatorBoolean;
@@ -26,10 +29,11 @@
*
*/
@NonNullByDefault
-class TypeContact extends KNXChannelType {
+class TypeContact extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_CONTACT, CHANNEL_CONTACT_CONTROL);
- TypeContact() {
- super(CHANNEL_CONTACT, CHANNEL_CONTACT_CONTROL);
+ TypeContact(Channel channel) {
+ super(channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDateTime.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDateTime.java
index baad286d7b..2896d774a9 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDateTime.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDateTime.java
@@ -15,7 +15,10 @@
import static org.smarthomej.binding.knx.internal.KNXBindingConstants.*;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlatorDateTime;
@@ -26,10 +29,11 @@
*
*/
@NonNullByDefault
-class TypeDateTime extends KNXChannelType {
+class TypeDateTime extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_DATETIME, CHANNEL_DATETIME_CONTROL);
- TypeDateTime() {
- super(CHANNEL_DATETIME, CHANNEL_DATETIME_CONTROL);
+ TypeDateTime(Channel channel) {
+ super(channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDimmer.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDimmer.java
index ec09834394..c3a124ebf0 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDimmer.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeDimmer.java
@@ -19,6 +19,7 @@
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlator3BitControlled;
import tuwien.auto.calimero.dptxlator.DPTXlator8BitUnsigned;
@@ -31,10 +32,11 @@
*
*/
@NonNullByDefault
-class TypeDimmer extends KNXChannelType {
+class TypeDimmer extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_DIMMER, CHANNEL_DIMMER_CONTROL);
- TypeDimmer() {
- super(Set.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA), CHANNEL_DIMMER, CHANNEL_DIMMER_CONTROL);
+ TypeDimmer(Channel channel) {
+ super(Set.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA), channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeNumber.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeNumber.java
index 1b176b9a53..60b9b7de7c 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeNumber.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeNumber.java
@@ -15,7 +15,10 @@
import static org.smarthomej.binding.knx.internal.KNXBindingConstants.*;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
/**
* number channel type description
@@ -24,10 +27,11 @@
*
*/
@NonNullByDefault
-class TypeNumber extends KNXChannelType {
+class TypeNumber extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_NUMBER, CHANNEL_NUMBER_CONTROL);
- TypeNumber() {
- super(CHANNEL_NUMBER, CHANNEL_NUMBER_CONTROL);
+ TypeNumber(Channel channel) {
+ super(channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeRollershutter.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeRollershutter.java
index bd43d5b966..3b16a895d9 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeRollershutter.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeRollershutter.java
@@ -19,6 +19,7 @@
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlator8BitUnsigned;
import tuwien.auto.calimero.dptxlator.DPTXlatorBoolean;
@@ -30,10 +31,12 @@
*
*/
@NonNullByDefault
-class TypeRollershutter extends KNXChannelType {
+class TypeRollershutter extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_ROLLERSHUTTER,
+ CHANNEL_ROLLERSHUTTER_CONTROL);
- TypeRollershutter() {
- super(Set.of(UP_DOWN_GA, STOP_MOVE_GA, POSITION_GA), CHANNEL_ROLLERSHUTTER, CHANNEL_ROLLERSHUTTER_CONTROL);
+ TypeRollershutter(Channel channel) {
+ super(Set.of(UP_DOWN_GA, STOP_MOVE_GA, POSITION_GA), channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeString.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeString.java
index 19f98cf833..873c56e1ac 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeString.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeString.java
@@ -15,7 +15,10 @@
import static org.smarthomej.binding.knx.internal.KNXBindingConstants.*;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlatorString;
@@ -26,10 +29,11 @@
*
*/
@NonNullByDefault
-class TypeString extends KNXChannelType {
+class TypeString extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_STRING, CHANNEL_STRING_CONTROL);
- TypeString() {
- super(CHANNEL_STRING, CHANNEL_STRING_CONTROL);
+ TypeString(Channel channel) {
+ super(channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeSwitch.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeSwitch.java
index 30aab99f51..b10932d7e7 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeSwitch.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/TypeSwitch.java
@@ -15,7 +15,10 @@
import static org.smarthomej.binding.knx.internal.KNXBindingConstants.*;
+import java.util.Set;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.openhab.core.thing.Channel;
import tuwien.auto.calimero.dptxlator.DPTXlatorBoolean;
@@ -26,10 +29,11 @@
*
*/
@NonNullByDefault
-class TypeSwitch extends KNXChannelType {
+class TypeSwitch extends KNXChannel {
+ public static final Set SUPPORTED_CHANNEL_TYPES = Set.of(CHANNEL_SWITCH, CHANNEL_SWITCH_CONTROL);
- TypeSwitch() {
- super(CHANNEL_SWITCH, CHANNEL_SWITCH_CONTROL);
+ TypeSwitch(Channel channel) {
+ super(channel);
}
@Override
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/WriteSpecImpl.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/WriteSpecImpl.java
index 3e01278f25..4eb193f845 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/WriteSpecImpl.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/channel/WriteSpecImpl.java
@@ -13,13 +13,13 @@
*/
package org.smarthomej.binding.knx.internal.channel;
+import java.util.Objects;
+
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.Type;
import org.smarthomej.binding.knx.internal.client.OutboundSpec;
import tuwien.auto.calimero.GroupAddress;
-import tuwien.auto.calimero.KNXFormatException;
/**
* Command meta-data
@@ -28,29 +28,29 @@
*
*/
@NonNullByDefault
-public class WriteSpecImpl extends AbstractSpec implements OutboundSpec {
-
+public class WriteSpecImpl implements OutboundSpec {
+ private String dpt;
private final Type value;
- private final @Nullable GroupAddress groupAddress;
-
- public WriteSpecImpl(@Nullable ChannelConfiguration channelConfiguration, String defaultDPT, Type value)
- throws KNXFormatException {
- super(channelConfiguration, defaultDPT);
- if (channelConfiguration != null) {
- this.groupAddress = new GroupAddress(channelConfiguration.getMainGA().getGA());
- } else {
- this.groupAddress = null;
- }
+ private final GroupAddress groupAddress;
+
+ public WriteSpecImpl(GroupAddressConfiguration groupAddressConfiguration, String defaultDPT, Type value) {
+ this.dpt = Objects.requireNonNullElse(groupAddressConfiguration.getDPT(), defaultDPT);
+ this.groupAddress = groupAddressConfiguration.getMainGA();
this.value = value;
}
+ @Override
+ public String getDPT() {
+ return dpt;
+ }
+
@Override
public Type getValue() {
return value;
}
@Override
- public @Nullable GroupAddress getGroupAddress() {
+ public GroupAddress getGroupAddress() {
return groupAddress;
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java
index 037b13b47e..46eaba2e09 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java
@@ -285,7 +285,6 @@ private void readNextQueuedDatapoint() {
}
} catch (InterruptedException e) {
logger.debug("Interrupted sending KNX read request");
- return;
}
}
}
@@ -395,7 +394,7 @@ public void writeToKNX(OutboundSpec commandSpec) throws KNXException {
ProcessCommunicator processCommunicator = this.processCommunicator;
KNXNetworkLink link = this.link;
if (processCommunicator == null || link == null) {
- logger.debug("Cannot write to the KNX bus (processCommuicator: {}, link: {})",
+ logger.debug("Cannot write to the KNX bus (processCommunicator: {}, link: {})",
processCommunicator == null ? "Not OK" : "OK",
link == null ? "Not OK" : (link.isOpen() ? "Open" : "Closed"));
return;
@@ -404,9 +403,7 @@ public void writeToKNX(OutboundSpec commandSpec) throws KNXException {
logger.trace("writeToKNX groupAddress '{}', commandSpec '{}'", groupAddress, commandSpec);
- if (groupAddress != null) {
- sendToKNX(processCommunicator, link, groupAddress, commandSpec.getDPT(), commandSpec.getValue());
- }
+ sendToKNX(processCommunicator, link, groupAddress, commandSpec.getDPT(), commandSpec.getValue());
}
@Override
@@ -423,9 +420,7 @@ public void respondToKNX(OutboundSpec responseSpec) throws KNXException {
logger.trace("respondToKNX groupAddress '{}', responseSpec '{}'", groupAddress, responseSpec);
- if (groupAddress != null) {
- sendToKNX(responseCommunicator, link, groupAddress, responseSpec.getDPT(), responseSpec.getValue());
- }
+ sendToKNX(responseCommunicator, link, groupAddress, responseSpec.getDPT(), responseSpec.getValue());
}
private void sendToKNX(ProcessCommunication communicator, KNXNetworkLink link, GroupAddress groupAddress,
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/InboundSpec.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/InboundSpec.java
index da38f7bc1f..243eebbf6f 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/InboundSpec.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/InboundSpec.java
@@ -13,7 +13,7 @@
*/
package org.smarthomej.binding.knx.internal.client;
-import java.util.List;
+import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
@@ -40,5 +40,5 @@ public interface InboundSpec {
*
* @return a list of group addresses.
*/
- List getGroupAddresses();
+ Set getGroupAddresses();
}
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/OutboundSpec.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/OutboundSpec.java
index 83d5e920b1..02c947317e 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/OutboundSpec.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/OutboundSpec.java
@@ -14,7 +14,6 @@
package org.smarthomej.binding.knx.internal.client;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.types.Type;
import tuwien.auto.calimero.GroupAddress;
@@ -40,7 +39,6 @@ public interface OutboundSpec {
*
* @return the group address
*/
- @Nullable
GroupAddress getGroupAddress();
/**
diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java
index e3ac67c793..a839a85b73 100644
--- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java
+++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java
@@ -26,12 +26,10 @@
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.openhab.core.config.core.Configuration;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing;
-import org.openhab.core.thing.type.ChannelTypeUID;
import org.openhab.core.types.Command;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
@@ -40,8 +38,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smarthomej.binding.knx.internal.KNXBindingConstants;
-import org.smarthomej.binding.knx.internal.channel.KNXChannelType;
-import org.smarthomej.binding.knx.internal.channel.KNXChannelTypes;
+import org.smarthomej.binding.knx.internal.channel.KNXChannel;
+import org.smarthomej.binding.knx.internal.channel.KNXChannelFactory;
import org.smarthomej.binding.knx.internal.client.AbstractKNXClient;
import org.smarthomej.binding.knx.internal.client.InboundSpec;
import org.smarthomej.binding.knx.internal.client.OutboundSpec;
@@ -51,7 +49,6 @@
import tuwien.auto.calimero.GroupAddress;
import tuwien.auto.calimero.IndividualAddress;
import tuwien.auto.calimero.KNXException;
-import tuwien.auto.calimero.KNXFormatException;
import tuwien.auto.calimero.datapoint.CommandDP;
import tuwien.auto.calimero.datapoint.Datapoint;
@@ -60,6 +57,7 @@
* bus and updating the channels correspondingly.
*
* @author Simon Kaufmann - Initial contribution and API
+ * @author Jan N. Klug - Refactored for performance
*/
@NonNullByDefault
public class DeviceThingHandler extends AbstractKNXThingHandler {
@@ -71,6 +69,7 @@ public class DeviceThingHandler extends AbstractKNXThingHandler {
private final Set groupAddressesRespondingSpec = ConcurrentHashMap.newKeySet();
private final Map> readFutures = new ConcurrentHashMap<>();
private final Map> channelFutures = new ConcurrentHashMap<>();
+ private final Map knxChannels = new ConcurrentHashMap<>();
private int readInterval;
public DeviceThingHandler(Thing thing) {
@@ -83,10 +82,12 @@ public void initialize() {
DeviceConfig config = getConfigAs(DeviceConfig.class);
readInterval = config.getReadInterval();
- // gather all GAs from channel configurations
- getThing().getChannels().forEach(
- channel -> applyChannelFunction(channel, (knxChannelType, channelConfiguration) -> groupAddresses
- .addAll(knxChannelType.getAllGroupAddresses(channelConfiguration))));
+ // gather all GAs from channel configurations and create channels
+ getThing().getChannels().forEach(channel -> {
+ KNXChannel knxChannel = KNXChannelFactory.createKnxChannel(channel);
+ knxChannels.put(channel.getUID(), knxChannel);
+ groupAddresses.addAll(knxChannel.getAllGroupAddresses());
+ });
}
@Override
@@ -101,6 +102,8 @@ public void dispose() {
groupAddresses.clear();
groupAddressesWriteBlockedOnce.clear();
groupAddressesRespondingSpec.clear();
+ knxChannels.clear();
+
super.dispose();
}
@@ -114,48 +117,30 @@ protected void cancelReadFutures() {
}
}
- @FunctionalInterface
- private interface ChannelFunction {
- void apply(KNXChannelType knxChannelType, Configuration configuration) throws KNXException;
- }
-
- private void applyChannelFunction(ChannelUID channelUID, ChannelFunction function) {
- Channel channel = getThing().getChannel(channelUID.getId());
- if (channel == null) {
- logger.warn("Channel '{}' does not exist", channelUID);
- return;
- }
- applyChannelFunction(channel, function);
- }
-
- private void applyChannelFunction(Channel channel, ChannelFunction function) {
- try {
- KNXChannelType knxChannelType = KNXChannelTypes.getKnxChannelType(channel);
- function.apply(knxChannelType, channel.getConfiguration());
- } catch (KNXException e) {
- logger.warn("An error occurred on channel {}: {}", channel.getUID(), e.getMessage(), e);
- }
- }
-
@Override
public void channelLinked(ChannelUID channelUID) {
- if (!isControl(channelUID)) {
- applyChannelFunction(channelUID, this::scheduleRead);
+ KNXChannel knxChannel = knxChannels.get(channelUID);
+ if (knxChannel == null) {
+ logger.warn("Channel '{}' received a channel linked event, but no KNXChannel found", channelUID);
+ return;
+ }
+ if (!knxChannel.isControl()) {
+ scheduleRead(knxChannel);
}
}
@Override
protected void scheduleReadJobs() {
cancelReadFutures();
- for (Channel channel : getThing().getChannels()) {
- if (isLinked(channel.getUID().getId()) && !isControl(channel.getUID())) {
- applyChannelFunction(channel, this::scheduleRead);
+ for (KNXChannel knxChannel : knxChannels.values()) {
+ if (isLinked(knxChannel.getChannelUID()) && knxChannel.isControl()) {
+ scheduleRead(knxChannel);
}
}
}
- private void scheduleRead(KNXChannelType knxChannelType, Configuration configuration) throws KNXFormatException {
- List readSpecs = knxChannelType.getReadSpec(configuration);
+ private void scheduleRead(KNXChannel knxChannel) {
+ List readSpecs = knxChannel.getReadSpec();
for (InboundSpec readSpec : readSpecs) {
readSpec.getGroupAddresses().forEach(ga -> scheduleReadJob(ga, readSpec.getDPT()));
}
@@ -193,9 +178,7 @@ public boolean listensTo(GroupAddress destination) {
/** KNXIO remember controls, removeIf may be null */
private void rememberRespondingSpec(OutboundSpec commandSpec) {
GroupAddress ga = commandSpec.getGroupAddress();
- if (ga != null) {
- groupAddressesRespondingSpec.removeIf(spec -> spec.matchesDestination(ga));
- }
+ groupAddressesRespondingSpec.removeIf(spec -> spec.matchesDestination(ga));
groupAddressesRespondingSpec.add(commandSpec);
logger.trace("rememberRespondingSpec handled commandSpec for '{}' size '{}'", ga,
groupAddressesRespondingSpec.size());
@@ -205,21 +188,26 @@ private void rememberRespondingSpec(OutboundSpec commandSpec) {
@Override
public void handleCommand(ChannelUID channelUID, Command command) {
logger.trace("Handling command '{}' for channel '{}'", command, channelUID);
- if (command instanceof RefreshType && !isControl(channelUID)) {
+ KNXChannel knxChannel = knxChannels.get(channelUID);
+ if (knxChannel == null) {
+ logger.warn("Channel '{}' received command, but no KNXChannel found", channelUID);
+ return;
+ }
+ if (command instanceof RefreshType && !knxChannel.isControl()) {
logger.debug("Refreshing channel '{}'", channelUID);
- applyChannelFunction(channelUID, this::scheduleRead);
+ scheduleRead(knxChannel);
} else {
if (CHANNEL_RESET.equals(channelUID.getId())) {
if (address != null) {
restart();
}
} else {
- applyChannelFunction(channelUID, (knxChannelType, channelConfiguration) -> {
- OutboundSpec commandSpec = knxChannelType.getCommandSpec(channelConfiguration, command);
+ try {
+ OutboundSpec commandSpec = knxChannel.getCommandSpec(command);
// only send GroupValueWrite to KNX if GA is not blocked once
if (commandSpec != null && !groupAddressesWriteBlockedOnce.remove(commandSpec.getGroupAddress())) {
getClient().writeToKNX(commandSpec);
- if (isControl(channelUID)) {
+ if (knxChannel.isControl()) {
rememberRespondingSpec(commandSpec);
}
} else {
@@ -227,39 +215,34 @@ public void handleCommand(ChannelUID channelUID, Command command) {
"None of the configured GAs on channel '{}' could handle the command '{}' of type '{}'",
channelUID, command, command.getClass().getSimpleName());
}
- });
+ } catch (KNXException e) {
+ logger.warn("An error occurred while handling command '{}' on channel '{}': {}", command,
+ channelUID, e.getMessage());
+ }
}
}
}
- private boolean isControl(ChannelUID channelUID) {
- ChannelTypeUID channelTypeUID = getChannelTypeUID(channelUID);
- return CONTROL_CHANNEL_TYPES.contains(channelTypeUID.getId());
- }
-
- private ChannelTypeUID getChannelTypeUID(ChannelUID channelUID) {
- Channel channel = getThing().getChannel(channelUID.getId());
- Objects.requireNonNull(channel);
- ChannelTypeUID channelTypeUID = channel.getChannelTypeUID();
- Objects.requireNonNull(channelTypeUID);
- return channelTypeUID;
- }
-
/** KNXIO */
- private void sendGroupValueResponse(Channel channel, GroupAddress destination) {
- Set rsa = KNXChannelTypes.getKnxChannelType(channel)
- .getWriteAddresses(channel.getConfiguration());
+ private void sendGroupValueResponse(ChannelUID channelUID, GroupAddress destination) {
+ KNXChannel knxChannel = knxChannels.get(channelUID);
+ if (knxChannel == null) {
+ return;
+ }
+ Set rsa = knxChannel.getWriteAddresses();
if (!rsa.isEmpty()) {
logger.trace("onGroupRead size '{}'", rsa.size());
- applyChannelFunction(channel, (knxChannelType, configuration) -> {
- Optional os = groupAddressesRespondingSpec.stream()
- .filter(spec -> spec.matchesDestination(destination)).findFirst();
- if (os.isPresent()) {
- logger.trace("onGroupRead respondToKNX '{}'", os.get().getGroupAddress());
- /* KNXIO: sending real "GroupValueResponse" to the KNX bus. */
+ Optional os = groupAddressesRespondingSpec.stream()
+ .filter(spec -> spec.matchesDestination(destination)).findFirst();
+ if (os.isPresent()) {
+ logger.trace("onGroupRead respondToKNX '{}'", os.get().getGroupAddress());
+ /* KNXIO: sending real "GroupValueResponse" to the KNX bus. */
+ try {
getClient().respondToKNX(os.get());
+ } catch (KNXException e) {
+ logger.warn("An error occurred on channel {}: {}", channelUID, e.getMessage(), e);
}
- });
+ }
}
}
@@ -270,22 +253,19 @@ private void sendGroupValueResponse(Channel channel, GroupAddress destination) {
public void onGroupRead(AbstractKNXClient client, IndividualAddress source, GroupAddress destination, byte[] asdu) {
logger.trace("onGroupRead Thing '{}' received a GroupValueRead telegram from '{}' for destination '{}'",
getThing().getUID(), source, destination);
- for (Channel channel : getThing().getChannels()) {
- if (isControl(channel.getUID())) {
- applyChannelFunction(channel, (knxChannelType, configuration) -> {
- OutboundSpec responseSpec = knxChannelType.getResponseSpec(configuration, destination,
- RefreshType.REFRESH);
- if (responseSpec != null) {
- logger.trace("onGroupRead isControl -> postCommand");
- // This event should be sent to KNX as GroupValueResponse immediately.
- sendGroupValueResponse(channel, destination);
- // Send REFRESH to openHAB to get this event for scripting with postCommand
- // and remember to ignore/block this REFRESH to be sent back to KNX as GroupValueWrite after
- // postCommand is done!
- groupAddressesWriteBlockedOnce.add(destination);
- postCommand(channel.getUID().getId(), RefreshType.REFRESH);
- }
- });
+ for (KNXChannel knxChannel : knxChannels.values()) {
+ if (knxChannel.isControl()) {
+ OutboundSpec responseSpec = knxChannel.getResponseSpec(destination, RefreshType.REFRESH);
+ if (responseSpec != null) {
+ logger.trace("onGroupRead isControl -> postCommand");
+ // This event should be sent to KNX as GroupValueResponse immediately.
+ sendGroupValueResponse(knxChannel.getChannelUID(), destination);
+ // Send REFRESH to openHAB to get this event for scripting with postCommand
+ // and remember to ignore/block this REFRESH to be sent back to KNX as GroupValueWrite after
+ // postCommand is done!
+ groupAddressesWriteBlockedOnce.add(destination);
+ postCommand(knxChannel.getChannelUID(), RefreshType.REFRESH);
+ }
}
}
}
@@ -308,34 +288,33 @@ public void onGroupWrite(AbstractKNXClient client, IndividualAddress source, Gro
logger.debug("onGroupWrite Thing '{}' received a GroupValueWrite telegram from '{}' for destination '{}'",
getThing().getUID(), source, destination);
- for (Channel channel : getThing().getChannels()) {
- applyChannelFunction(channel, (selector, configuration) -> {
- InboundSpec listenSpec = selector.getListenSpec(configuration, destination);
- if (listenSpec != null) {
- logger.trace(
- "onGroupWrite Thing '{}' processes a GroupValueWrite telegram for destination '{}' for channel '{}'",
- getThing().getUID(), destination, channel.getUID());
- /**
- * Remember current KNXIO outboundSpec only if it is a control channel.
- */
- if (isControl(channel.getUID())) {
- logger.trace("onGroupWrite isControl");
- Type value = KNXCoreTypeMapper.convertRawDataToType(listenSpec.getDPT(), asdu);
- if (value != null) {
- OutboundSpec commandSpec = selector.getCommandSpec(configuration, value);
- if (commandSpec != null) {
- rememberRespondingSpec(commandSpec);
- }
+ for (KNXChannel knxChannel : knxChannels.values()) {
+ InboundSpec listenSpec = knxChannel.getListenSpec(destination);
+ if (listenSpec != null) {
+ logger.trace(
+ "onGroupWrite Thing '{}' processes a GroupValueWrite telegram for destination '{}' for channel '{}'",
+ getThing().getUID(), destination, knxChannel.getChannelUID());
+ /**
+ * Remember current KNXIO outboundSpec only if it is a control channel.
+ */
+ if (knxChannel.isControl()) {
+ logger.trace("onGroupWrite isControl");
+ Type value = KNXCoreTypeMapper.convertRawDataToType(listenSpec.getDPT(), asdu);
+ if (value != null) {
+ OutboundSpec commandSpec = knxChannel.getCommandSpec(value);
+ if (commandSpec != null) {
+ rememberRespondingSpec(commandSpec);
}
}
- processDataReceived(destination, asdu, listenSpec, channel.getUID());
}
- });
+ processDataReceived(destination, asdu, listenSpec, knxChannel);
+ }
+
}
}
private void processDataReceived(GroupAddress destination, byte[] asdu, InboundSpec listenSpec,
- ChannelUID channelUID) {
+ KNXChannel knxChannel) {
if (!isDPTSupported(listenSpec.getDPT())) {
logger.warn("DPT '{}' is not supported by the KNX binding.", listenSpec.getDPT());
return;
@@ -343,27 +322,33 @@ private void processDataReceived(GroupAddress destination, byte[] asdu, InboundS
Type value = KNXCoreTypeMapper.convertRawDataToType(listenSpec.getDPT(), asdu);
if (value != null) {
- if (isControl(channelUID)) {
- Channel channel = getThing().getChannel(channelUID.getId());
- Object repeat = channel != null ? channel.getConfiguration().get(KNXBindingConstants.REPEAT_FREQUENCY)
- : null;
- int frequency = repeat != null ? ((BigDecimal) repeat).intValue() : 0;
- if (KNXBindingConstants.CHANNEL_DIMMER_CONTROL.equals(getChannelTypeUID(channelUID).getId())
- && (value instanceof UnDefType || value instanceof IncreaseDecreaseType) && frequency > 0) {
+ if (knxChannel.isControl()) {
+ ChannelUID channelUID = knxChannel.getChannelUID();
+ int frequency;
+ if (KNXBindingConstants.CHANNEL_DIMMER_CONTROL.equals(knxChannel.getChannelType())) {
+ // if we have a dimmer control channel, check if a frequency is defined
+ Channel channel = getThing().getChannel(channelUID);
+ if (channel == null) {
+ logger.warn("Failed to find channel for ChannelUID '{}'", channelUID);
+ return;
+ }
+ frequency = ((BigDecimal) Objects.requireNonNullElse(
+ channel.getConfiguration().get(KNXBindingConstants.REPEAT_FREQUENCY), BigDecimal.ZERO))
+ .intValue();
+ } else {
+ // disable dimming by binding
+ frequency = 0;
+ }
+ if ((value instanceof UnDefType || value instanceof IncreaseDecreaseType) && frequency > 0) {
// continuous dimming by the binding
- if (UnDefType.UNDEF.equals(value)) {
- channelFutures.computeIfPresent(channelUID, (k, v) -> {
- v.cancel(false);
- return null;
- });
- } else if (value instanceof IncreaseDecreaseType) {
- channelFutures.compute(channelUID, (k, v) -> {
- if (v != null) {
- v.cancel(true);
- }
- return scheduler.scheduleWithFixedDelay(() -> postCommand(channelUID, (Command) value), 0,
- frequency, TimeUnit.MILLISECONDS);
- });
+ // cancel a running scheduler before adding a new (and only add if not UnDefType)
+ ScheduledFuture> oldFuture = channelFutures.remove(channelUID);
+ if (oldFuture != null) {
+ oldFuture.cancel(true);
+ }
+ if (value instanceof IncreaseDecreaseType) {
+ channelFutures.put(channelUID, scheduler.scheduleWithFixedDelay(
+ () -> postCommand(channelUID, (Command) value), 0, frequency, TimeUnit.MILLISECONDS));
}
} else {
if (value instanceof Command) {
@@ -373,7 +358,7 @@ private void processDataReceived(GroupAddress destination, byte[] asdu, InboundS
}
} else {
if (value instanceof State) {
- updateState(channelUID, (State) value);
+ updateState(knxChannel.getChannelUID(), (State) value);
}
}
} else {
diff --git a/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java b/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTest.java
similarity index 52%
rename from bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java
rename to bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTest.java
index 706fbc08d7..8d0f5940c8 100644
--- a/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java
+++ b/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTest.java
@@ -14,14 +14,17 @@
package org.smarthomej.binding.knx.internal.channel;
import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.openhab.core.config.core.Configuration;
+import org.openhab.core.thing.Channel;
+import org.openhab.core.thing.type.ChannelTypeUID;
import tuwien.auto.calimero.GroupAddress;
import tuwien.auto.calimero.KNXFormatException;
@@ -32,18 +35,17 @@
*
*/
@NonNullByDefault
-public class KNXChannelTypeTest {
+public class KNXChannelTest {
- private @NonNullByDefault({}) KNXChannelType ct;
-
- @BeforeEach
- public void setup() {
- ct = new MyKNXChannelType("");
+ @Test
+ public void invalidFails() {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<1/3/22+0/3/22+<0/8/15");
+ assertNull(res);
}
@Test
- public void testParseWithDPTMultipleWithRead() {
- ChannelConfiguration res = ct.parse("5.001:<1/3/22+0/3/22+<0/8/15");
+ public void testParseWithDPTMultipleWithRead() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<1/3/22+0/3/22+<0/7/15");
if (res == null) {
fail();
@@ -51,15 +53,15 @@ public void testParseWithDPTMultipleWithRead() {
}
assertEquals("5.001", res.getDPT());
- assertEquals("1/3/22", res.getMainGA().getGA());
- assertTrue(res.getMainGA().isRead());
+ assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
+ assertTrue(res.getReadGAs().contains(res.getMainGA()));
assertEquals(3, res.getListenGAs().size());
assertEquals(2, res.getReadGAs().size());
}
@Test
- public void testParseWithDPTMultipleWithoutRead() {
- ChannelConfiguration res = ct.parse("5.001:1/3/22+0/3/22+0/8/15");
+ public void testParseWithDPTMultipleWithoutRead() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:1/3/22+0/3/22+0/7/15");
if (res == null) {
fail();
@@ -67,15 +69,15 @@ public void testParseWithDPTMultipleWithoutRead() {
}
assertEquals("5.001", res.getDPT());
- assertEquals("1/3/22", res.getMainGA().getGA());
- assertFalse(res.getMainGA().isRead());
+ assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
+ assertFalse(res.getReadGAs().contains(res.getMainGA()));
assertEquals(3, res.getListenGAs().size());
assertEquals(0, res.getReadGAs().size());
}
@Test
- public void testParseWithoutDPTSingleWithoutRead() {
- ChannelConfiguration res = ct.parse("1/3/22");
+ public void testParseWithoutDPTSingleWithoutRead() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("1/3/22");
if (res == null) {
fail();
@@ -83,15 +85,15 @@ public void testParseWithoutDPTSingleWithoutRead() {
}
assertNull(res.getDPT());
- assertEquals("1/3/22", res.getMainGA().getGA());
- assertFalse(res.getMainGA().isRead());
+ assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
+ assertFalse(res.getReadGAs().contains(res.getMainGA()));
assertEquals(1, res.getListenGAs().size());
assertEquals(0, res.getReadGAs().size());
}
@Test
- public void testParseWithoutDPTSingleWithRead() {
- ChannelConfiguration res = ct.parse("<1/3/22");
+ public void testParseWithoutDPTSingleWithRead() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("<1/3/22");
if (res == null) {
fail();
@@ -99,57 +101,64 @@ public void testParseWithoutDPTSingleWithRead() {
}
assertNull(res.getDPT());
- assertEquals("1/3/22", res.getMainGA().getGA());
- assertTrue(res.getMainGA().isRead());
+ assertEquals(new GroupAddress("1/3/22"), res.getMainGA());
+ assertTrue(res.getReadGAs().contains(res.getMainGA()));
assertEquals(1, res.getListenGAs().size());
assertEquals(1, res.getReadGAs().size());
}
@Test
- public void testParseTwoLevel() {
- ChannelConfiguration res = ct.parse("5.001:<3/1024+<4/1025");
+ public void testParseTwoLevel() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<3/1024+<4/1025");
if (res == null) {
fail();
return;
}
- assertEquals("3/1024", res.getMainGA().getGA());
+ assertEquals(new GroupAddress("3/1024"), res.getMainGA());
+ assertTrue(res.getReadGAs().contains(res.getMainGA()));
assertEquals(2, res.getListenGAs().size());
assertEquals(2, res.getReadGAs().size());
}
@Test
- public void testParseFreeLevel() {
- ChannelConfiguration res = ct.parse("5.001:<4610+<4611");
+ public void testParseFreeLevel() throws KNXFormatException {
+ GroupAddressConfiguration res = GroupAddressConfiguration.parse("5.001:<4610+<4611");
if (res == null) {
fail();
return;
}
- assertEquals("4610", res.getMainGA().getGA());
+ assertEquals(new GroupAddress("4610"), res.getMainGA());
assertEquals(2, res.getListenGAs().size());
assertEquals(2, res.getReadGAs().size());
}
@Test
public void testChannelGaParsing() throws KNXFormatException {
+ Channel channel = mock(Channel.class);
Configuration configuration = new Configuration(
Map.of("key1", "5.001:<1/2/3+4/5/6+1/5/6", "key2", "1.001:7/1/9+1/1/2"));
- Set listenAddresses = ct.getAllGroupAddresses(configuration);
+ when(channel.getChannelTypeUID()).thenReturn(new ChannelTypeUID("a:b:c"));
+ when(channel.getConfiguration()).thenReturn(configuration);
+
+ MyKNXChannel knxChannel = new MyKNXChannel(channel);
+
+ Set listenAddresses = knxChannel.getAllGroupAddresses();
assertEquals(5, listenAddresses.size());
// we don't check the content since parsing has been checked before and the quantity is correct
- Set writeAddresses = ct.getWriteAddresses(configuration);
+ Set writeAddresses = knxChannel.getWriteAddresses();
assertEquals(2, writeAddresses.size());
assertTrue(writeAddresses.contains(new GroupAddress("1/2/3")));
assertTrue(writeAddresses.contains(new GroupAddress("7/1/9")));
}
- private static class MyKNXChannelType extends KNXChannelType {
- public MyKNXChannelType(String channelTypeID) {
- super(Set.of("key1", "key2"), channelTypeID);
+ private static class MyKNXChannel extends KNXChannel {
+ public MyKNXChannel(Channel channel) {
+ super(Set.of("key1", "key2"), channel);
}
@Override