diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java index 9c09850c31723..252e507dd7e95 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/KNXTypeMapper.java @@ -38,7 +38,7 @@ public interface KNXTypeMapper { * @return datapoint value as a string */ @Nullable - public String toDPTValue(Type type, @Nullable String dpt); + String toDPTValue(Type type, @Nullable String dpt); /** * maps a datapoint value to an openHAB command or state @@ -49,8 +49,8 @@ public interface KNXTypeMapper { * @return a command or state of openHAB */ @Nullable - public Type toType(Datapoint datapoint, byte[] data); + Type toType(Datapoint datapoint, byte[] data); @Nullable - public Class toTypeClass(@Nullable String dpt); + Class toTypeClass(@Nullable String dpt); } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDimmer.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDimmer.java index 90e55672fda12..5e01f0386ba8d 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDimmer.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeDimmer.java @@ -12,12 +12,10 @@ */ package org.openhab.binding.knx.internal.channel; -import static java.util.stream.Collectors.toSet; import static org.openhab.binding.knx.internal.KNXBindingConstants.*; import java.util.Objects; import java.util.Set; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -40,7 +38,7 @@ class TypeDimmer extends KNXChannelType { @Override protected Set getAllGAKeys() { - return Stream.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA).collect(toSet()); + return Set.of(SWITCH_GA, POSITION_GA, INCREASE_DECREASE_GA); } @Override diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java index 27cd9bf11062e..94a41563d01d7 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/channel/TypeRollershutter.java @@ -12,12 +12,10 @@ */ package org.openhab.binding.knx.internal.channel; -import static java.util.stream.Collectors.toSet; import static org.openhab.binding.knx.internal.KNXBindingConstants.*; import java.util.Objects; import java.util.Set; -import java.util.stream.Stream; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -53,6 +51,6 @@ protected String getDefaultDPT(String gaConfigKey) { @Override protected Set getAllGAKeys() { - return Stream.of(UP_DOWN_GA, STOP_MOVE_GA, POSITION_GA).collect(toSet()); + return Set.of(UP_DOWN_GA, STOP_MOVE_GA, POSITION_GA); } } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java index 7740173200af8..2ef00e9aa713e 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/client/AbstractKNXClient.java @@ -297,12 +297,11 @@ private synchronized void disconnect(@Nullable Exception e, Optional j.cancel(true)); readDatapoints.clear(); @@ -321,7 +320,7 @@ protected void releaseConnection() { logger.trace("Bridge {} disconnected from KNX bus", thingUID); } - private @Nullable T nullify(T target, @Nullable Consumer lastWill) { + private @Nullable T nullify(@Nullable T target, @Nullable Consumer lastWill) { if (target != null && lastWill != null) { lastWill.accept(target); } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapper.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapper.java index db902650a10a9..5b2766f80686e 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapper.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/dpt/KNXCoreTypeMapper.java @@ -977,7 +977,7 @@ private String quantityTypeToDPTValue(QuantityType qt, int mainNumber, int su if (typeClass.equals(DateTimeType.class)) { String date = formatDateTime(value, datapoint.getDPT()); if (date.isEmpty()) { - logger.debug("toType: KNX clock msg ignored: date object null or empty {}.", date); + logger.debug("toType: KNX clock msg ignored: date object empty {}.", date); return null; } else { return DateTimeType.valueOf(date); @@ -1047,7 +1047,7 @@ private String quantityTypeToDPTValue(QuantityType qt, int mainNumber, int su * @return a formatted String like yyyy-MM-dd'T'HH:mm:ss which * is target format of the {@link DateTimeType} */ - private String formatDateTime(String value, String dpt) { + private String formatDateTime(String value, @Nullable String dpt) { Date date = null; try { diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java index 460d236206710..f07593596412f 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/factory/KNXHandlerFactory.java @@ -14,8 +14,8 @@ import static org.openhab.binding.knx.internal.KNXBindingConstants.*; -import java.util.Arrays; import java.util.Collection; +import java.util.Set; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; @@ -50,7 +50,7 @@ @Component(service = ThingHandlerFactory.class, configurationPid = "binding.knx") public class KNXHandlerFactory extends BaseThingHandlerFactory { - public static final Collection SUPPORTED_THING_TYPES_UIDS = Arrays.asList(THING_TYPE_DEVICE, + public static final Collection SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_DEVICE, THING_TYPE_IP_BRIDGE, THING_TYPE_SERIAL_BRIDGE); @Nullable @@ -58,9 +58,11 @@ public class KNXHandlerFactory extends BaseThingHandlerFactory { private final SerialPortManager serialPortManager; @Activate - public KNXHandlerFactory(final @Reference TranslationProvider translationProvider, - final @Reference LocaleProvider localeProvider, final @Reference SerialPortManager serialPortManager) { + public KNXHandlerFactory(final @Reference NetworkAddressService networkAddressService, + final @Reference TranslationProvider translationProvider, final @Reference LocaleProvider localeProvider, + final @Reference SerialPortManager serialPortManager) { KNXTranslationProvider.I18N.setProvider(localeProvider, translationProvider); + this.networkAddressService = networkAddressService; this.serialPortManager = serialPortManager; SerialTransportAdapter.setSerialPortManager(serialPortManager); } @@ -84,7 +86,7 @@ public boolean supportsThingType(ThingTypeUID thingTypeUID) { if (THING_TYPE_DEVICE.equals(thingTypeUID)) { return super.createThing(thingTypeUID, configuration, thingUID, bridgeUID); } - throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the KNX binding."); + return null; } @Override @@ -116,13 +118,4 @@ private ThingUID getSerialBridgeThingUID(ThingTypeUID thingTypeUID, @Nullable Th String serialPort = (String) configuration.get(SERIAL_PORT); return new ThingUID(thingTypeUID, serialPort); } - - @Reference - protected void setNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = networkAddressService; - } - - protected void unsetNetworkAddressService(NetworkAddressService networkAddressService) { - this.networkAddressService = null; - } } diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java index 397399f59eb65..fd181d44c47a6 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/AbstractKNXThingHandler.java @@ -52,7 +52,7 @@ public abstract class AbstractKNXThingHandler extends BaseThingHandler implement private final Logger logger = LoggerFactory.getLogger(AbstractKNXThingHandler.class); protected @Nullable IndividualAddress address; - private @Nullable Future descriptionJob; + private @Nullable ScheduledFuture descriptionJob; private boolean filledDescription = false; private final Random random = new Random(); diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java index 68d5c74b72e4f..aee86534ab45a 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/DeviceThingHandler.java @@ -15,13 +15,12 @@ import static org.openhab.binding.knx.internal.KNXBindingConstants.*; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; @@ -69,11 +68,11 @@ public class DeviceThingHandler extends AbstractKNXThingHandler { private final Logger logger = LoggerFactory.getLogger(DeviceThingHandler.class); private final KNXTypeMapper typeHelper = new KNXCoreTypeMapper(); - private final Set groupAddresses = new HashSet<>(); - private final Set groupAddressesWriteBlockedOnce = new HashSet<>(); - private final Set groupAddressesRespondingSpec = new HashSet<>(); - private final Map> readFutures = new HashMap<>(); - private final Map> channelFutures = new HashMap<>(); + private final Set groupAddresses = ConcurrentHashMap.newKeySet(); + private final Set groupAddressesWriteBlockedOnce = ConcurrentHashMap.newKeySet(); + private final Set groupAddressesRespondingSpec = ConcurrentHashMap.newKeySet(); + private final Map> readFutures = new ConcurrentHashMap<>(); + private final Map> channelFutures = new ConcurrentHashMap<>(); private int readInterval; public DeviceThingHandler(Thing thing) { @@ -99,20 +98,20 @@ private void initializeGroupAddresses() { @Override public void dispose() { cancelChannelFutures(); - freeGroupAdresses(); + freeGroupAddresses(); super.dispose(); } private void cancelChannelFutures() { - for (ScheduledFuture future : channelFutures.values()) { - if (!future.isDone()) { - future.cancel(true); - } + for (ChannelUID channelUID : channelFutures.keySet()) { + channelFutures.computeIfPresent(channelUID, (k, v) -> { + v.cancel(true); + return null; + }); } - channelFutures.clear(); } - private void freeGroupAdresses() { + private void freeGroupAddresses() { groupAddresses.clear(); groupAddressesWriteBlockedOnce.clear(); groupAddressesRespondingSpec.clear(); @@ -120,12 +119,12 @@ private void freeGroupAdresses() { @Override protected void cancelReadFutures() { - for (ScheduledFuture future : readFutures.values()) { - if (!future.isDone()) { - future.cancel(true); - } + for (GroupAddress groupAddress : readFutures.keySet()) { + readFutures.computeIfPresent(groupAddress, (k, v) -> { + v.cancel(true); + return null; + }); } - readFutures.clear(); } @FunctionalInterface @@ -220,7 +219,9 @@ public boolean listensTo(GroupAddress destination) { @SuppressWarnings("null") private void rememberRespondingSpec(OutboundSpec commandSpec, boolean add) { GroupAddress ga = commandSpec.getGroupAddress(); - groupAddressesRespondingSpec.removeIf(spec -> spec.getGroupAddress().equals(ga)); + if (ga != null) { + groupAddressesRespondingSpec.removeIf(spec -> spec.getGroupAddress().equals(ga)); + } if (add) { groupAddressesRespondingSpec.add(commandSpec); } @@ -393,18 +394,18 @@ private void processDataReceived(GroupAddress destination, byte[] asdu, InboundS && (type instanceof UnDefType || type instanceof IncreaseDecreaseType) && frequency > 0) { // continuous dimming by the binding if (UnDefType.UNDEF.equals(type)) { - ScheduledFuture future = channelFutures.remove(channelUID); - if (future != null) { - future.cancel(false); - } + channelFutures.computeIfPresent(channelUID, (k, v) -> { + v.cancel(false); + return null; + }); } else if (type instanceof IncreaseDecreaseType) { - ScheduledFuture future = scheduler.scheduleWithFixedDelay(() -> { - postCommand(channelUID, (Command) type); - }, 0, frequency, TimeUnit.MILLISECONDS); - ScheduledFuture previousFuture = channelFutures.put(channelUID, future); - if (previousFuture != null) { - previousFuture.cancel(true); - } + channelFutures.compute(channelUID, (k, v) -> { + if (v != null) { + v.cancel(true); + } + return scheduler.scheduleWithFixedDelay(() -> postCommand(channelUID, (Command) type), 0, + frequency, TimeUnit.MILLISECONDS); + }); } } else { if (type instanceof Command) { diff --git a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java index f5aa5d6ecc18c..e2067d7f3c765 100644 --- a/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java +++ b/bundles/org.openhab.binding.knx/src/main/java/org/openhab/binding/knx/internal/handler/IPBridgeThingHandler.java @@ -175,8 +175,9 @@ public void initializeLater() { logger.debug("NetworkAddressService not available, cannot create bridge {}", thing.getUID()); updateStatus(ThingStatus.OFFLINE); return; + } else { + localEndPoint = new InetSocketAddress(networkAddressService.getPrimaryIpv4HostAddress(), 0); } - localEndPoint = new InetSocketAddress(networkAddressService.getPrimaryIpv4HostAddress(), 0); } updateStatus(ThingStatus.UNKNOWN); diff --git a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java index eaa33e041cf63..14bbbb1b7910d 100644 --- a/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java +++ b/bundles/org.openhab.binding.knx/src/test/java/org/openhab/binding/knx/internal/channel/KNXChannelTypeTest.java @@ -36,11 +36,15 @@ void setup() { ct = new MyKNXChannelType(""); } - @SuppressWarnings("null") @Test void testParseWithDptMultipleWithRead() { ChannelConfiguration res = ct.parse("5.001:<1/3/22+0/3/22+<0/8/15"); + if (res == null) { + fail(); + return; + } + assertEquals("5.001", res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertTrue(res.getMainGA().isRead()); @@ -48,11 +52,15 @@ void testParseWithDptMultipleWithRead() { assertEquals(2, res.getReadGAs().size()); } - @SuppressWarnings("null") @Test void testParseWithDptMultipleWithoutRead() { ChannelConfiguration res = ct.parse("5.001:1/3/22+0/3/22+0/8/15"); + if (res == null) { + fail(); + return; + } + assertEquals("5.001", res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertFalse(res.getMainGA().isRead()); @@ -60,11 +68,15 @@ void testParseWithDptMultipleWithoutRead() { assertEquals(0, res.getReadGAs().size()); } - @SuppressWarnings("null") @Test void testParseWithoutDptSingleWithoutRead() { ChannelConfiguration res = ct.parse("1/3/22"); + if (res == null) { + fail(); + return; + } + assertNull(res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertFalse(res.getMainGA().isRead()); @@ -72,11 +84,15 @@ void testParseWithoutDptSingleWithoutRead() { assertEquals(0, res.getReadGAs().size()); } - @SuppressWarnings("null") @Test void testParseWithoutDptSingleWitRead() { ChannelConfiguration res = ct.parse("<1/3/22"); + if (res == null) { + fail(); + return; + } + assertNull(res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertTrue(res.getMainGA().isRead()); @@ -84,19 +100,29 @@ void testParseWithoutDptSingleWitRead() { assertEquals(1, res.getReadGAs().size()); } - @SuppressWarnings("null") @Test void testParseTwoLevel() { ChannelConfiguration res = ct.parse("5.001:<3/1024+<4/1025"); + + if (res == null) { + fail(); + return; + } + assertEquals("3/1024", res.getMainGA().getGA()); assertEquals(2, res.getListenGAs().size()); assertEquals(2, res.getReadGAs().size()); } - @SuppressWarnings("null") @Test void testParseFreeLevel() { ChannelConfiguration res = ct.parse("5.001:<4610+<4611"); + + if (res == null) { + fail(); + return; + } + assertEquals("4610", res.getMainGA().getGA()); assertEquals(2, res.getListenGAs().size()); assertEquals(2, res.getReadGAs().size());