diff --git a/java/libraries/serial/.classpath b/java/libraries/serial/.classpath
index fb88820a0..d8894f2e3 100644
--- a/java/libraries/serial/.classpath
+++ b/java/libraries/serial/.classpath
@@ -2,7 +2,7 @@
-
+
diff --git a/java/libraries/serial/build.xml b/java/libraries/serial/build.xml
index d04e8a66a..d6b18410e 100755
--- a/java/libraries/serial/build.xml
+++ b/java/libraries/serial/build.xml
@@ -3,7 +3,7 @@
-
+
@@ -18,7 +18,7 @@
srcdir="src" destdir="bin"
encoding="UTF-8"
includeAntRuntime="false"
- classpath="../../../core/library/core.jar; library/RXTXcomm.jar"
+ classpath="../../../core/library/core.jar; library/jssc.jar"
nowarn="true"
compiler="org.eclipse.jdt.core.JDTCompilerAdapter">
diff --git a/java/libraries/serial/library/jssc.txt b/java/libraries/serial/library/jssc.txt
new file mode 100644
index 000000000..cf2f974ac
--- /dev/null
+++ b/java/libraries/serial/library/jssc.txt
@@ -0,0 +1 @@
+This is using a modified version of Java Simple Serial Connector by Alexey Sokolov. See https://github.com/gohai/java-simple-serial-connector for details on the modifications.
diff --git a/java/libraries/serial/src/processing/serial/Serial.java b/java/libraries/serial/src/processing/serial/Serial.java
index fd3595fc1..8e82e2184 100644
--- a/java/libraries/serial/src/processing/serial/Serial.java
+++ b/java/libraries/serial/src/processing/serial/Serial.java
@@ -5,6 +5,7 @@
Part of the Processing project - http://processing.org
Copyright (c) 2004-05 Ben Fry & Casey Reas
+ Reworked by Gottfried Haider as part of GSOC 2013
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -24,728 +25,401 @@
package processing.serial;
import processing.core.*;
-
-import gnu.io.*;
-
-import java.io.*;
-import java.util.*;
import java.lang.reflect.*;
+import java.util.Map;
+import jssc.*;
-/**
- * @generate Serial.xml
- * @webref net
- * @usage application
- */
public class Serial implements SerialPortEventListener {
PApplet parent;
+ public SerialPort port;
+ Method serialAvailableMethod;
Method serialEventMethod;
- // properties can be passed in for default values
- // otherwise defaults to 9600 N81
+ byte[] buffer = new byte[32768];
+ int inBuffer = 0;
+ int readOffset = 0;
- // these could be made static, which might be a solution
- // for the classloading problem.. because if code ran again,
- // the static class would have an object that could be closed
+ int bufferUntilSize = 1;
+ byte bufferUntilByte = 0;
- public SerialPort port;
+ volatile boolean invokeSerialAvailable = false;
- public int rate;
- public int parity;
- public int databits;
- public int stopbits;
+ // Things we are currently not exposing:
+ // * hardware flow control
+ // * state of the RING, RLSD line
+ // * sending breaks
-
- // read buffer and streams
-
- public InputStream input;
- public OutputStream output;
-
- byte buffer[] = new byte[32768];
- int bufferIndex;
- int bufferLast;
-
- //boolean bufferUntil = false;
- int bufferSize = 1; // how big before reset or event firing
- boolean bufferUntil;
- byte bufferUntilByte;
-
-
- // defaults
-
- static String dname = "COM1";
- static int drate = 9600;
- static char dparity = 'N';
- static int ddatabits = 8;
- static float dstopbits = 1;
-
-
- public void setProperties(Properties props) {
- dname =
- props.getProperty("serial.port", dname);
- drate =
- Integer.parseInt(props.getProperty("serial.rate", "9600"));
- dparity =
- props.getProperty("serial.parity", "N").charAt(0);
- ddatabits =
- Integer.parseInt(props.getProperty("serial.databits", "8"));
- dstopbits =
- new Float(props.getProperty("serial.stopbits", "1")).floatValue();
- }
-
-/**
- * @param parent typically use "this"
- */
public Serial(PApplet parent) {
- this(parent, dname, drate, dparity, ddatabits, dstopbits);
+ this(parent, "COM1", 9600, 'N', 8, 1);
}
-
-/**
- * @param irate 9600 is the default
- */
- public Serial(PApplet parent, int irate) {
- this(parent, dname, irate, dparity, ddatabits, dstopbits);
+ public Serial(PApplet parent, int baudRate) {
+ this(parent, "COM1", baudRate, 'N', 8, 1);
}
-
-/**
- * @param iname name of the port (COM1 is the default)
- */
- public Serial(PApplet parent, String iname, int irate) {
- this(parent, iname, irate, dparity, ddatabits, dstopbits);
+ public Serial(PApplet parent, String portName) {
+ this(parent, portName, 9600, 'N', 8, 1);
}
- public Serial(PApplet parent, String iname) {
- this(parent, iname, drate, dparity, ddatabits, dstopbits);
+ public Serial(PApplet parent, String portName, int baudRate) {
+ this(parent, portName, baudRate, 'N', 8, 1);
}
-
-/**
- * @param iparity 'N' for none, 'E' for even, 'O' for odd ('N' is the default)
- * @param idatabits 8 is the default
- * @param istopbits 1.0, 1.5, or 2.0 (1.0 is the default)
- */
- public Serial(PApplet parent, String iname, int irate,
- char iparity, int idatabits, float istopbits) {
- //if (port != null) port.close();
+ public Serial(PApplet parent, String portName, int baudRate, char parity, int dataBits, float stopBits) {
this.parent = parent;
- //parent.attach(this);
+ parent.registerMethod("dispose", this);
+ parent.registerMethod("pre", this);
- // On OS X, make sure the lock folder needed by RXTX is present
- if (PApplet.platform == PConstants.MACOSX) {
- File lockFolder = new File("/var/lock");
- if (!lockFolder.exists() ||
- !lockFolder.canRead() ||
- !lockFolder.canWrite() ||
- !lockFolder.canExecute()) {
- final String MESSAGE =
- "To use the serial library, first open\n" +
- "Applications -> Utilities -> Terminal.app\n" +
- "and enter the following:\n" +
- "sudo mkdir -p /var/lock\n" +
- "sudo chmod 777 /var/lock";
- System.err.println(MESSAGE);
- //throw new RuntimeException("Additional installation required to " +
- // "use serial, read the console below.");
- final String msg =
- "Please use Tools \u2192 Fix the Serial Library.";
- throw new RuntimeException(msg);
- }
+ // setup parity
+ if (parity == 'O') {
+ parity = SerialPort.PARITY_ODD;
+ } else if (parity == 'E') {
+ parity = SerialPort.PARITY_EVEN;
+ } else if (parity == 'M') {
+ parity = SerialPort.PARITY_MARK;
+ } else if (parity == 'S') {
+ parity = SerialPort.PARITY_SPACE;
+ } else {
+ parity = SerialPort.PARITY_NONE;
}
- this.rate = irate;
+ // setup stop bits
+ int stopBitsIdx = SerialPort.STOPBITS_1;
+ if (stopBits == 1.5f) {
+ stopBitsIdx = SerialPort.STOPBITS_1_5;
+ } else if (stopBits == 2) {
+ stopBitsIdx = SerialPort.STOPBITS_2;
+ }
- parity = SerialPort.PARITY_NONE;
- if (iparity == 'E') parity = SerialPort.PARITY_EVEN;
- if (iparity == 'O') parity = SerialPort.PARITY_ODD;
-
- this.databits = idatabits;
-
- stopbits = SerialPort.STOPBITS_1;
- if (istopbits == 1.5f) stopbits = SerialPort.STOPBITS_1_5;
- if (istopbits == 2) stopbits = SerialPort.STOPBITS_2;
+ port = new SerialPort(portName);
+ try {
+ // the native open() call is not using O_NONBLOCK, so this might block for certain operations (see write())
+ port.openPort();
+ port.setParams(baudRate, dataBits, stopBitsIdx, parity);
+ // we could register more events here
+ port.addEventListener(this, SerialPort.MASK_RXCHAR);
+ } catch (SerialPortException e) {
+ // this used to be a RuntimeException before, so stick with it
+ throw new RuntimeException("Error opening serial port "+e.getPortName()+": "+e.getExceptionType());
+ }
try {
- Enumeration> portList = CommPortIdentifier.getPortIdentifiers();
- while (portList.hasMoreElements()) {
- CommPortIdentifier portId =
- (CommPortIdentifier) portList.nextElement();
+ serialEventMethod = parent.getClass().getMethod("serialEvent", new Class[] { this.getClass() });
+ } catch (Exception e) {
+ }
- if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
- //System.out.println("found " + portId.getName());
- if (portId.getName().equals(iname)) {
- port = (SerialPort)portId.open("serial madness", 2000);
- input = port.getInputStream();
- output = port.getOutputStream();
- port.setSerialPortParams(rate, databits, stopbits, parity);
- port.addEventListener(this);
- port.notifyOnDataAvailable(true);
- //System.out.println("opening, ready to roll");
- }
+ try {
+ serialAvailableMethod = parent.getClass().getMethod("serialAvailable", new Class[] { this.getClass() });
+ } catch (Exception e) {
+ }
+ }
+
+ public void dispose() {
+ stop();
+ }
+
+ public void pre() {
+ if (serialAvailableMethod != null && invokeSerialAvailable) {
+ invokeSerialAvailable = false;
+ try {
+ serialAvailableMethod.invoke(parent, new Object[] { this });
+ } catch (Exception e) {
+ System.err.println("Error, disabling serialAvailable() for "+port.getPortName());
+ System.err.println(e.getLocalizedMessage());
+ serialAvailableMethod = null;
+ }
+ }
+ }
+
+
+ public int available() {
+ return (inBuffer-readOffset);
+ }
+
+ public void buffer(int size) {
+ bufferUntilSize = size;
+ }
+
+ public void bufferUntil(int inByte) {
+ bufferUntilSize = 0;
+ bufferUntilByte = (byte)inByte;
+ }
+
+ public void clear() {
+ synchronized (buffer) {
+ inBuffer = 0;
+ readOffset = 0;
+ }
+ }
+
+ public boolean getCTS() {
+ try {
+ return port.isCTS();
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error reading the CTS line: "+e.getExceptionType());
+ }
+ }
+
+ public boolean getDSR() {
+ try {
+ return port.isDSR();
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error reading the DSR line: "+e.getExceptionType());
+ }
+ }
+
+ public static Map getProperties(String portName) {
+ SerialPortList list = new SerialPortList();
+ return list.getPortProperties(portName);
+ }
+
+ public int last() {
+ if (inBuffer == readOffset) {
+ return -1;
+ }
+
+ synchronized (buffer) {
+ int ret = buffer[inBuffer-1] & 0xFF;
+ inBuffer = 0;
+ readOffset = 0;
+ return ret;
+ }
+ }
+
+ public char lastChar() {
+ return (char)last();
+ }
+
+ public static String[] list() {
+ SerialPortList list = new SerialPortList();
+ // returns list sorted alphabetically, thus cu.* comes before tty.*
+ // this was different with RXTX
+ return list.getPortNames();
+ }
+
+ public int read() {
+ if (inBuffer == readOffset) {
+ return -1;
+ }
+
+ synchronized (buffer) {
+ int ret = buffer[readOffset++] & 0xFF;
+ if (inBuffer == readOffset) {
+ inBuffer = 0;
+ readOffset = 0;
+ }
+ return ret;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ 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;
}
}
-
- } catch (Exception e) {
- errorMessage("", e);
- //exception = e;
- //e.printStackTrace();
- port = null;
- input = null;
- output = null;
- }
-
- parent.registerMethod("dispose", this);
-
- // reflection to check whether host applet has a call for
- // public void serialEvent(processing.serial.Serial)
- // which would be called each time an event comes in
- try {
- serialEventMethod =
- parent.getClass().getMethod("serialEvent",
- new Class[] { Serial.class });
- } catch (Exception e) {
- // no such method, or an error.. which is fine, just ignore
- }
- }
-
-
- /**
- * @generate Serial_stop.xml
- * @webref serial:serial
- * @usage web_application
- */
- public void stop() {
- dispose();
- }
-
-
- /**
- * Used by PApplet to shut things down.
- */
- public void dispose() {
- try {
- if (input != null) {
- input.close();
- input = null;
+ if (found == -1) {
+ return null;
}
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- if (output != null) {
- output.close();
- output = 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;
}
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- try {
- if (port != null) {
- port.close();
- port = null;
- }
- } catch (Exception e) {
- e.printStackTrace();
+ return dest;
}
}
+ public int readBytesUntil(int inByte, byte[] dest) {
+ if (inBuffer == readOffset) {
+ return 0;
+ }
- /**
- * Set the DTR line. Addition from Tom Hulbert.
- */
- public void setDTR(boolean state) {
- port.setDTR(state);
+ 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;
+ }
}
+ public char readChar() {
+ return (char)read();
+ }
- /**
- * @generate serialEvent.xml
- * @webref serial:events
- * @usage web_application
- * @param serialEvent the port where new data is available
- */
- synchronized public void serialEvent(SerialPortEvent serialEvent) {
- if (serialEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
+ public String readString() {
+ if (inBuffer == readOffset) {
+ return null;
+ }
+
+ return new String(readBytes());
+ }
+
+ public void serialEvent(SerialPortEvent event) {
+ if (event.getEventType() == SerialPortEvent.RXCHAR) {
+ int toRead;
try {
- while (input.available() > 0) {
+ while (0 < (toRead = port.getInputBufferBytesCount())) {
+ // this method can be called from the context of another thread
synchronized (buffer) {
- if (bufferLast == buffer.length) {
- byte temp[] = new byte[bufferLast << 1];
- System.arraycopy(buffer, 0, temp, 0, bufferLast);
+ // 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;
}
- buffer[bufferLast++] = (byte) input.read();
+ // 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 ((bufferUntil &&
- (buffer[bufferLast-1] == bufferUntilByte)) ||
- (!bufferUntil &&
- ((bufferLast - bufferIndex) >= bufferSize))) {
+ 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, new Object[] { this });
} catch (Exception e) {
- String msg = "error, disabling serialEvent() for " + port;
- System.err.println(msg);
- e.printStackTrace();
+ System.err.println("Error, disabling serialEvent() for "+port.getPortName());
+ System.err.println(e.getLocalizedMessage());
serialEventMethod = null;
}
}
}
+ invokeSerialAvailable = true;
}
}
-
- } catch (IOException e) {
- errorMessage("serialEvent", e);
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error reading from serial port "+e.getPortName()+": "+e.getExceptionType());
}
}
}
-
- /**
- * @generate Serial_buffer.xml
- * @webref serial:serial
- * @usage web_application
- * @param count number of bytes to buffer
- */
- public void buffer(int count) {
- bufferUntil = false;
- bufferSize = count;
- }
-
-
- /**
- * @generate Serial_bufferUntil.xml
- * @webref serial:serial
- * @usage web_application
- * @param what the value to buffer until
- */
- public void bufferUntil(int what) {
- bufferUntil = true;
- bufferUntilByte = (byte) what;
- }
-
-
- /**
- * @generate Serial_available.xml
- * @webref serial:serial
- * @usage web_application
- */
- public int available() {
- return (bufferLast - bufferIndex);
- }
-
-
- /**
- * @generate Serial_clear.xml
- * @webref serial:serial
- * @usage web_application
- */
- public void clear() {
- bufferLast = 0;
- bufferIndex = 0;
- }
-
-
- /**
- * @generate Serial_read.xml
- * @webref serial:serial
- * @usage web_application
- */
- public int read() {
- if (bufferIndex == bufferLast) return -1;
-
- synchronized (buffer) {
- int outgoing = buffer[bufferIndex++] & 0xff;
- if (bufferIndex == bufferLast) { // rewind
- bufferIndex = 0;
- bufferLast = 0;
- }
- return outgoing;
- }
- }
-
-
- /**
- * @generate Serial_last.xml
- * Advanced
- * Same as read() but returns the very last value received
- * and clears the buffer. Useful when you just want the most
- * recent value sent over the port.
- * @webref serial:serial
- * @usage web_application
- */
- public int last() {
- if (bufferIndex == bufferLast) return -1;
- synchronized (buffer) {
- int outgoing = buffer[bufferLast-1];
- bufferIndex = 0;
- bufferLast = 0;
- return outgoing;
- }
- }
-
-
- /**
- * @generate Serial_readChar.xml
- * @webref serial:serial
- * @usage web_application
- */
- public char readChar() {
- if (bufferIndex == bufferLast) return (char)(-1);
- return (char) read();
- }
-
-
- /**
- * @generate Serial_lastChar.xml
- * @webref serial:serial
- * @usage web_application
- */
- public char lastChar() {
- if (bufferIndex == bufferLast) return (char)(-1);
- return (char) last();
- }
-
-
- /**
- * @generate Serial_readBytes.xml
- * @webref serial:serial
- * @usage web_application
- */
- public byte[] readBytes() {
- if (bufferIndex == bufferLast) return null;
-
- synchronized (buffer) {
- int length = bufferLast - bufferIndex;
- byte outgoing[] = new byte[length];
- System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
-
- bufferIndex = 0; // rewind
- bufferLast = 0;
- return outgoing;
- }
- }
-
-
- /**
- * Advanced
- * 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.
- *
- * 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 outgoing[]) {
- if (bufferIndex == bufferLast) return 0;
-
- synchronized (buffer) {
- int length = bufferLast - bufferIndex;
- if (length > outgoing.length) length = outgoing.length;
- System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
-
- bufferIndex += length;
- if (bufferIndex == bufferLast) {
- bufferIndex = 0; // rewind
- bufferLast = 0;
- }
- return length;
- }
- }
-
-
- /**
- * @generate Serial_readBytesUntil.xml
- * @webref serial:serial
- * @usage web_application
- * @param interesting character designated to mark the end of the data
- */
- public byte[] readBytesUntil(int interesting) {
- if (bufferIndex == bufferLast) return null;
- byte what = (byte)interesting;
-
- synchronized (buffer) {
- int found = -1;
- for (int k = bufferIndex; k < bufferLast; k++) {
- if (buffer[k] == what) {
- found = k;
- break;
- }
- }
- if (found == -1) return null;
-
- int length = found - bufferIndex + 1;
- byte outgoing[] = new byte[length];
- System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
-
- bufferIndex += length;
- if (bufferIndex == bufferLast) {
- bufferIndex = 0; // rewind
- bufferLast = 0;
- }
- return outgoing;
- }
- }
-
-
- /**
- * Advanced
- * If outgoing[] 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 outgoing passed in byte array to be altered
- */
- public int readBytesUntil(int interesting, byte outgoing[]) {
- if (bufferIndex == bufferLast) return 0;
- byte what = (byte)interesting;
-
- synchronized (buffer) {
- int found = -1;
- for (int k = bufferIndex; k < bufferLast; k++) {
- if (buffer[k] == what) {
- found = k;
- break;
- }
- }
- if (found == -1) return 0;
-
- int length = found - bufferIndex + 1;
- if (length > outgoing.length) {
- System.err.println("readBytesUntil() byte buffer is" +
- " too small for the " + length +
- " bytes up to and including char " + interesting);
- return -1;
- }
- //byte outgoing[] = new byte[length];
- System.arraycopy(buffer, bufferIndex, outgoing, 0, length);
-
- bufferIndex += length;
- if (bufferIndex == bufferLast) {
- bufferIndex = 0; // rewind
- bufferLast = 0;
- }
- return length;
- }
- }
-
-
- /**
- * @generate Serial_readString.xml
- * @webref serial:serial
- * @usage web_application
- */
- public String readString() {
- if (bufferIndex == bufferLast) return null;
- return new String(readBytes());
- }
-
-
- /**
- * @generate Serial_readStringUntil.xml
- *Advanced
- * If you want to move Unicode data, you can first convert the
- * String to a byte stream in the representation of your choice
- * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
- *
- * @webref serial:serial
- * @usage web_application
- * @param interesting character designated to mark the end of the data
- */
- public String readStringUntil(int interesting) {
- byte b[] = readBytesUntil(interesting);
- if (b == null) return null;
- return new String(b);
- }
-
-
- /**
- * Advanced
- * This will handle both ints, bytes and chars transparently.
- * @param what data to write
- */
- public void write(int what) { // will also cover char
+ public void setDTR(boolean state) {
+ // there is no way to influence the behavior of the DTR line when opening the serial port
+ // this means that at least on Linux and OS X, Arduino devices are always reset
try {
- output.write(what & 0xff); // for good measure do the &
- output.flush(); // hmm, not sure if a good idea
-
- } catch (Exception e) { // null pointer or serial port dead
- errorMessage("write", e);
+ port.setDTR(state);
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error setting the DTR line: "+e.getExceptionType());
}
}
- /**
- * @param bytes[] data to write
- */
- public void write(byte bytes[]) {
+ public void setRTS(boolean state) {
try {
- output.write(bytes);
- output.flush(); // hmm, not sure if a good idea
-
- } catch (Exception e) { // null pointer or serial port dead
- //errorMessage("write", e);
- e.printStackTrace();
+ port.setRTS(state);
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error setting the RTS line: "+e.getExceptionType());
}
}
-
- /**
- * @generate Serial_write.xml
- * Advanced
- * Write a String to the output. Note that this doesn't account
- * for Unicode (two bytes per char), nor will it send UTF8
- * characters.. It assumes that you mean to send a byte buffer
- * (most often the case for networking and serial i/o) and
- * will only use the bottom 8 bits of each char in the string.
- * (Meaning that internally it uses String.getBytes)
- *
- * If you want to move Unicode data, you can first convert the
- * String to a byte stream in the representation of your choice
- * (i.e. UTF8 or two-byte Unicode data), and send it as a byte array.
- *
- * @webref serial:serial
- * @usage web_application
- * @param what data to write
- */
- public void write(String what) {
- write(what.getBytes());
- }
-
-
- /**
- * @generate Serial_list.xml
- * Advanced
- * If this just hangs and never completes on Windows,
- * it may be because the DLL doesn't have its exec bit set.
- * Why the hell that'd be the case, who knows.
- *
- * @webref serial
- * @usage web_application
- */
- static public String[] list() {
- Vector list = new Vector();
+ public void stop() {
try {
- //System.err.println("trying");
- Enumeration> portList = CommPortIdentifier.getPortIdentifiers();
- //System.err.println("got port list");
- while (portList.hasMoreElements()) {
- CommPortIdentifier portId =
- (CommPortIdentifier) portList.nextElement();
- //System.out.println(portId);
-
- if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
- String name = portId.getName();
- list.addElement(name);
- }
- }
-
- } catch (UnsatisfiedLinkError e) {
- //System.err.println("1");
- errorMessage("ports", e);
-
- } catch (Exception e) {
- //System.err.println("2");
- errorMessage("ports", e);
+ port.closePort();
+ } catch (SerialPortException e) {
}
- //System.err.println("move out");
- String outgoing[] = new String[list.size()];
- list.copyInto(outgoing);
- return outgoing;
+ inBuffer = 0;
+ readOffset = 0;
}
-
- /**
- * General error reporting, all corraled here just in case
- * I think of something slightly more intelligent to do.
- */
- static public void errorMessage(String where, Throwable e) {
- e.printStackTrace();
- throw new RuntimeException("Error inside Serial." + where + "()");
- }
-}
-
-
- /*
- class SerialMenuListener implements ItemListener {
- //public SerialMenuListener() { }
-
- public void itemStateChanged(ItemEvent e) {
- int count = serialMenu.getItemCount();
- for (int i = 0; i < count; i++) {
- ((CheckboxMenuItem)serialMenu.getItem(i)).setState(false);
- }
- CheckboxMenuItem item = (CheckboxMenuItem)e.getSource();
- item.setState(true);
- String name = item.getLabel();
- //System.out.println(item.getLabel());
- PdeBase.properties.put("serial.port", name);
- //System.out.println("set to " + get("serial.port"));
- }
- }
- */
-
-
- /*
- protected Vector buildPortList() {
- // get list of names for serial ports
- // have the default port checked (if present)
- Vector list = new Vector();
-
- //SerialMenuListener listener = new SerialMenuListener();
- boolean problem = false;
-
- // if this is failing, it may be because
- // lib/javax.comm.properties is missing.
- // java is weird about how it searches for java.comm.properties
- // so it tends to be very fragile. i.e. quotes in the CLASSPATH
- // environment variable will hose things.
+ public void write(byte[] src) {
try {
- //System.out.println("building port list");
- Enumeration portList = CommPortIdentifier.getPortIdentifiers();
- while (portList.hasMoreElements()) {
- CommPortIdentifier portId =
- (CommPortIdentifier) portList.nextElement();
- //System.out.println(portId);
-
- if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
- //if (portId.getName().equals(port)) {
- String name = portId.getName();
- //CheckboxMenuItem mi =
- //new CheckboxMenuItem(name, name.equals(defaultName));
-
- //mi.addItemListener(listener);
- //serialMenu.add(mi);
- list.addElement(name);
- }
- }
- } catch (UnsatisfiedLinkError e) {
- e.printStackTrace();
- problem = true;
-
- } catch (Exception e) {
- System.out.println("exception building serial menu");
- e.printStackTrace();
+ // this might block if the serial device is not yet ready (esp. tty devices under OS X)
+ port.writeBytes(src);
+ // we used to call flush() here
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error writing to serial port "+e.getPortName()+": "+e.getExceptionType());
}
-
- //if (serialMenu.getItemCount() == 0) {
- //System.out.println("dimming serial menu");
- //serialMenu.setEnabled(false);
- //}
-
- // only warn them if this is the first time
- if (problem && PdeBase.firstTime) {
- JOptionPane.showMessageDialog(this, //frame,
- "Serial port support not installed.\n" +
- "Check the readme for instructions\n" +
- "if you need to use the serial port. ",
- "Serial Port Warning",
- JOptionPane.WARNING_MESSAGE);
- }
- return list;
}
- */
+ public void write(int src) {
+ try {
+ port.writeInt(src);
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error writing to serial port "+e.getPortName()+": "+e.getExceptionType());
+ }
+ }
+ public void write(String src) {
+ try {
+ port.writeString(src);
+ } catch (SerialPortException e) {
+ throw new RuntimeException("Error writing to serial port "+e.getPortName()+": "+e.getExceptionType());
+ }
+ }
+}
\ No newline at end of file