From ee72664d475069d8394c09746e86e2a86e5f07e3 Mon Sep 17 00:00:00 2001 From: vbier Date: Thu, 31 Dec 2020 11:01:01 +0100 Subject: [PATCH] [elerotransmitterstick] Drop responses that do not fit the command that was sent. (#9562) Signed-off-by: vbier --- .../internal/stick/CommandPacket.java | 8 +++-- .../internal/stick/Response.java | 10 +++++++ .../internal/stick/ResponseUtil.java | 2 +- .../internal/stick/SerialConnection.java | 30 +++++++++++++------ .../internal/stick/TransmitterStick.java | 2 +- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java index cda28b03ba9..74f1528b77c 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/CommandPacket.java @@ -28,7 +28,7 @@ public class CommandPacket { data = new byte[bytes.length + 1]; System.arraycopy(bytes, 0, data, 0, bytes.length); - data[bytes.length] = checksum(data); + data[bytes.length] = checksum(bytes); } public byte[] getBytes() { @@ -36,7 +36,7 @@ public class CommandPacket { } public long getResponseTimeout() { - if (data[2] == EASY_CHECK) { + if (isEasyCheck()) { return 1000; } @@ -54,6 +54,10 @@ public class CommandPacket { return (byte) (256 - val); } + public boolean isEasyCheck() { + return data[2] == EASY_CHECK; + } + @Override public String toString() { return HexUtils.bytesToHex(data); diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java index 41a285367bd..6ef089dcff0 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/Response.java @@ -46,6 +46,16 @@ public class Response { return status; } + public boolean isResponseFor(CommandPacket cmd) { + if (cmd == null || cmd.isEasyCheck()) { + return false; + } + + byte[] cmdBytes = cmd.getBytes(); + int[] cmdChannels = ResponseUtil.getChannelIds(cmdBytes[3], cmdBytes[4]); + return Arrays.equals(channels, cmdChannels); + } + @Override public String toString() { return status + " for channels " + Arrays.toString(channels); diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java index a3ee0c6f807..320a292e564 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/ResponseUtil.java @@ -30,7 +30,7 @@ public class ResponseUtil { /** * returns the list of channels (starting with 1) */ - private static int[] getChannelIds(byte upperChannelByte, byte lowerChannelByte) { + public static int[] getChannelIds(byte upperChannelByte, byte lowerChannelByte) { int[] result = new int[16]; int idx = 0; diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java index 465d92862ab..d7f4c7a6356 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/SerialConnection.java @@ -25,6 +25,7 @@ import org.openhab.core.io.transport.serial.SerialPortEventListener; import org.openhab.core.io.transport.serial.SerialPortIdentifier; import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.io.transport.serial.UnsupportedCommOperationException; +import org.openhab.core.util.HexUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +39,7 @@ public class SerialConnection { private boolean open; private String portName; private final List bytes = new ArrayList<>(); + private CommandPacket lastSentPacket = null; private Response response = null; private final SerialPortManager serialPortManager; @@ -106,17 +108,15 @@ public class SerialConnection { // send a packet to the stick and wait for the response public synchronized Response sendPacket(CommandPacket p) throws IOException { if (open) { - Response r = response; + Response r = null; synchronized (bytes) { response = null; + lastSentPacket = p; + logger.debug("Writing packet to stick: {}", p); serialPort.getOutputStream().write(p.getBytes()); - if (r != null) { - return r; - } - final long responseTimeout = p.getResponseTimeout(); try { logger.trace("Waiting {} ms for answer from stick...", responseTimeout); @@ -155,9 +155,10 @@ public class SerialConnection { } if (logger.isTraceEnabled()) { - logger.trace("buffer contains {} bytes: {}", bytes.size(), - ArrayUtils.toPrimitive(bytes.toArray(new Byte[bytes.size()]))); + logger.trace("buffer contains bytes: {}", + HexUtils.bytesToHex(ArrayUtils.toPrimitive(bytes.toArray(new Byte[bytes.size()])))); } + if (bytes.size() > 1) { // second byte should be length byte (has to be either 0x04 or 0x05) int len = bytes.get(1); @@ -179,7 +180,13 @@ public class SerialConnection { long val = bytes.get(0) + bytes.get(1) + bytes.get(2) + bytes.get(3) + bytes.get(4) + bytes.get(5); if (val % 256 == 0) { - response = ResponseUtil.createResponse(bytes.get(3), bytes.get(4)); + Response r = ResponseUtil.createResponse(bytes.get(3), bytes.get(4)); + if (lastSentPacket != null && lastSentPacket.isEasyCheck()) { + response = r; + } else { + logger.warn("response type does not match command {}. Skipping response.", + lastSentPacket); + } } else { logger.warn("invalid response checksum. Skipping response."); } @@ -191,7 +198,12 @@ public class SerialConnection { long val = bytes.get(0) + bytes.get(1) + bytes.get(2) + bytes.get(3) + bytes.get(4) + bytes.get(5) + bytes.get(6); if (val % 256 == 0) { - response = ResponseUtil.createResponse(bytes.get(3), bytes.get(4), bytes.get(5)); + Response r = ResponseUtil.createResponse(bytes.get(3), bytes.get(4), bytes.get(5)); + if (r.isResponseFor(lastSentPacket)) { + response = r; + } else { + logger.warn("response does not match command channels. Skipping response."); + } } else { logger.warn("invalid response checksum. Skipping response."); } diff --git a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java index a7e2bd1e6d3..b183521550f 100644 --- a/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java +++ b/bundles/org.openhab.binding.elerotransmitterstick/src/main/java/org/openhab/binding/elerotransmitterstick/internal/stick/TransmitterStick.java @@ -274,7 +274,7 @@ public class TransmitterStick { try { // in case we have no commands that are currently due, wait for a new one if (dueCommands.isEmpty()) { - logger.debug("No due commands, invoking take on queue..."); + logger.trace("No due commands, invoking take on queue..."); dueCommands.add(cmdQueue.take()); logger.trace("take returned {}", dueCommands.first()); }