28
28
import jssc .SerialPortException ;
29
29
30
30
import java .io .IOException ;
31
+ import java .nio .ByteBuffer ;
32
+ import java .nio .CharBuffer ;
33
+ import java .nio .charset .Charset ;
34
+ import java .nio .charset .CharsetDecoder ;
35
+ import java .nio .charset .CodingErrorAction ;
36
+ import java .nio .charset .StandardCharsets ;
31
37
import java .util .Arrays ;
32
38
import java .util .List ;
33
39
34
- import static processing .app .I18n .tr ;
35
40
import static processing .app .I18n .format ;
41
+ import static processing .app .I18n .tr ;
36
42
37
43
public class Serial implements SerialPortEventListener {
38
44
@@ -47,6 +53,12 @@ public class Serial implements SerialPortEventListener {
47
53
48
54
private SerialPort port ;
49
55
56
+ private CharsetDecoder bytesToStrings ;
57
+ private static final int IN_BUFFER_CAPACITY = 128 ;
58
+ private static final int OUT_BUFFER_CAPACITY = 128 ;
59
+ private ByteBuffer inFromSerial = ByteBuffer .allocate (IN_BUFFER_CAPACITY );
60
+ private CharBuffer outToMessage = CharBuffer .allocate (OUT_BUFFER_CAPACITY );
61
+
50
62
public Serial () throws SerialException {
51
63
this (PreferencesData .get ("serial.port" ),
52
64
PreferencesData .getInteger ("serial.debug_rate" , 9600 ),
@@ -101,6 +113,8 @@ private Serial(String iname, int irate, char iparity, int idatabits, float istop
101
113
//this.parent = parent;
102
114
//parent.attach(this);
103
115
116
+ resetDecoding (StandardCharsets .UTF_8 );
117
+
104
118
int parity = SerialPort .PARITY_NONE ;
105
119
if (iparity == 'E' ) parity = SerialPort .PARITY_EVEN ;
106
120
if (iparity == 'O' ) parity = SerialPort .PARITY_ODD ;
@@ -153,10 +167,24 @@ public synchronized void serialEvent(SerialPortEvent serialEvent) {
153
167
if (serialEvent .isRXCHAR ()) {
154
168
try {
155
169
byte [] buf = port .readBytes (serialEvent .getEventValue ());
156
- if (buf .length > 0 ) {
157
- String msg = new String (buf );
158
- char [] chars = msg .toCharArray ();
159
- message (chars , chars .length );
170
+ int next = 0 ;
171
+ while (next < buf .length ) {
172
+ while (next < buf .length && outToMessage .hasRemaining ()) {
173
+ int spaceInIn = inFromSerial .remaining ();
174
+ int copyNow = buf .length - next < spaceInIn ? buf .length - next : spaceInIn ;
175
+ inFromSerial .put (buf , next , copyNow );
176
+ next += copyNow ;
177
+ inFromSerial .flip ();
178
+ bytesToStrings .decode (inFromSerial , outToMessage , false );
179
+ inFromSerial .compact ();
180
+ }
181
+ outToMessage .flip ();
182
+ if (outToMessage .hasRemaining ()) {
183
+ char [] chars = new char [outToMessage .remaining ()];
184
+ outToMessage .get (chars );
185
+ message (chars , chars .length );
186
+ }
187
+ outToMessage .clear ();
160
188
}
161
189
} catch (SerialPortException e ) {
162
190
errorMessage ("serialEvent" , e );
@@ -226,6 +254,17 @@ public void setRTS(boolean state) {
226
254
}
227
255
}
228
256
257
+ /**
258
+ * Reset the encoding used to convert the bytes coming in
259
+ * before they are handed as Strings to {@Link #message(char[], int)}.
260
+ */
261
+ public synchronized void resetDecoding (Charset charset ) {
262
+ bytesToStrings = charset .newDecoder ()
263
+ .onMalformedInput (CodingErrorAction .REPLACE )
264
+ .onUnmappableCharacter (CodingErrorAction .REPLACE )
265
+ .replaceWith ("\u2e2e " );
266
+ }
267
+
229
268
static public List <String > list () {
230
269
return Arrays .asList (SerialPortList .getPortNames ());
231
270
}
0 commit comments