Revision 1946
Added Java code to listen to serial port. Also included development notes (DEV-NOTES.txt) which describe the process I had to go through to get serial ports to work in Java.
trunk/code/projects/calibration_platform/server/DEV-NOTES.txt | ||
---|---|---|
1 |
DEV-NOTES - Development notes for the cal_sta_server Java code |
|
2 |
Author: John Sexton |
|
3 |
Date: 3/20/11 |
|
4 |
|
|
5 |
|
|
6 |
SUMMARY: |
|
7 |
-Tried to install Sun's Java Comm API, doesn't work for 64-bit machines. |
|
8 |
-Changed from open source IcedTea Java 6 to Sun's Java 6. |
|
9 |
-Tried to install RXTX library. Need special version for 64-bit. Does not |
|
10 |
allow you to open any port, only can open what it scans. |
|
11 |
-Downloaded RXTX source code, added "arduino" and "robot" port prefixes |
|
12 |
to RXTX library, compiled it and installed it on Marvin. |
|
13 |
|
|
14 |
USEFUL JAVA LOCATIONS: |
|
15 |
/usr/lib/jvm - |
|
16 |
location of java installations |
|
17 |
|
|
18 |
/usr/lib/jvm/java-6-sun/jre/lib/ext - |
|
19 |
java extension .jar files (like RXTXcomm.jar) go here (for Sun's Java) |
|
20 |
|
|
21 |
/usr/lib/jvm/java-6-sun/jre/lib/amd64 - |
|
22 |
the librxtx______.so files go here (for Sun's Java + 64-bit) |
|
23 |
|
|
24 |
/usr/lib/jvm/java-6-sun/jre/lib/amd64 |
|
25 |
^ ^ |
|
26 |
Sun's Java 64-bit architecture |
|
27 |
|
|
28 |
|
|
29 |
USEFUL WEBSITES: |
|
30 |
http://en.wikibooks.org/wiki/Serial_Programming/Serial_Java - |
|
31 |
General overview of serial programming in Java. |
|
32 |
|
|
33 |
http://download.oracle.com/docs/cd/E17802_01/products/products/javacomm/reference/api/index.html - |
|
34 |
API for javax.comm / gnu.io |
|
35 |
|
|
36 |
http://www.capybara.org/~dfraser/archives/29 - |
|
37 |
Article describing how to edit RXTX source code to add port prefixes. |
|
38 |
|
|
39 |
http://rxtx.qbang.org/wiki/index.php/Main_Page - |
|
40 |
RXTX development wiki. Very good resource for installing and obtaining |
|
41 |
source code. |
|
42 |
|
|
43 |
http://www.cloudhopper.com/opensource/rxtx/ - |
|
44 |
Location of 64-bit compiled binaries for RXTX library. |
|
45 |
|
|
46 |
|
|
47 |
|
|
48 |
|
|
49 |
|
|
50 |
NOTES: |
|
51 |
|
|
52 |
Java does not play nice with serial ports right out of the box. You must |
|
53 |
install additional libraries to gain the ability to speak to serial ports |
|
54 |
in Java. The most common library that I found is the JAVA COMMUNICATIONS |
|
55 |
API LIBRARY. |
|
56 |
|
|
57 |
|
|
58 |
== Sun's Java Communications API == |
|
59 |
|
|
60 |
Sun does a very poor job of maintaining this library (after all, they |
|
61 |
support platform-independent development and this is difficult when a |
|
62 |
serial port inherently relies on the underlying hardware). My first |
|
63 |
attempts to successfully listen over a serial port involved using Sun's |
|
64 |
implementation of the Java Communications API. It was difficult to find a |
|
65 |
good download of this online, but I eventually ended up using an Oracle |
|
66 |
website (http://www.oracle.com/technetwork/java/index-jsp-141752.html) to |
|
67 |
obtain the library. Followed installation instructions and successfully |
|
68 |
installed, but when I tried to run a program I got an error which cited |
|
69 |
the ELF compiled binary file. Also mentioned the word size might be wrong. |
|
70 |
This error was confirmed online where I found support for the fact that |
|
71 |
Sun/Oracle only supports 32-bit versions of the Java Communications API |
|
72 |
and doesn't support windows. All of these limitations led me to abandon |
|
73 |
using Sun's version. |
|
74 |
|
|
75 |
|
|
76 |
== RXTX Library == |
|
77 |
|
|
78 |
I found an open source library called the RXTX library which follows the |
|
79 |
Java Communications API exactly (except it's called 'gnu.io' instead of |
|
80 |
'javax.comm'). The development website |
|
81 |
(http://rxtx.qbang.org/wiki/index.php/Main_Page) was very useful. I was |
|
82 |
able to successfully install the RXTX library, but when I tried to run |
|
83 |
sample code, Java seg-faulted (OMG... XD). In an attempt to fix this, I |
|
84 |
removed the open source IcedTea java and installed Sun's Java, but the |
|
85 |
error still remained. I then traced the error back to the Thread function, |
|
86 |
so I believe the problem is not actualy with the RXTX functionality that |
|
87 |
we need and instead has to do with using threads with the RXTX library. |
|
88 |
|
|
89 |
I proceeded to write a small Java program to test the |
|
90 |
RXTX library, and discovered that you can only address ports which the |
|
91 |
library finds on its own. This was a problem because the library only |
|
92 |
looked for a few prefixes and did not show the 'arduino' or the 'robot#' |
|
93 |
nodes in the /dev folder. I found an article online |
|
94 |
(http://www.capybara.org/~dfraser/archives/29) which describes how |
|
95 |
to edit the source code for the RXTX library to include more ports. I |
|
96 |
used the link included in the article to obtain the source code, but when |
|
97 |
I edited the necessary source file (RXTXCommDriver.java), recompiled it |
|
98 |
into a .jar file again (had to remove a 'import javax.comm.*' line from |
|
99 |
the source file which seemed strange to me), and transfered it into the |
|
100 |
proper directory (/usr/lib/jvm/java-6-sun/jre/lib/ext) it did not work. |
|
101 |
Java threw an error which I can't remember the content of at the moment |
|
102 |
(but it wasn't a seg-fault like the thread error). To obtain a better copy |
|
103 |
of the source code, I again resorted to the RXTX development wiki |
|
104 |
(http://rxtx.qbang.org/wiki/index.php/Main_Page). I downloaded a recent |
|
105 |
copy of the source code, unzipped it, ran '/configure', and ran 'make'. |
|
106 |
I received some errors, but there was still a brand new 'RXTXComm.jar' |
|
107 |
file in the folder now, so I proceeded to install it |
|
108 |
(replace the RXTXComm.jar file in the |
|
109 |
/usr/lib/jvm/java-6-sun/jre/lib/ext folder). To my relief, my test program |
|
110 |
did NOT throw an error this time. I did get a warning that looked like this: |
|
111 |
|
|
112 |
WARNING: RXTX Version mismatch |
|
113 |
Jar version = RXTX-2.2 |
|
114 |
native lib Version = RXTX-2.2pre2 |
|
115 |
|
|
116 |
(versions are not the same as the versions I saw, but I did have a mismatch |
|
117 |
warning). To solve this, I just went back to the development wiki and |
|
118 |
found the version that made these two lines agree (turned out to be |
|
119 |
rxtx-2.2pre2). Now (finally), my little test program can find the 'arduino' |
|
120 |
and 'robot#' ports and listen to them! |
|
121 |
|
|
122 |
Hope this helps for anyone who has to take this project up after me! |
trunk/code/projects/calibration_platform/server/cal_sta_server/SimpleRead.java | ||
---|---|---|
1 |
import gnu.io.*; |
|
2 |
|
|
3 |
public class SimpleRead { |
|
4 |
|
|
5 |
static CommPortIdentifier portId; |
|
6 |
static Enumeration portList; |
|
7 |
InputStream inputStream; |
|
8 |
SerialPort serialPort; |
|
9 |
Thread readThread; |
|
10 |
|
|
11 |
public static void main(String[] args) { |
|
12 |
boolean portFound = false; |
|
13 |
String defaultPort = "/dev/ttyUSB0"; |
|
14 |
|
|
15 |
if (args.length > 0) { |
|
16 |
defaultPort = args[0]; |
|
17 |
} |
|
18 |
|
|
19 |
portList = CommPortIdentifier.getPortIdentifiers(); |
|
20 |
|
|
21 |
while (portList.hasMoreElements()) { |
|
22 |
portId = (CommPortIdentifier) portList.nextElement(); |
|
23 |
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { |
|
24 |
if (portId.getName().equals(defaultPort)) { |
|
25 |
System.out.println("Found port: "+defaultPort); |
|
26 |
portFound = true; |
|
27 |
SimpleRead reader = new SimpleRead(); |
|
28 |
} |
|
29 |
} |
|
30 |
} |
|
31 |
if (!portFound) { |
|
32 |
System.out.println("port " + defaultPort + " not found."); |
|
33 |
} |
|
34 |
|
|
35 |
Opens |
|
36 |
} |
|
37 |
|
|
38 |
/** |
|
39 |
* Constructor declaration |
|
40 |
* |
|
41 |
* |
|
42 |
* @see |
|
43 |
*/ |
|
44 |
public SimpleRead() { |
|
45 |
try { |
|
46 |
serialPort = (SerialPort) portId.open("SimpleReadApp", 2000); |
|
47 |
} catch (PortInUseException e) {} |
|
48 |
|
|
49 |
try { |
|
50 |
inputStream = serialPort.getInputStream(); |
|
51 |
} catch (IOException e) {} |
|
52 |
|
|
53 |
try { |
|
54 |
serialPort.addEventListener(this); |
|
55 |
} catch (TooManyListenersException e) {} |
|
56 |
|
|
57 |
serialPort.notifyOnDataAvailable(true); |
|
58 |
|
|
59 |
try { |
|
60 |
serialPort.setSerialPortParams(9600, SerialPort.DATABITS_8, |
|
61 |
SerialPort.STOPBITS_1, |
|
62 |
SerialPort.PARITY_NONE); |
|
63 |
} catch (UnsupportedCommOperationException e) {} |
|
64 |
|
|
65 |
readThread = new Thread(this); |
|
66 |
|
|
67 |
readThread.start(); |
|
68 |
} |
|
69 |
|
|
70 |
/** |
|
71 |
* Method declaration |
|
72 |
* |
|
73 |
* |
|
74 |
* @see |
|
75 |
*/ |
|
76 |
public void run() { |
|
77 |
try { |
|
78 |
Thread.sleep(20000); |
|
79 |
} catch (InterruptedException e) {} |
|
80 |
} |
|
81 |
|
|
82 |
/** |
|
83 |
* Method declaration |
|
84 |
* |
|
85 |
* |
|
86 |
* @param event |
|
87 |
* |
|
88 |
* @see |
|
89 |
*/ |
|
90 |
public void serialEvent(SerialPortEvent event) { |
|
91 |
switch (event.getEventType()) { |
|
92 |
|
|
93 |
case SerialPortEvent.BI: |
|
94 |
|
|
95 |
case SerialPortEvent.OE: |
|
96 |
|
|
97 |
case SerialPortEvent.FE: |
|
98 |
|
|
99 |
case SerialPortEvent.PE: |
|
100 |
|
|
101 |
case SerialPortEvent.CD: |
|
102 |
|
|
103 |
case SerialPortEvent.CTS: |
|
104 |
|
|
105 |
case SerialPortEvent.DSR: |
|
106 |
|
|
107 |
case SerialPortEvent.RI: |
|
108 |
|
|
109 |
case SerialPortEvent.OUTPUT_BUFFER_EMPTY: |
|
110 |
break; |
|
111 |
|
|
112 |
case SerialPortEvent.DATA_AVAILABLE: |
|
113 |
byte[] readBuffer = new byte[20]; |
|
114 |
|
|
115 |
try { |
|
116 |
while (inputStream.available() > 0) { |
|
117 |
int numBytes = inputStream.read(readBuffer); |
|
118 |
} |
|
119 |
|
|
120 |
System.out.print(new String(readBuffer)); |
|
121 |
} catch (IOException e) {} |
|
122 |
|
|
123 |
break; |
|
124 |
} |
|
125 |
} |
|
126 |
|
|
127 |
} |
trunk/code/projects/calibration_platform/server/cal_sta_server/SimpleSerial.java | ||
---|---|---|
1 |
import java.io.*; |
|
2 |
import java.util.Enumeration; |
|
3 |
import gnu.io.*; |
|
4 |
|
|
5 |
import java.lang.Character; |
|
6 |
|
|
7 |
public class SimpleSerial { |
|
8 |
|
|
9 |
public static void main(String[] args) { |
|
10 |
|
|
11 |
String port_path = "/dev/ttyUSB0"; |
|
12 |
/* |
|
13 |
FileInputStream port_stream; |
|
14 |
|
|
15 |
try { |
|
16 |
port_stream = new FileInputStream(port_path); |
|
17 |
} catch (IOException e) { |
|
18 |
System.out.print(e); |
|
19 |
} |
|
20 |
|
|
21 |
port_stream.getFD() |
|
22 |
*/ |
|
23 |
|
|
24 |
|
|
25 |
Enumeration ports = CommPortIdentifier.getPortIdentifiers(); |
|
26 |
CommPortIdentifier port = null, arduino = null; |
|
27 |
|
|
28 |
SerialPort ser = null; |
|
29 |
InputStream inSt = null; |
|
30 |
|
|
31 |
while (ports.hasMoreElements()) { |
|
32 |
|
|
33 |
port = (CommPortIdentifier)ports.nextElement(); |
|
34 |
|
|
35 |
System.out.println(port.getName()); |
|
36 |
|
|
37 |
if (port.getName().equals("/dev/arduino")) { |
|
38 |
arduino = port; |
|
39 |
} |
|
40 |
|
|
41 |
} |
|
42 |
|
|
43 |
System.out.println(arduino.getName()); |
|
44 |
|
|
45 |
try{ |
|
46 |
ser = (SerialPort) arduino.open("cal_sta_server", 2000); |
|
47 |
} catch (PortInUseException e) {System.out.print(e);} |
|
48 |
|
|
49 |
try { |
|
50 |
inSt = ser.getInputStream(); |
|
51 |
} catch (IOException e) {System.out.print(e);} |
|
52 |
|
|
53 |
try { |
|
54 |
ser.setSerialPortParams(19200, SerialPort.DATABITS_8, |
|
55 |
SerialPort.STOPBITS_1, |
|
56 |
SerialPort.PARITY_NONE); |
|
57 |
} catch (UnsupportedCommOperationException e) {} |
|
58 |
|
|
59 |
while (true) { |
|
60 |
|
|
61 |
try { |
|
62 |
if (inSt.available() > 0) { |
|
63 |
System.out.print((char)inSt.read()); |
|
64 |
} |
|
65 |
} catch (IOException e) {System.out.print(e);} |
|
66 |
|
|
67 |
} |
|
68 |
|
|
69 |
} |
|
70 |
|
|
71 |
} |
Also available in: Unified diff