diff --git a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ExtServices.java b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ExtServices.java index 25a8866b1..9efc9a958 100644 --- a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ExtServices.java +++ b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ExtServices.java @@ -14,6 +14,8 @@ package org.openhab.binding.lcn.internal.pchkdiscovery; import org.eclipse.jdt.annotation.NonNullByDefault; +import com.thoughtworks.xstream.annotations.XStreamAlias; + /** * Used for deserializing the XML response of the LCN-PCHK discovery protocol. * @@ -21,13 +23,14 @@ import org.eclipse.jdt.annotation.NonNullByDefault; */ @NonNullByDefault public class ExtServices { - private final ExtService ExtService; + @XStreamAlias("ExtService") + private final ExtService extService; public ExtServices(ExtService extService) { - ExtService = extService; + this.extService = extService; } public ExtService getExtService() { - return ExtService; + return extService; } } diff --git a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/LcnPchkDiscoveryService.java b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/LcnPchkDiscoveryService.java index 8a5973af7..4ec9cc14f 100644 --- a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/LcnPchkDiscoveryService.java +++ b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/LcnPchkDiscoveryService.java @@ -15,6 +15,7 @@ package org.openhab.binding.lcn.internal.pchkdiscovery; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.MulticastSocket; import java.net.NetworkInterface; import java.net.SocketException; @@ -69,14 +70,14 @@ public class LcnPchkDiscoveryService extends AbstractDiscoveryService { super(SUPPORTED_THING_TYPES_UIDS, 0, false); } - private List getLocalAddresses() { - List result = new LinkedList<>(); + private List getLocalNetworkInterfaces() { + List result = new LinkedList<>(); try { for (NetworkInterface networkInterface : Collections.list(NetworkInterface.getNetworkInterfaces())) { try { if (networkInterface.isUp() && !networkInterface.isLoopback() && !networkInterface.isPointToPoint()) { - result.addAll(Collections.list(networkInterface.getInetAddresses())); + result.add(networkInterface); } } catch (SocketException exception) { // ignore @@ -93,13 +94,13 @@ public class LcnPchkDiscoveryService extends AbstractDiscoveryService { try { InetAddress multicastAddress = InetAddress.getByName(PCHK_DISCOVERY_MULTICAST_ADDRESS); - getLocalAddresses().forEach(localInterfaceAddress -> { - logger.debug("Searching on {} ...", localInterfaceAddress.getHostAddress()); + getLocalNetworkInterfaces().forEach(localNetworkInterface -> { + logger.debug("Searching on {} ...", localNetworkInterface); try (MulticastSocket socket = new MulticastSocket(PCHK_DISCOVERY_PORT)) { - socket.setInterface(localInterfaceAddress); socket.setReuseAddress(true); socket.setSoTimeout(INTERFACE_TIMEOUT_SEC * 1000); - socket.joinGroup(multicastAddress); + socket.joinGroup(new InetSocketAddress(multicastAddress, PCHK_DISCOVERY_PORT), + localNetworkInterface); byte[] requestData = DISCOVER_REQUEST.getBytes(LcnDefs.LCN_ENCODING); DatagramPacket request = new DatagramPacket(requestData, requestData.length, multicastAddress, @@ -136,7 +137,7 @@ public class LcnPchkDiscoveryService extends AbstractDiscoveryService { thingDiscovered(discoveryResult.build()); } while (true); // left by SocketTimeoutException } catch (IOException e) { - logger.debug("Discovery failed for {}: {}", localInterfaceAddress, e.getMessage()); + logger.debug("Discovery failed for {}: {}", localNetworkInterface, e.getMessage()); } }); } catch (UnknownHostException e) { diff --git a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ServicesResponse.java b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ServicesResponse.java index 5568601a8..7ede1b8e9 100644 --- a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ServicesResponse.java +++ b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/pchkdiscovery/ServicesResponse.java @@ -14,6 +14,8 @@ package org.openhab.binding.lcn.internal.pchkdiscovery; import org.eclipse.jdt.annotation.NonNullByDefault; +import com.thoughtworks.xstream.annotations.XStreamAlias; + /** * Used for deserializing the XML response of the LCN-PCHK discovery protocol. * @@ -21,27 +23,30 @@ import org.eclipse.jdt.annotation.NonNullByDefault; */ @NonNullByDefault public class ServicesResponse { - private final Version Version; - private final Server Server; - private final ExtServices ExtServices; - @SuppressWarnings("unused") - private final Object Services = new Object(); + @XStreamAlias("Version") + private final Version version; + @XStreamAlias("Server") + private final Server server; + @XStreamAlias("ExtServices") + private final ExtServices extServices; + @XStreamAlias("Services") + private final Object services = new Object(); public ServicesResponse(Version version, Server server, ExtServices extServices) { - this.Version = version; - this.Server = server; - this.ExtServices = extServices; + this.version = version; + this.server = server; + this.extServices = extServices; } public Server getServer() { - return Server; + return server; } public Version getVersion() { - return Version; + return version; } public ExtServices getExtServices() { - return ExtServices; + return extServices; } } diff --git a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandler.java b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandler.java index 0fdc13281..78f6c6939 100644 --- a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandler.java +++ b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandler.java @@ -53,14 +53,14 @@ public class LcnModuleCodeSubHandler extends AbstractLcnModuleSubHandler { public void handleStatusMessage(Matcher matcher) { String code; + int base = 10; if (matcher.pattern() == FINGERPRINT_PATTERN_HEX) { - code = String.format("%02X%02X%02X", Integer.parseInt(matcher.group("byte0"), 16), - Integer.parseInt(matcher.group("byte1"), 16), Integer.parseInt(matcher.group("byte2"), 16)); - } else { - code = String.format("%02X%02X%02X", Integer.parseInt(matcher.group("byte0")), - Integer.parseInt(matcher.group("byte1")), Integer.parseInt(matcher.group("byte2"))); + base = 16; } + code = String.format("%02X%02X%02X", Integer.parseInt(matcher.group("byte0"), base), + Integer.parseInt(matcher.group("byte1"), base), Integer.parseInt(matcher.group("byte2"), base)); + if (matcher.pattern() == TRANSPONDER_PATTERN) { handler.triggerChannel(LcnChannelGroup.CODE, "transponder", code); } else if (matcher.pattern() == FINGERPRINT_PATTERN_HEX || matcher.pattern() == FINGERPRINT_PATTERN_DEC) { diff --git a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleOutputSubHandler.java b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleOutputSubHandler.java index df3188df7..a6000a72a 100644 --- a/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleOutputSubHandler.java +++ b/bundles/org.openhab.binding.lcn/src/main/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleOutputSubHandler.java @@ -31,6 +31,7 @@ import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.UpDownType; +import org.openhab.core.util.ColorUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -108,14 +109,15 @@ public class LcnModuleOutputSubHandler extends AbstractLcnModuleSubHandler { currentColor = hsbType; handler.updateChannel(LcnChannelGroup.OUTPUT, OUTPUT_COLOR, currentColor); + PercentType[] rgb = ColorUtil.hsbToRgbPercent(currentColor); + if (info.getFirmwareVersion().map(v -> v >= LcnBindingConstants.FIRMWARE_2014).orElse(true)) { - handler.sendPck(PckGenerator.dimAllOutputs(currentColor.getRed().doubleValue(), - currentColor.getGreen().doubleValue(), currentColor.getBlue().doubleValue(), output4.doubleValue(), - COLOR_RAMP_MS)); + handler.sendPck(PckGenerator.dimAllOutputs(rgb[0].doubleValue(), rgb[1].doubleValue(), rgb[2].doubleValue(), + output4.doubleValue(), COLOR_RAMP_MS)); } else { - handler.sendPck(PckGenerator.dimOutput(0, currentColor.getRed().doubleValue(), COLOR_RAMP_MS)); - handler.sendPck(PckGenerator.dimOutput(1, currentColor.getGreen().doubleValue(), COLOR_RAMP_MS)); - handler.sendPck(PckGenerator.dimOutput(2, currentColor.getBlue().doubleValue(), COLOR_RAMP_MS)); + handler.sendPck(PckGenerator.dimOutput(0, rgb[0].doubleValue(), COLOR_RAMP_MS)); + handler.sendPck(PckGenerator.dimOutput(1, rgb[1].doubleValue(), COLOR_RAMP_MS)); + handler.sendPck(PckGenerator.dimOutput(2, rgb[2].doubleValue(), COLOR_RAMP_MS)); } } diff --git a/bundles/org.openhab.binding.lcn/src/test/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandlerTest.java b/bundles/org.openhab.binding.lcn/src/test/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandlerTest.java index e6824fe93..952768873 100644 --- a/bundles/org.openhab.binding.lcn/src/test/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandlerTest.java +++ b/bundles/org.openhab.binding.lcn/src/test/java/org/openhab/binding/lcn/internal/subhandler/LcnModuleCodeSubHandlerTest.java @@ -12,6 +12,7 @@ */ package org.openhab.binding.lcn.internal.subhandler; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -42,8 +43,32 @@ public class LcnModuleCodeSubHandlerTest extends AbstractTestLcnModuleSubHandler @Test public void testDecFingerprint() { - tryParseAllHandlers("=M000005.ZF255255255"); - verify(handler).triggerChannel(LcnChannelGroup.CODE, "fingerprint", "FFFFFF"); + tryParseAllHandlers("=M000005.ZF255001002"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "fingerprint", "FF0102"); verify(handler).triggerChannel(any(), any(), any()); } + + @Test + public void testTransponder() { + tryParseAllHandlers("=M000005.ZT255001002"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "transponder", "FF0102"); + verify(handler).triggerChannel(any(), any(), any()); + } + + @Test + public void testRemote() { + tryParseAllHandlers("=M000005.ZI255001002013001"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "remotecontrolkey", "B3:HIT"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "remotecontrolcode", "FF0102:B3:HIT"); + verify(handler, times(2)).triggerChannel(any(), any(), any()); + } + + @Test + public void testRemoteBatteryLow() { + tryParseAllHandlers("=M000005.ZI255001002008012"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "remotecontrolkey", "A8:MAKE"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "remotecontrolcode", "FF0102:A8:MAKE"); + verify(handler).triggerChannel(LcnChannelGroup.CODE, "remotecontrolbatterylow", "FF0102"); + verify(handler, times(3)).triggerChannel(any(), any(), any()); + } }