From 491bf0c029beb2d4f0b706a37ace2f3936f1d933 Mon Sep 17 00:00:00 2001 From: Felipe Herranz Date: Wed, 26 Dec 2018 20:27:05 +0100 Subject: [PATCH 1/5] adding protocols buffer --- .../java/com/felhr/utils/ProtocolBuffer.java | 162 ++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java diff --git a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java new file mode 100644 index 0000000..bfec2df --- /dev/null +++ b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java @@ -0,0 +1,162 @@ +package com.felhr.utils; + +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ProtocolBuffer { + + public static final String BINARY = "binary"; + public static final String TEXT = "text"; + + private final String baseRegex1 = "(?<="; + private final String baseRegex2 = ")"; + + private String mode; + + private String finalRegex; + + private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; + + private String trailChars; + private String regex; + + private byte[] rawBuffer; + private StringBuilder stringBuffer; + + private List commands = new ArrayList<>(); + + public ProtocolBuffer(String mode){ + this.mode = mode; + if(mode.equals(BINARY)){ + rawBuffer = new byte[DEFAULT_BUFFER_SIZE]; + }else{ + stringBuffer = new StringBuilder(DEFAULT_BUFFER_SIZE); + } + } + + public ProtocolBuffer(String mode, int bufferSize){ + if(mode.equals(BINARY)){ + rawBuffer = new byte[bufferSize]; + }else{ + stringBuffer = new StringBuilder(bufferSize); + } + } + + public void setTrailChars(String trailChars){ + finalRegex = baseRegex1 + adaptTrailChars(trailChars) + baseRegex2; + } + + public void setRegex(String regex){ + finalRegex = regex; + } + + public void appendData(byte[] data){ + if(mode.equals(TEXT)){ + try { + String dataStr = new String(data, "UTF-8"); + stringBuffer.append(dataStr); + String[] splitStr = stringBuffer.toString().split(finalRegex); + if(splitStr.length > 1){ + commands.addAll(Arrays.asList(splitStr)); + stringBuffer.setLength(0); + } + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + + private String adaptTrailChars(String trailChars){ + String tempStr = trailChars; + + if(trailChars.contains("\\")){ + tempStr = tempStr.replace("\\", "\\\\"); + } + + if(trailChars.contains(".")){ + tempStr = tempStr.replace(".", "\\."); + } + + if(trailChars.contains("+")){ + tempStr = tempStr.replace("+", "\\+"); + } + + if(trailChars.contains("*")){ + tempStr = tempStr.replace("*", "\\*"); + } + + if(trailChars.contains("?")){ + tempStr = tempStr.replace("?", "\\?"); + } + + if(trailChars.contains("[")){ + tempStr = tempStr.replace("[", "\\["); + } + + if(trailChars.contains("^")){ + tempStr = tempStr.replace("^", "\\^"); + } + + if(trailChars.contains("]")){ + tempStr = tempStr.replace("]", "\\]"); + } + + if(trailChars.contains("$")){ + tempStr = tempStr.replace("$", "\\$"); + } + + if(trailChars.contains("(")){ + tempStr = tempStr.replace("(", "\\("); + } + + if(trailChars.contains(")")){ + tempStr = tempStr.replace(")", "\\)"); + } + + if(trailChars.contains("{")){ + tempStr = tempStr.replace("{", "\\{"); + } + + if(trailChars.contains("}")){ + tempStr = tempStr.replace("}", "\\}"); + } + + if(trailChars.contains("=")){ + tempStr = tempStr.replace("=", "\\="); + } + + if(trailChars.contains("!")){ + tempStr = tempStr.replace("!", "\\!"); + } + + if(trailChars.contains("<")) { + tempStr = tempStr.replace("<", "\\<"); + } + + if(trailChars.contains(">")){ + tempStr = tempStr.replace(">", "\\>"); + } + + if(trailChars.contains("|")){ + tempStr = tempStr.replace("|", "\\|"); + } + + if(trailChars.contains(":")){ + tempStr = tempStr.replace(":", "\\:"); + } + + if(trailChars.contains("-")){ + tempStr = tempStr.replace("-", "\\-"); + } + + if(trailChars.contains("/")){ + tempStr = tempStr.replace("/", "\\/"); + } + + return tempStr; + } + +} From 4a8e09dbf41ecc8dad5d31a5b8e4f051011d477f Mon Sep 17 00:00:00 2001 From: Felipe Herranz Date: Thu, 27 Dec 2018 21:01:44 +0100 Subject: [PATCH 2/5] added regex --- .../java/com/felhr/utils/ProtocolBuffer.java | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java index bfec2df..7ef6e28 100644 --- a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java +++ b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java @@ -2,33 +2,40 @@ package com.felhr.utils; import java.io.UnsupportedEncodingException; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Iterator; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class ProtocolBuffer { - public static final String BINARY = "binary"; + public static final String BINARY = "binary."; public static final String TEXT = "text"; - private final String baseRegex1 = "(?<="; + /** + * REGEX + * .+?(?<=\\r\\n) + */ + + private final String baseRegex1 = ".+?(?<="; private final String baseRegex2 = ")"; private String mode; - private String finalRegex; - private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; - private String trailChars; - private String regex; - private byte[] rawBuffer; + private byte[] separator; private StringBuilder stringBuffer; + private Iterator iterator; private List commands = new ArrayList<>(); + private Pattern wholeCommandPattern; + public ProtocolBuffer(String mode){ this.mode = mode; + this.iterator = commands.iterator(); if(mode.equals(BINARY)){ rawBuffer = new byte[DEFAULT_BUFFER_SIZE]; }else{ @@ -37,6 +44,8 @@ public class ProtocolBuffer { } public ProtocolBuffer(String mode, int bufferSize){ + this.mode = mode; + this.iterator = commands.iterator(); if(mode.equals(BINARY)){ rawBuffer = new byte[bufferSize]; }else{ @@ -45,11 +54,15 @@ public class ProtocolBuffer { } public void setTrailChars(String trailChars){ - finalRegex = baseRegex1 + adaptTrailChars(trailChars) + baseRegex2; + wholeCommandPattern = Pattern.compile(baseRegex1 + adaptTrailChars(trailChars) + baseRegex2); + } + + public void setSeparator(byte[] separator){ + this.separator = separator; } public void setRegex(String regex){ - finalRegex = regex; + wholeCommandPattern = Pattern.compile(regex); } public void appendData(byte[] data){ @@ -57,15 +70,33 @@ public class ProtocolBuffer { try { String dataStr = new String(data, "UTF-8"); stringBuffer.append(dataStr); - String[] splitStr = stringBuffer.toString().split(finalRegex); - if(splitStr.length > 1){ - commands.addAll(Arrays.asList(splitStr)); - stringBuffer.setLength(0); + + Matcher matcher1 = wholeCommandPattern.matcher(stringBuffer.toString()); + int groupCount = matcher1.groupCount(); + + for(int i=0;i<=groupCount-1;i++){ + commands.add(matcher1.group(i)); } + stringBuffer.replace(0, stringBuffer.length(), matcher1.replaceAll("")); + } catch (UnsupportedEncodingException e) { e.printStackTrace(); } + }else if(mode.equals(BINARY)){ + //TODO:!! + } + } + + public boolean hasMoreCommands(){ + return iterator.hasNext(); + } + + public String nextCommand(){ + if(iterator.hasNext()){ + return iterator.next(); + }else{ + return null; } } From baa2db7c1773226e63a4393250a3b0257bea6f20 Mon Sep 17 00:00:00 2001 From: Felipe Herranz Date: Fri, 28 Dec 2018 17:59:48 +0100 Subject: [PATCH 3/5] adding protocolbuffer test --- usbserial/build.gradle | 6 ++++ .../felhr/tests/utils/ProtocolBufferTest.java | 32 +++++++++++++++++ .../java/com/felhr/utils/ProtocolBuffer.java | 36 +++++++++---------- 3 files changed, 56 insertions(+), 18 deletions(-) create mode 100644 usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java diff --git a/usbserial/build.gradle b/usbserial/build.gradle index b63abc0..f632f37 100644 --- a/usbserial/build.gradle +++ b/usbserial/build.gradle @@ -36,6 +36,12 @@ android { dependencies { implementation 'com.annimon:stream:1.2.1' + + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'junit:junit:4.12' + + testImplementation 'junit:junit:4.12' } createJar.dependsOn(deleteJar, build) diff --git a/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java new file mode 100644 index 0000000..a794f51 --- /dev/null +++ b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java @@ -0,0 +1,32 @@ +package com.felhr.tests.utils; + +import com.felhr.utils.ProtocolBuffer; + +import junit.framework.TestCase; + +import org.junit.Test; + + +public class ProtocolBufferTest extends TestCase { + + private final String NMEA1 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n"; + private final String NMEA2 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n"; + private final String NMEA3 = "$GPAAM,A,A,0.10,N,WPTN"; + private final String NMEA4 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000"; + + private ProtocolBuffer protocolBuffer; + private final String modeText = ProtocolBuffer.TEXT; + private final String modeBinary = ProtocolBuffer.BINARY; + + @Test + public void testNMEA1(){ + protocolBuffer = new ProtocolBuffer(modeText); + protocolBuffer.setTrailChars("\r\n"); + protocolBuffer.appendData(NMEA1.getBytes()); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + String nextCommand = protocolBuffer.nextCommand(); + assertEquals(NMEA1, nextCommand); + } +} diff --git a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java index 7ef6e28..36dd0e6 100644 --- a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java +++ b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java @@ -1,8 +1,9 @@ package com.felhr.utils; +import android.util.Log; + import java.io.UnsupportedEncodingException; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -17,8 +18,8 @@ public class ProtocolBuffer { * .+?(?<=\\r\\n) */ - private final String baseRegex1 = ".+?(?<="; - private final String baseRegex2 = ")"; + private final String baseRegex1 = "(.+?(?<="; + private final String baseRegex2 = "))"; private String mode; @@ -28,14 +29,12 @@ public class ProtocolBuffer { private byte[] separator; private StringBuilder stringBuffer; - private Iterator iterator; private List commands = new ArrayList<>(); private Pattern wholeCommandPattern; public ProtocolBuffer(String mode){ this.mode = mode; - this.iterator = commands.iterator(); if(mode.equals(BINARY)){ rawBuffer = new byte[DEFAULT_BUFFER_SIZE]; }else{ @@ -45,7 +44,6 @@ public class ProtocolBuffer { public ProtocolBuffer(String mode, int bufferSize){ this.mode = mode; - this.iterator = commands.iterator(); if(mode.equals(BINARY)){ rawBuffer = new byte[bufferSize]; }else{ @@ -54,7 +52,8 @@ public class ProtocolBuffer { } public void setTrailChars(String trailChars){ - wholeCommandPattern = Pattern.compile(baseRegex1 + adaptTrailChars(trailChars) + baseRegex2); + wholeCommandPattern = Pattern.compile(baseRegex1 + adaptTrailChars(trailChars) + baseRegex2, + Pattern.MULTILINE); } public void setSeparator(byte[] separator){ @@ -72,14 +71,16 @@ public class ProtocolBuffer { stringBuffer.append(dataStr); Matcher matcher1 = wholeCommandPattern.matcher(stringBuffer.toString()); - int groupCount = matcher1.groupCount(); + if(matcher1.find()) { + int groupCount = matcher1.groupCount(); - for(int i=0;i<=groupCount-1;i++){ - commands.add(matcher1.group(i)); + for (int i = 0; i <= groupCount - 1; i++) { + commands.add(matcher1.group(i)); + } + + stringBuffer.replace(0, stringBuffer.length(), matcher1.replaceAll("")); } - stringBuffer.replace(0, stringBuffer.length(), matcher1.replaceAll("")); - } catch (UnsupportedEncodingException e) { e.printStackTrace(); } @@ -89,12 +90,12 @@ public class ProtocolBuffer { } public boolean hasMoreCommands(){ - return iterator.hasNext(); + return commands.size() > 0; } public String nextCommand(){ - if(iterator.hasNext()){ - return iterator.next(); + if(commands.size() > 0){ + return commands.remove(0); }else{ return null; } @@ -102,9 +103,8 @@ public class ProtocolBuffer { private String adaptTrailChars(String trailChars){ String tempStr = trailChars; - - if(trailChars.contains("\\")){ - tempStr = tempStr.replace("\\", "\\\\"); + if(trailChars.contains("\r\n")){ + tempStr = tempStr.replace("\r\n", "\\\\r\\\\n"); } if(trailChars.contains(".")){ From d8377625915956308fb6f4c41131b4593775872c Mon Sep 17 00:00:00 2001 From: Felipe Herranz Date: Sun, 30 Dec 2018 03:07:24 +0100 Subject: [PATCH 4/5] testing test mode --- .../felhr/tests/utils/ProtocolBufferTest.java | 108 +++++++++++++- .../java/com/felhr/utils/ProtocolBuffer.java | 137 +++--------------- 2 files changed, 119 insertions(+), 126 deletions(-) diff --git a/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java index a794f51..f29b60b 100644 --- a/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java +++ b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java @@ -9,24 +9,116 @@ import org.junit.Test; public class ProtocolBufferTest extends TestCase { - private final String NMEA1 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n"; - private final String NMEA2 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n"; - private final String NMEA3 = "$GPAAM,A,A,0.10,N,WPTN"; - private final String NMEA4 = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000"; + private final String onePacket = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n"; + private final String twoPackets = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000,5321.6802,N,00630.3372,W,1,8,1.03,61.7,M,55.2,M,,*76\r\n"; + private final String splitPacket = "$GPAAM,A,A,0.10,N,WPTN"; + private final String oneHalfPacket = "$GPAAM,A,A,0.10,N,WPTNME*32\r\n$GPGGA,092750.000"; + + private final String[] verySplit ={"$GPAAM,", + "A", + ",", + "A,", + "0", + ".", + "10,N", + ",WPTNME*32\r\n"}; private ProtocolBuffer protocolBuffer; private final String modeText = ProtocolBuffer.TEXT; private final String modeBinary = ProtocolBuffer.BINARY; @Test - public void testNMEA1(){ + public void testOnePacket(){ protocolBuffer = new ProtocolBuffer(modeText); - protocolBuffer.setTrailChars("\r\n"); - protocolBuffer.appendData(NMEA1.getBytes()); + protocolBuffer.setDelimiter("\r\n"); + protocolBuffer.appendData(onePacket.getBytes()); boolean hasMoreData = protocolBuffer.hasMoreCommands(); assertTrue(hasMoreData); String nextCommand = protocolBuffer.nextCommand(); - assertEquals(NMEA1, nextCommand); + assertEquals(onePacket, nextCommand); + } + + @Test + public void testTwoPackets(){ + protocolBuffer = new ProtocolBuffer(modeText); + protocolBuffer.setDelimiter("\r\n"); + protocolBuffer.appendData(twoPackets.getBytes()); + + StringBuilder builder = new StringBuilder(); + + while(protocolBuffer.hasMoreCommands()){ + builder.append(protocolBuffer.nextCommand()); + } + assertEquals(twoPackets, builder.toString()); + } + + @Test + public void testSplitPackets(){ + protocolBuffer = new ProtocolBuffer(modeText); + protocolBuffer.setDelimiter("\r\n"); + protocolBuffer.appendData(splitPacket.getBytes()); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + } + + @Test + public void testOneHalfPacket(){ + protocolBuffer = new ProtocolBuffer(modeText); + protocolBuffer.setDelimiter("\r\n"); + protocolBuffer.appendData(oneHalfPacket.getBytes()); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + String nextCommand = protocolBuffer.nextCommand(); + assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", nextCommand); + + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + nextCommand = protocolBuffer.nextCommand(); + assertNull(nextCommand); + } + + @Test + public void testNMEA5(){ + protocolBuffer = new ProtocolBuffer(modeText); + protocolBuffer.setDelimiter("\r\n"); + + protocolBuffer.appendData(verySplit[0].getBytes()); + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[1].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[2].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[3].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[4].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[5].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[6].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplit[7].getBytes()); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + String command = protocolBuffer.nextCommand(); + assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", command); } } diff --git a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java index 36dd0e6..b1d00dd 100644 --- a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java +++ b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java @@ -1,37 +1,27 @@ package com.felhr.utils; -import android.util.Log; - import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; public class ProtocolBuffer { public static final String BINARY = "binary."; public static final String TEXT = "text"; - /** - * REGEX - * .+?(?<=\\r\\n) - */ - - private final String baseRegex1 = "(.+?(?<="; - private final String baseRegex2 = "))"; - private String mode; private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; private byte[] rawBuffer; + private byte[] separator; + private String delimiter; private StringBuilder stringBuffer; private List commands = new ArrayList<>(); - private Pattern wholeCommandPattern; + private String regex; public ProtocolBuffer(String mode){ this.mode = mode; @@ -51,34 +41,35 @@ public class ProtocolBuffer { } } - public void setTrailChars(String trailChars){ - wholeCommandPattern = Pattern.compile(baseRegex1 + adaptTrailChars(trailChars) + baseRegex2, - Pattern.MULTILINE); + public void setDelimiter(String delimiter){ + this.delimiter = delimiter; } public void setSeparator(byte[] separator){ this.separator = separator; } - public void setRegex(String regex){ - wholeCommandPattern = Pattern.compile(regex); - } - public void appendData(byte[] data){ if(mode.equals(TEXT)){ try { String dataStr = new String(data, "UTF-8"); stringBuffer.append(dataStr); - Matcher matcher1 = wholeCommandPattern.matcher(stringBuffer.toString()); - if(matcher1.find()) { - int groupCount = matcher1.groupCount(); + String buffer = stringBuffer.toString(); + int prevIndex = 0; + int index = buffer.indexOf(delimiter); + while (index >= 0) { + String tempStr = buffer.substring(prevIndex, index + delimiter.length()); + commands.add(tempStr); + prevIndex = index + delimiter.length(); + index = stringBuffer.toString().indexOf(delimiter, prevIndex); + } - for (int i = 0; i <= groupCount - 1; i++) { - commands.add(matcher1.group(i)); - } - - stringBuffer.replace(0, stringBuffer.length(), matcher1.replaceAll("")); + if(prevIndex < buffer.length() + && prevIndex > 0){ + String tempStr = buffer.substring(prevIndex, buffer.length()); + stringBuffer.setLength(0); + stringBuffer.append(tempStr); } } catch (UnsupportedEncodingException e) { @@ -100,94 +91,4 @@ public class ProtocolBuffer { return null; } } - - private String adaptTrailChars(String trailChars){ - String tempStr = trailChars; - if(trailChars.contains("\r\n")){ - tempStr = tempStr.replace("\r\n", "\\\\r\\\\n"); - } - - if(trailChars.contains(".")){ - tempStr = tempStr.replace(".", "\\."); - } - - if(trailChars.contains("+")){ - tempStr = tempStr.replace("+", "\\+"); - } - - if(trailChars.contains("*")){ - tempStr = tempStr.replace("*", "\\*"); - } - - if(trailChars.contains("?")){ - tempStr = tempStr.replace("?", "\\?"); - } - - if(trailChars.contains("[")){ - tempStr = tempStr.replace("[", "\\["); - } - - if(trailChars.contains("^")){ - tempStr = tempStr.replace("^", "\\^"); - } - - if(trailChars.contains("]")){ - tempStr = tempStr.replace("]", "\\]"); - } - - if(trailChars.contains("$")){ - tempStr = tempStr.replace("$", "\\$"); - } - - if(trailChars.contains("(")){ - tempStr = tempStr.replace("(", "\\("); - } - - if(trailChars.contains(")")){ - tempStr = tempStr.replace(")", "\\)"); - } - - if(trailChars.contains("{")){ - tempStr = tempStr.replace("{", "\\{"); - } - - if(trailChars.contains("}")){ - tempStr = tempStr.replace("}", "\\}"); - } - - if(trailChars.contains("=")){ - tempStr = tempStr.replace("=", "\\="); - } - - if(trailChars.contains("!")){ - tempStr = tempStr.replace("!", "\\!"); - } - - if(trailChars.contains("<")) { - tempStr = tempStr.replace("<", "\\<"); - } - - if(trailChars.contains(">")){ - tempStr = tempStr.replace(">", "\\>"); - } - - if(trailChars.contains("|")){ - tempStr = tempStr.replace("|", "\\|"); - } - - if(trailChars.contains(":")){ - tempStr = tempStr.replace(":", "\\:"); - } - - if(trailChars.contains("-")){ - tempStr = tempStr.replace("-", "\\-"); - } - - if(trailChars.contains("/")){ - tempStr = tempStr.replace("/", "\\/"); - } - - return tempStr; - } - } From b2222b0c2785472b49eedc833930179c09ef5190 Mon Sep 17 00:00:00 2001 From: Felipe Herranz Date: Mon, 31 Dec 2018 03:14:16 +0100 Subject: [PATCH 5/5] added unit tests for binary mode --- .../felhr/tests/utils/ProtocolBufferTest.java | 102 ++++++++++++++++-- .../java/com/felhr/utils/ProtocolBuffer.java | 75 +++++++++++-- 2 files changed, 163 insertions(+), 14 deletions(-) diff --git a/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java index f29b60b..d752b19 100644 --- a/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java +++ b/usbserial/src/androidTest/java/com/felhr/tests/utils/ProtocolBufferTest.java @@ -4,6 +4,7 @@ import com.felhr.utils.ProtocolBuffer; import junit.framework.TestCase; +import org.junit.Assert; import org.junit.Test; @@ -23,6 +24,16 @@ public class ProtocolBufferTest extends TestCase { "10,N", ",WPTNME*32\r\n"}; + private final byte[] rawPacket = new byte[]{0x21, 0x3b, 0x20, 0x40}; + private final byte[] twoRawPackets = new byte[]{0x21, 0x3b, 0x20, 0x40, 0x4a, 0x20, 0x40}; + private final byte[] splitRawPacket = new byte[]{0x21, 0x3b, 0x20, 0x40, 0x4a}; + + private final byte[][] verySplitRawPacket = { + new byte[]{0x21}, + new byte[]{0x3b}, + new byte[]{0x20}, + new byte[]{0x40}}; + private ProtocolBuffer protocolBuffer; private final String modeText = ProtocolBuffer.TEXT; private final String modeBinary = ProtocolBuffer.BINARY; @@ -35,7 +46,7 @@ public class ProtocolBufferTest extends TestCase { boolean hasMoreData = protocolBuffer.hasMoreCommands(); assertTrue(hasMoreData); - String nextCommand = protocolBuffer.nextCommand(); + String nextCommand = protocolBuffer.nextTextCommand(); assertEquals(onePacket, nextCommand); } @@ -48,7 +59,7 @@ public class ProtocolBufferTest extends TestCase { StringBuilder builder = new StringBuilder(); while(protocolBuffer.hasMoreCommands()){ - builder.append(protocolBuffer.nextCommand()); + builder.append(protocolBuffer.nextTextCommand()); } assertEquals(twoPackets, builder.toString()); } @@ -71,18 +82,18 @@ public class ProtocolBufferTest extends TestCase { boolean hasMoreData = protocolBuffer.hasMoreCommands(); assertTrue(hasMoreData); - String nextCommand = protocolBuffer.nextCommand(); + String nextCommand = protocolBuffer.nextTextCommand(); assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", nextCommand); hasMoreData = protocolBuffer.hasMoreCommands(); assertFalse(hasMoreData); - nextCommand = protocolBuffer.nextCommand(); + nextCommand = protocolBuffer.nextTextCommand(); assertNull(nextCommand); } @Test - public void testNMEA5(){ + public void testVerySplit(){ protocolBuffer = new ProtocolBuffer(modeText); protocolBuffer.setDelimiter("\r\n"); @@ -118,7 +129,86 @@ public class ProtocolBufferTest extends TestCase { hasMoreData = protocolBuffer.hasMoreCommands(); assertTrue(hasMoreData); - String command = protocolBuffer.nextCommand(); + String command = protocolBuffer.nextTextCommand(); assertEquals("$GPAAM,A,A,0.10,N,WPTNME*32\r\n", command); } + + @Test + public void testRawPacket(){ + protocolBuffer = new ProtocolBuffer(modeBinary); + protocolBuffer.setDelimiter(new byte[]{0x20, 0x40}); + protocolBuffer.appendData(rawPacket); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + byte[] command = protocolBuffer.nextBinaryCommand(); + Assert.assertArrayEquals(command, rawPacket); + + command = protocolBuffer.nextBinaryCommand(); + assertNull(command); + } + + @Test + public void testTwoRawPackets(){ + protocolBuffer = new ProtocolBuffer(modeBinary); + protocolBuffer.setDelimiter(new byte[]{0x20, 0x40}); + protocolBuffer.appendData(twoRawPackets); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + byte[] command1 = protocolBuffer.nextBinaryCommand(); + Assert.assertArrayEquals(command1, new byte[]{0x21, 0x3b, 0x20, 0x40}); + + hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + byte[] command2 = protocolBuffer.nextBinaryCommand(); + Assert.assertArrayEquals(command2, new byte[]{0x4a, 0x20, 0x40}); + + command2 = protocolBuffer.nextBinaryCommand(); + assertNull(command2); + } + + @Test + public void testSplitRawPacket(){ + protocolBuffer = new ProtocolBuffer(modeBinary); + protocolBuffer.setDelimiter(new byte[]{0x20, 0x40}); + protocolBuffer.appendData(splitRawPacket); + + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + byte[] command1 = protocolBuffer.nextBinaryCommand(); + Assert.assertArrayEquals(command1, new byte[]{0x21, 0x3b, 0x20, 0x40}); + + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + } + + @Test + public void testVerySplitRawPacket(){ + protocolBuffer = new ProtocolBuffer(modeBinary); + protocolBuffer.setDelimiter(new byte[]{0x20, 0x40}); + + protocolBuffer.appendData(verySplitRawPacket[0]); + boolean hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplitRawPacket[1]); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplitRawPacket[2]); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertFalse(hasMoreData); + + protocolBuffer.appendData(verySplitRawPacket[3]); + hasMoreData = protocolBuffer.hasMoreCommands(); + assertTrue(hasMoreData); + + byte[] command = protocolBuffer.nextBinaryCommand(); + Assert.assertArrayEquals(command, new byte[]{0x21, 0x3b, 0x20, 0x40}); + } } diff --git a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java index b1d00dd..80debde 100644 --- a/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java +++ b/usbserial/src/main/java/com/felhr/utils/ProtocolBuffer.java @@ -1,12 +1,16 @@ package com.felhr.utils; +import com.annimon.stream.IntStream; +import com.annimon.stream.function.IntPredicate; + import java.io.UnsupportedEncodingException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class ProtocolBuffer { - public static final String BINARY = "binary."; + public static final String BINARY = "binary"; public static final String TEXT = "text"; private String mode; @@ -14,14 +18,14 @@ public class ProtocolBuffer { private static final int DEFAULT_BUFFER_SIZE = 16 * 1024; private byte[] rawBuffer; + private int bufferPointer = 0; private byte[] separator; private String delimiter; private StringBuilder stringBuffer; private List commands = new ArrayList<>(); - - private String regex; + private List rawCommands = new ArrayList<>(); public ProtocolBuffer(String mode){ this.mode = mode; @@ -45,8 +49,8 @@ public class ProtocolBuffer { this.delimiter = delimiter; } - public void setSeparator(byte[] separator){ - this.separator = separator; + public void setDelimiter(byte[] delimiter){ + this.separator = delimiter; } public void appendData(byte[] data){ @@ -76,19 +80,74 @@ public class ProtocolBuffer { e.printStackTrace(); } }else if(mode.equals(BINARY)){ - //TODO:!! + appendRawData(data); } } public boolean hasMoreCommands(){ - return commands.size() > 0; + if(mode.equals(TEXT)) { + return commands.size() > 0; + }else { + return rawCommands.size() > 0; + } } - public String nextCommand(){ + public String nextTextCommand(){ if(commands.size() > 0){ return commands.remove(0); }else{ return null; } } + + public byte[] nextBinaryCommand(){ + if(rawCommands.size() > 0){ + return rawCommands.remove(0); + }else{ + return null; + } + } + + private void appendRawData(byte[] rawData){ + + System.arraycopy(rawData, 0, rawBuffer, bufferPointer, rawData.length); + bufferPointer += rawData.length; + + SeparatorPredicate predicate = new SeparatorPredicate(); + int[] indexes = + IntStream.range(0, bufferPointer) + .filter(predicate) + .toArray(); + + int prevIndex = 0; + for(Integer i : indexes){ + byte[] command = Arrays.copyOfRange(rawBuffer, prevIndex, i + separator.length); + rawCommands.add(command); + prevIndex = i + separator.length; + } + + if(prevIndex < rawBuffer.length + && prevIndex > 0){ + byte[] tempBuffer = Arrays.copyOfRange(rawBuffer, prevIndex, rawBuffer.length); + bufferPointer = 0; + System.arraycopy(tempBuffer, 0, rawBuffer, bufferPointer, rawData.length); + bufferPointer += rawData.length; + } + + } + + private class SeparatorPredicate implements IntPredicate{ + @Override + public boolean test(int value) { + if(rawBuffer[value] == separator[0]){ + for(int i=1;i<=separator.length-1;i++){ + if(rawBuffer[value + i] != separator[i]){ + return false; + } + } + return true; + } + return false; + } + } }