[elerotransmitterstick] Drop responses that do not fit the command that was sent. (#9562)

Signed-off-by: vbier <volker.bier@web.de>
This commit is contained in:
vbier 2020-12-31 11:01:01 +01:00 committed by GitHub
parent 220115c734
commit ee72664d47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 39 additions and 13 deletions

View File

@ -28,7 +28,7 @@ public class CommandPacket {
data = new byte[bytes.length + 1]; data = new byte[bytes.length + 1];
System.arraycopy(bytes, 0, data, 0, bytes.length); System.arraycopy(bytes, 0, data, 0, bytes.length);
data[bytes.length] = checksum(data); data[bytes.length] = checksum(bytes);
} }
public byte[] getBytes() { public byte[] getBytes() {
@ -36,7 +36,7 @@ public class CommandPacket {
} }
public long getResponseTimeout() { public long getResponseTimeout() {
if (data[2] == EASY_CHECK) { if (isEasyCheck()) {
return 1000; return 1000;
} }
@ -54,6 +54,10 @@ public class CommandPacket {
return (byte) (256 - val); return (byte) (256 - val);
} }
public boolean isEasyCheck() {
return data[2] == EASY_CHECK;
}
@Override @Override
public String toString() { public String toString() {
return HexUtils.bytesToHex(data); return HexUtils.bytesToHex(data);

View File

@ -46,6 +46,16 @@ public class Response {
return status; 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 @Override
public String toString() { public String toString() {
return status + " for channels " + Arrays.toString(channels); return status + " for channels " + Arrays.toString(channels);

View File

@ -30,7 +30,7 @@ public class ResponseUtil {
/** /**
* returns the list of channels (starting with 1) * 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[] result = new int[16];
int idx = 0; int idx = 0;

View File

@ -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.SerialPortIdentifier;
import org.openhab.core.io.transport.serial.SerialPortManager; import org.openhab.core.io.transport.serial.SerialPortManager;
import org.openhab.core.io.transport.serial.UnsupportedCommOperationException; import org.openhab.core.io.transport.serial.UnsupportedCommOperationException;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -38,6 +39,7 @@ public class SerialConnection {
private boolean open; private boolean open;
private String portName; private String portName;
private final List<Byte> bytes = new ArrayList<>(); private final List<Byte> bytes = new ArrayList<>();
private CommandPacket lastSentPacket = null;
private Response response = null; private Response response = null;
private final SerialPortManager serialPortManager; private final SerialPortManager serialPortManager;
@ -106,17 +108,15 @@ public class SerialConnection {
// send a packet to the stick and wait for the response // send a packet to the stick and wait for the response
public synchronized Response sendPacket(CommandPacket p) throws IOException { public synchronized Response sendPacket(CommandPacket p) throws IOException {
if (open) { if (open) {
Response r = response; Response r = null;
synchronized (bytes) { synchronized (bytes) {
response = null; response = null;
lastSentPacket = p;
logger.debug("Writing packet to stick: {}", p); logger.debug("Writing packet to stick: {}", p);
serialPort.getOutputStream().write(p.getBytes()); serialPort.getOutputStream().write(p.getBytes());
if (r != null) {
return r;
}
final long responseTimeout = p.getResponseTimeout(); final long responseTimeout = p.getResponseTimeout();
try { try {
logger.trace("Waiting {} ms for answer from stick...", responseTimeout); logger.trace("Waiting {} ms for answer from stick...", responseTimeout);
@ -155,9 +155,10 @@ public class SerialConnection {
} }
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("buffer contains {} bytes: {}", bytes.size(), logger.trace("buffer contains bytes: {}",
ArrayUtils.toPrimitive(bytes.toArray(new Byte[bytes.size()]))); HexUtils.bytesToHex(ArrayUtils.toPrimitive(bytes.toArray(new Byte[bytes.size()]))));
} }
if (bytes.size() > 1) { if (bytes.size() > 1) {
// second byte should be length byte (has to be either 0x04 or 0x05) // second byte should be length byte (has to be either 0x04 or 0x05)
int len = bytes.get(1); 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) long val = bytes.get(0) + bytes.get(1) + bytes.get(2) + bytes.get(3) + bytes.get(4)
+ bytes.get(5); + bytes.get(5);
if (val % 256 == 0) { 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 { } else {
logger.warn("invalid response checksum. Skipping response."); 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) long val = bytes.get(0) + bytes.get(1) + bytes.get(2) + bytes.get(3) + bytes.get(4)
+ bytes.get(5) + bytes.get(6); + bytes.get(5) + bytes.get(6);
if (val % 256 == 0) { 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 { } else {
logger.warn("invalid response checksum. Skipping response."); logger.warn("invalid response checksum. Skipping response.");
} }

View File

@ -274,7 +274,7 @@ public class TransmitterStick {
try { try {
// in case we have no commands that are currently due, wait for a new one // in case we have no commands that are currently due, wait for a new one
if (dueCommands.isEmpty()) { 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()); dueCommands.add(cmdQueue.take());
logger.trace("take returned {}", dueCommands.first()); logger.trace("take returned {}", dueCommands.first());
} }