2828import jssc .SerialPortException ;
2929
3030import 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 ;
3137import java .util .Arrays ;
3238import java .util .List ;
3339
34- import static processing .app .I18n .tr ;
3540import static processing .app .I18n .format ;
41+ import static processing .app .I18n .tr ;
3642
3743public class Serial implements SerialPortEventListener {
3844
@@ -47,6 +53,12 @@ public class Serial implements SerialPortEventListener {
4753
4854 private SerialPort port ;
4955
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+
5062 public Serial () throws SerialException {
5163 this (PreferencesData .get ("serial.port" ),
5264 PreferencesData .getInteger ("serial.debug_rate" , 9600 ),
@@ -101,6 +113,8 @@ private Serial(String iname, int irate, char iparity, int idatabits, float istop
101113 //this.parent = parent;
102114 //parent.attach(this);
103115
116+ resetDecoding (StandardCharsets .UTF_8 );
117+
104118 int parity = SerialPort .PARITY_NONE ;
105119 if (iparity == 'E' ) parity = SerialPort .PARITY_EVEN ;
106120 if (iparity == 'O' ) parity = SerialPort .PARITY_ODD ;
@@ -153,10 +167,24 @@ public synchronized void serialEvent(SerialPortEvent serialEvent) {
153167 if (serialEvent .isRXCHAR ()) {
154168 try {
155169 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 ();
160188 }
161189 } catch (SerialPortException e ) {
162190 errorMessage ("serialEvent" , e );
@@ -226,6 +254,17 @@ public void setRTS(boolean state) {
226254 }
227255 }
228256
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+
229268 static public List <String > list () {
230269 return Arrays .asList (SerialPortList .getPortNames ());
231270 }
0 commit comments