/** * @generate serialEvent.xml * @webref serial:events * @usage web_application * @param event the port where new data is available */ public void serialEvent(SerialPortEvent event) { if (event.getEventType() == SerialPortEvent.RXCHAR) { int toRead; try { while (0 < (toRead = port.getInputBufferBytesCount())) { // this method can be called from the context of another thread synchronized (buffer) { // read one byte at a time if the sketch is using serialEvent if (serialEventMethod != null) { toRead = 1; } // enlarge buffer if necessary if (buffer.length < inBuffer + toRead) { byte temp[] = new byte[buffer.length << 1]; System.arraycopy(buffer, 0, temp, 0, inBuffer); buffer = temp; } // read an array of bytes and copy it into our buffer byte[] read = port.readBytes(toRead); System.arraycopy(read, 0, buffer, inBuffer, read.length); inBuffer += read.length; } if (serialEventMethod != null) { if ((0 < bufferUntilSize && bufferUntilSize <= inBuffer - readOffset) || (0 == bufferUntilSize && bufferUntilByte == buffer[inBuffer - 1])) { try { // serialEvent() is invoked in the context of the current (serial) thread // which means that serialization and atomic variables need to be used to // guarantee reliable operation (and better not draw() etc..) // serialAvailable() does not provide any real benefits over using // available() and read() inside draw - but this function has no // thread-safety issues since it's being invoked during pre in the context // of the Processing applet serialEventMethod.invoke(parent, this); } catch (Exception e) { System.err.println("Error, disabling serialEvent() for " + port.getPortName()); System.err.println(e.getLocalizedMessage()); serialEventMethod = null; } } } invokeSerialAvailable = true; } } catch (SerialPortException e) { throw new RuntimeException( "Error reading from serial port " + e.getPortName() + ": " + e.getExceptionType()); } } }
/** * @generate Serial_readBytesUntil.xml * @webref serial:serial * @usage web_application * @param inByte character designated to mark the end of the data */ public byte[] readBytesUntil(int inByte) { if (inBuffer == readOffset) { return null; } synchronized (buffer) { // look for needle in buffer int found = -1; for (int i = readOffset; i < inBuffer; i++) { if (buffer[i] == (byte) inByte) { found = i; break; } } if (found == -1) { return null; } int toCopy = found - readOffset + 1; byte[] dest = new byte[toCopy]; System.arraycopy(buffer, readOffset, dest, 0, toCopy); readOffset += toCopy; if (inBuffer == readOffset) { inBuffer = 0; readOffset = 0; } return dest; } }
/** * @generate Serial_readBytes.xml * @webref serial:serial * @usage web_application */ public byte[] readBytes() { if (inBuffer == readOffset) { return null; } synchronized (buffer) { byte[] ret = new byte[inBuffer - readOffset]; System.arraycopy(buffer, readOffset, ret, 0, ret.length); inBuffer = 0; readOffset = 0; return ret; } }
/** * * * <h3>Advanced</h3> * * Grab whatever is in the serial buffer, and stuff it into a byte buffer passed in by the user. * This is more memory/time efficient than readBytes() returning a byte[] array. * * <p>Returns an int for how many bytes were read. If more bytes are available than can fit into * the byte array, only those that will fit are read. */ public int readBytes(byte[] dest) { if (inBuffer == readOffset) { return 0; } synchronized (buffer) { int toCopy = inBuffer - readOffset; if (dest.length < toCopy) { toCopy = dest.length; } System.arraycopy(buffer, readOffset, dest, 0, toCopy); readOffset += toCopy; if (inBuffer == readOffset) { inBuffer = 0; readOffset = 0; } return toCopy; } }
/** * * * <h3>Advanced</h3> * * Return a byte array of anything that's in the serial buffer up to the specified maximum number * of bytes. Not particularly memory/speed efficient, because it creates a byte array on each * read, but it's easier to use than readBytes(byte b[]) (see below). * * @param max the maximum number of bytes to read */ public byte[] readBytes(int max) { if (inBuffer == readOffset) { return null; } synchronized (buffer) { int length = inBuffer - readOffset; if (length > max) length = max; byte[] ret = new byte[length]; System.arraycopy(buffer, readOffset, ret, 0, length); readOffset += length; if (inBuffer == readOffset) { inBuffer = 0; readOffset = 0; } return ret; } }
/** * * * <h3>Advanced</h3> * * If dest[] is not big enough, then -1 is returned, and an error message is printed on the * console. If nothing is in the buffer, zero is returned. If 'interesting' byte is not in the * buffer, then 0 is returned. * * @param dest passed in byte array to be altered */ public int readBytesUntil(int inByte, byte[] dest) { if (inBuffer == readOffset) { return 0; } synchronized (buffer) { // look for needle in buffer int found = -1; for (int i = readOffset; i < inBuffer; i++) { if (buffer[i] == (byte) inByte) { found = i; break; } } if (found == -1) { return 0; } // check if bytes to copy fit in dest int toCopy = found - readOffset + 1; if (dest.length < toCopy) { System.err.println( "The buffer passed to readBytesUntil() is to small " + "to contain " + toCopy + " bytes up to and including " + "char " + (byte) inByte); return -1; } System.arraycopy(buffer, readOffset, dest, 0, toCopy); readOffset += toCopy; if (inBuffer == readOffset) { inBuffer = 0; readOffset = 0; } return toCopy; } }