使用RXTX库我在serialEvent上遇到过(当数据到达时)我不知道如何引用已经运行的主应用程序。
我发现它的工作方式是在endOfMessageFlag到达时关闭串口(所以我没有得到"锁定文件已存在错误"当我尝试之后发送更多数据)并创建处理该消息的类的新实例。
我不喜欢这个"解决方案"因为我害怕效率不高,如果有很多消息一起到达,我甚至可能会遇到堆栈溢出异常。
我在raspbian上使用rxtx-2.2-pre2。
我有三个类,一个是main,一个是协议,另一个是处理串口(initialize,send,(receive)serialEvent)。
主类snipet:
package app;
public class MainClass {
private MyProtocol myProt = new MyProtocol();
public boolean newCDevices = false;
public int newDevices = 0;
public static void main(String[] args) throws Exception {
System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyAMA0");
MainClass myMain = new MainClass();
monitorS.findDevices();
}
public void messageReceived(byte[] message){
myProt.processMessage(message);
myProt.sendAcknowledge();
}
private void findDevices(){
myProt.findNewDevices();
}
}
协议类snipet:
package serialcomms;
public class MyProtocol {
private static SerialComms messageSender = new SerialComms();
// sends acknowledge onReceive.
public void sendAcknowledge(){
byte[] messageBytes = composeMessage(acknowledge);
if(messageSender.initialize()){
messageSender.sendData(messageBytes);
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
messageSender.close();
}
}
//sends broadcast message asking all unidentified devices to make contact.
public void findNewDevices(){
byte[] messageBytes = composeMessage(findDevicesMessage);
if(messageSender.initialize()){
messageSender.sendData(messageBytes);
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
messageSender.close();
}
}
}
处理串口的类: (基于这个例子btw:http://www.drdobbs.com/jvm/control-an-arduino-from-java/240163864)
package serialcomms;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.time.Clock;
import java.util.Enumeration;
public class SerialComms implements SerialPortEventListener {
SerialPort serialPort = null;
private static final String PORT_NAMES[] = {
// "/dev/tty.usbmodem", // Mac OS X
// "/dev/usbdev", // Linux
"/dev/ttyAMA0", // Raspberry
// "/dev/tty", // Linux
// "/dev/serial", // Linux
// "COM3", // Windows
};
private String appName;
private BufferedReader input;
private OutputStream output;
private int tail = 0;
int lengthArray = 50;
public byte[] buffer = new byte[lengthArray];
private static final int TIME_OUT = 1000; // Port open timeout
private static final int DATA_RATE = 9600; // Arduino serial port
private static final int BYTE_START = 100;
private static final int BYTE_END = 120;
private final byte startOfMessage = (byte)BYTE_START;
private final byte endOfMessage = (byte)BYTE_END;
public SerialComms(){
appName = getClass().getName();
}
public boolean initialize() {
try {
CommPortIdentifier portId = null;
Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
// Enumerate system ports and try connecting to Arduino over each
//
System.out.println( "Trying:");
while (portId == null && portEnum.hasMoreElements()) {
// Iterate through your host computer's serial port IDs
//
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
System.out.println( " port" + currPortId.getName() );
for (String portName : PORT_NAMES) {
if ( currPortId.getName().equals(portName)
|| currPortId.getName().startsWith(portName)) {
// Try to connect to the Arduino on this port
//
// Open serial port
serialPort = (SerialPort)currPortId.open(appName, TIME_OUT);
portId = currPortId;
System.out.println( "Connected on port" + currPortId.getName() );
break;
}
}
}
if (portId == null || serialPort == null) {
System.out.println("Oops... Could not connect to Arduino");
return false;
}
// set port parameters
serialPort.setSerialPortParams(DATA_RATE,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// add event listeners
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
// Give the Arduino some time
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
return true;
}
catch ( Exception e ) {
e.printStackTrace();
}
return false;
}
public void sendData(byte[] data) {
try {
System.out.println("Sending data: '" + data +"'");
// open the streams and send
output = serialPort.getOutputStream();
output.write( data );
}
catch (Exception e) {
System.err.println(e.toString());
System.exit(0);
}
}
//
// This should be called when you stop using the port
//
public synchronized void close() {
if ( serialPort != null ) {
serialPort.removeEventListener();
serialPort.close();
}
}
//
// Handle serial port event
//
public synchronized void serialEvent(SerialPortEvent oEvent) {
try {
while (oEvent.getEventType() == SerialPortEvent.DATA_AVAILABLE){
byte singleData = (byte)serialPort.getInputStream().read();
if (singleData == startOfMessage){
for(int i = 0; i < tail ; i++){
buffer[i] = 0x00;
}
tail = 0;
buffer[tail] = singleData;
tail++;
} else if(singleData == endOfMessage && tail <= buffer.length){
buffer[tail] = singleData;
tail++;
for(int i = 0; i< tail ; i++){
System.out.println(buffer[i]);
}
close(); //This are the lines that got it to
MainClass newMain = new MainClass(); //work. However I think there must
newMain.messageReceived(buffer); //be a better solution.
} else if(tail < buffer.length){
buffer[tail] = singleData;
tail++;
}
break;
default:
break;
}
}
catch (Exception e) {
System.err.println(e.toString());
}
}
}
在SerialComms上编辑了serialEvent方法,因此它将接收所有可用数据,而不必为接收的每个字节中断。
答案 0 :(得分:0)
我找到了一个更好,更简单的解决方案来解决我的问题,即在我的主类上声明一个静态的字节数组,然后将收到的消息存储在那里。
我将重新发布修改后的代码部分:
public class MainClass{
private static MyProtocol myProt = new MyProtocol();
public static byte[] message = new byte[50];
public boolean newMessage = false;
private boolean runApp = true;
public int newColectors = 0;
private static final int START_OF_MESAGE = 100;
public static void main(String[] args) throws Exception {
// TODO code application logic here
System.setProperty("gnu.io.rxtx.SerialPorts", "/dev/ttyAMA0");
MainClass myApp = new MainClass();
while(myApp.runApp){
if(myApp.checkMessageReceived()){
myProt.processMessage(message);
myProt.sendAcknowledge();
}
myApp.findNewCollectors();
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
}
}
public boolean checkMessageReceived(){
if(message[0]== (byte) START_OF_MESAGE){
newMessage = true;
}
return newMessage;
}
}
并添加串口处理程序类:
MainClass.message = buffer;
而不是:
close(); //This are the lines that got it to
MainClass newMain = new MainClass(); //work. However I think there must
newMain.messageReceived(buffer); //be a better solution.
数组数组是我计划用来处理消息并发的实际解决方案。 现在这样做:) 如果有人有更好的答案,我很乐意阅读。