diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java
index 3b5653b7e3f16..9b2c24e4bcac9 100644
--- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java
+++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/Port.java
@@ -300,21 +300,23 @@ public void run() {
}
private void processMessages() {
- try {
- // must call processData() until we get a null pointer back
- for (Msg m = msgFactory.processData(); m != null; m = msgFactory.processData()) {
- toAllListeners(m);
- notifyWriter(m);
- }
- } catch (IOException e) {
- // got bad data from modem,
- // unblock those waiting for ack
- logger.warn("bad data received: {}", e.getMessage());
- synchronized (getRequestReplyLock()) {
- if (reply == ReplyType.WAITING_FOR_ACK) {
- logger.warn("got bad data back, must assume message was acked.");
- reply = ReplyType.GOT_ACK;
- getRequestReplyLock().notify();
+ // must call processData() until msgFactory done fully processing buffer
+ while (!msgFactory.isDone()) {
+ try {
+ Msg msg = msgFactory.processData();
+ if (msg != null) {
+ toAllListeners(msg);
+ notifyWriter(msg);
+ }
+ } catch (IOException e) {
+ // got bad data from modem,
+ // unblock those waiting for ack
+ synchronized (getRequestReplyLock()) {
+ if (reply == ReplyType.WAITING_FOR_ACK) {
+ logger.debug("got bad data back, must assume message was acked.");
+ reply = ReplyType.GOT_ACK;
+ getRequestReplyLock().notify();
+ }
}
}
}
diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java
index fd08382283455..144eb3cfd839e 100644
--- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java
+++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/driver/hub/HubIOStream.java
@@ -23,6 +23,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Base64;
+import org.apache.commons.lang.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.insteon.internal.driver.IOStream;
@@ -159,6 +160,7 @@ private synchronized String bufferStatus() throws IOException {
* @throws IOException
*/
private synchronized void clearBuffer() throws IOException {
+ logger.trace("clearing buffer");
getURL("/1?XB=M=1");
bufferIdx = 0;
}
@@ -171,14 +173,15 @@ private synchronized void clearBuffer() throws IOException {
*/
public synchronized void write(ByteBuffer msg) throws IOException {
poll(); // fetch the status buffer before we send out commands
- clearBuffer(); // clear the status buffer explicitly.
StringBuilder b = new StringBuilder();
while (msg.remaining() > 0) {
b.append(String.format("%02x", msg.get()));
}
String hexMSG = b.toString();
+ logger.trace("writing a message");
getURL("/3?" + hexMSG + "=I=3");
+ bufferIdx = 0;
}
/**
@@ -210,10 +213,22 @@ public synchronized void poll() throws IOException {
return; // XXX why return here????
}
+ if (StringUtils.repeat("0", data.length()).equals(data)) {
+ logger.trace("skip cleared buffer");
+ bufferIdx = 0;
+ return;
+ }
+
StringBuilder msg = new StringBuilder();
if (nIdx < bufferIdx) {
- msg.append(data.substring(bufferIdx, data.length()));
- msg.append(data.substring(0, nIdx));
+ String msgStart = data.substring(bufferIdx, data.length());
+ String msgEnd = data.substring(0, nIdx);
+ if (StringUtils.repeat("0", msgStart.length()).equals(msgStart)) {
+ logger.trace("discard cleared buffer wrap around msg start");
+ msgStart = "";
+ }
+
+ msg.append(msgStart + msgEnd);
logger.trace("wrap around: copying new data on: {}", msg.toString());
} else {
msg.append(data.substring(bufferIdx, nIdx));
@@ -278,8 +293,6 @@ private String getData(InputStream is) throws IOException {
}
String s = baos.toString();
- logger.trace("read:\n{}", s);
-
return s;
} finally {
bis.close();
diff --git a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgFactory.java b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgFactory.java
index 2a9a4859edc50..26fd5a737f11b 100644
--- a/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgFactory.java
+++ b/bundles/org.openhab.binding.insteon/src/main/java/org/openhab/binding/insteon/internal/message/MsgFactory.java
@@ -40,6 +40,7 @@ public class MsgFactory {
private static final int MAX_MSG_LEN = 4096;
private byte[] buf = new byte[MAX_MSG_LEN];
private int end = 0; // offset of end of buffer
+ private boolean done = true; // done fully processing buffer flag
/**
* Constructor
@@ -47,6 +48,15 @@ public class MsgFactory {
public MsgFactory() {
}
+ /**
+ * Indicates if no more complete message available in the buffer to be processed
+ *
+ * @return buffer data fully processed flag
+ */
+ public boolean isDone() {
+ return done;
+ }
+
/**
* Adds incoming data to the data buffer. First call addData(), then call processData()
*
@@ -56,9 +66,13 @@ public MsgFactory() {
public void addData(byte[] data, int len) {
int l = len;
if (l + end > MAX_MSG_LEN) {
- logger.warn("warn: truncating excessively long message!");
+ logger.warn("truncating excessively long message!");
l = MAX_MSG_LEN - end;
}
+ // indicate new data can be processed if length > 0
+ if (l > 0) {
+ done = false;
+ }
// append the new data to the one we already have
System.arraycopy(data, 0, buf, end, l);
end += l;
@@ -75,13 +89,14 @@ public void addData(byte[] data, int len) {
* @throws IOException if data was received with unknown command codes
*/
public @Nullable Msg processData() throws IOException {
+ Msg msg = null;
// handle the case where we get a pure nack
if (end > 0 && buf[0] == 0x15) {
logger.trace("got pure nack!");
removeFromBuffer(1);
try {
- Msg m = Msg.makeMessage("PureNACK");
- return m;
+ msg = Msg.makeMessage("PureNACK");
+ return msg;
} catch (InvalidMessageTypeException e) {
return null;
}
@@ -93,36 +108,40 @@ public void addData(byte[] data, int len) {
// Now see if we have enough data for a complete message.
// If not, we return null, and expect this method to be called again
// when more data has come in.
- int msgLen = -1;
- boolean isExtended = false;
if (end > 1) {
// we have some data, but do we have enough to read the entire header?
int headerLength = Msg.getHeaderLength(buf[1]);
- isExtended = Msg.isExtended(buf, end, headerLength);
+ boolean isExtended = Msg.isExtended(buf, end, headerLength);
logger.trace("header length expected: {} extended: {}", headerLength, isExtended);
if (headerLength < 0) {
removeFromBuffer(1); // get rid of the leading 0x02 so draining works
- bail("got unknown command code " + Utils.getHexByte(buf[1]));
+ bail("got unknown command code " + Utils.getHexByte(buf[0]));
} else if (headerLength >= 2) {
if (end >= headerLength) {
// only when the header is complete do we know that isExtended is correct!
- msgLen = Msg.getMessageLength(buf[1], isExtended);
+ int msgLen = Msg.getMessageLength(buf[1], isExtended);
+ logger.trace("msgLen expected: {}", msgLen);
if (msgLen < 0) {
// Cannot make sense out of the combined command code & isExtended flag.
removeFromBuffer(1);
- bail("unknown command code/ext flag: " + Utils.getHexByte(buf[1]));
+ bail("got unknown command code/ext flag " + Utils.getHexByte(buf[0]));
+ } else if (msgLen > 0) {
+ if (end >= msgLen) {
+ msg = Msg.createMessage(buf, msgLen, isExtended);
+ removeFromBuffer(msgLen);
+ }
+ } else { // should never happen
+ logger.warn("invalid message length, internal error!");
}
}
} else { // should never happen
logger.warn("invalid header length, internal error!");
- msgLen = -1;
}
}
- logger.trace("msgLen expected: {}", msgLen);
- Msg msg = null;
- if (msgLen > 0 && end >= msgLen) {
- msg = Msg.createMessage(buf, msgLen, isExtended);
- removeFromBuffer(msgLen);
+ // indicate no more messages available in buffer if empty or undefined message
+ if (end == 0 || msg == null) {
+ logger.trace("done processing current buffer data");
+ done = true;
}
logger.trace("keeping buffer len {} data: {}", end, Utils.getHexString(buf, end));
return msg;
@@ -130,7 +149,7 @@ public void addData(byte[] data, int len) {
private void bail(String txt) throws IOException {
drainBuffer(); // this will drain until end or it finds the next 0x02
- logger.warn("{}", txt);
+ logger.debug("bad data received: {}", txt);
throw new IOException(txt);
}
diff --git a/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml b/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml
index 50aa493113ad5..d4c1cf08aeff2 100644
--- a/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml
+++ b/bundles/org.openhab.binding.insteon/src/main/resources/msg_definitions.xml
@@ -120,6 +120,17 @@
+
+
+
+
+
-
+
-
\ No newline at end of file
+