rxtx取代javax.comm实现Java跨平台设备端口通信




rxtx取代javax.comm实现Java跨平台设备端口通信(转)

 

 

 

来源于http://blog.ednchina.com/hotpower/182484/message.aspx

 

通过修改sample例程,使用observer模式实现串口通信数据的订阅读取.

以下为俺的原创程序:

实现功能如下:

1. 在windows中监听指定的串口

2. observer模式订阅端口数据,可以有多个数据监听者同时接收数据

 

先到sun网站上下载串口通信库

http://java.sun.com/products/javacomm/index.jsp

再下载windows中的dll库

http://www.rxtx.org/

java实现源程序如下

 

------------------ 1 ---------------------

package serial;

import gnu.io.SerialPort;

import java.util.HashMap;

public class CommTest {

 /**
  * windows中串口通信程序需要rxtxSerial.dll的支持,放到D:\jdk1.5\bin目录下即可
  */
 public static void main(String[] args) {
  HashMap<String, Comparable> params = new HashMap<String, Comparable>();
  params.put(SerialReader.PARAMS_PORT, "COM8"); // 端口名称
  params.put(SerialReader.PARAMS_RATE, 9600); // 波特率
  params.put(SerialReader.PARAMS_TIMEOUT, 1000); // 设备超时时间 1秒
  params.put(SerialReader.PARAMS_DELAY, 200); // 端口数据准备时间 1秒
  params.put(SerialReader.PARAMS_DATABITS, SerialPort.DATABITS_8); // 数据位
  params.put(SerialReader.PARAMS_STOPBITS, SerialPort.STOPBITS_1); // 停止位
  params.put(SerialReader.PARAMS_PARITY, SerialPort.PARITY_NONE); // 无奇偶校验
  SerialReader sr = new SerialReader(params);

  CommDataObserver bob = new CommDataObserver("bob");
  CommDataObserver joe = new CommDataObserver("joe");
  sr.addObserver(joe);
  sr.addObserver(bob);
 }
}

 

---------------- 2 -----------------

package serial;

import gnu.io.CommPort;
import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import gnu.io.UnsupportedCommOperationException;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Observable;
import java.util.TooManyListenersException;

/**
 * 串口数据读取类,用于windows的串口数据读取
 *
 *
 * @author Macro Lu
 * @version 2007-4-4
 */
public class SerialReader extends Observable implements Runnable, SerialPortEventListener {
 static CommPortIdentifier portId;

 int delayRead = 200;

 int numBytes; // buffer中的实际数据字节数

 private static byte[] readBuffer = new byte[4096]; // 4k的buffer空间,缓存串口读入的数据

 static Enumeration portList;

 InputStream inputStream;

 SerialPort serialPort;

 HashMap serialParams;

 // 端口读入数据事件触发后,等待n毫秒后再读取,以便让数据一次性读完
 public static final String PARAMS_DELAY = "delay read"; // 延时等待端口数据准备的时间

 public static final String PARAMS_TIMEOUT = "timeout"; // 超时时间

 public static final String PARAMS_PORT = "port name"; // 端口名称

 public static final String PARAMS_DATABITS = "data bits"; // 数据位

 public static final String PARAMS_STOPBITS = "stop bits"; // 停止位

 public static final String PARAMS_PARITY = "parity"; // 奇偶校验

 public static final String PARAMS_RATE = "rate"; // 波特率

 /**
  * 初始化端口操作的参数.
  *
  *
  * @see
  */
 public SerialReader(HashMap params) {
  serialParams = params;
  init();

 }

 private void init() {
  try {
   // 参数初始化
   int timeout = Integer.parseInt(serialParams.get(PARAMS_TIMEOUT).toString());
   int rate = Integer.parseInt(serialParams.get(PARAMS_RATE).toString());
   int dataBits = Integer.parseInt(serialParams.get(PARAMS_DATABITS).toString());
   int stopBits = Integer.parseInt(serialParams.get(PARAMS_STOPBITS).toString());
   int parity = Integer.parseInt(serialParams.get(PARAMS_PARITY).toString());
   delayRead = Integer.parseInt(serialParams.get(PARAMS_DELAY).toString());

   String port = serialParams.get(PARAMS_PORT).toString();

   // 打开端口
   portId = CommPortIdentifier.getPortIdentifier(port);
   serialPort = (SerialPort) portId.open("SerialReader", timeout);
   inputStream = serialPort.getInputStream();
   serialPort.addEventListener(this);
   serialPort.notifyOnDataAvailable(true);
   serialPort.setSerialPortParams(rate, dataBits, stopBits, parity);

  } catch (PortInUseException e) {
   System.out.println("端口已经被占用!");
   e.printStackTrace();
  } catch (TooManyListenersException e) {
   System.out.println("端口监听者过多!");
   e.printStackTrace();
  } catch (UnsupportedCommOperationException e) {
   System.out.println("端口操作命令不支持!");
   e.printStackTrace();
  } catch (NoSuchPortException e) {
   System.out.println("端口不存在!");
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
  Thread readThread = new Thread(this);
  readThread.start();
 }

 /**
  * Method declaration
  *
  *
  * @see
  */
 public void run() {
  try {
   Thread.sleep(100);
  } catch (InterruptedException e) {
  }
 }

 /**
  * Method declaration
  *
  *
  * @param event
  *
  * @see
  */
 public void serialEvent(SerialPortEvent event) {
  try {
   // 等待1秒钟让串口把数据全部接收后在处理
   Thread.sleep(delayRead);
   System.out.print("serialEvent[" + event.getEventType() + "]    ");
  } catch (InterruptedException e) {
   e.printStackTrace();
  }

  switch (event.getEventType()) {

  case SerialPortEvent.BI: // 10
  case SerialPortEvent.OE: // 7
  case SerialPortEvent.FE: // 9
  case SerialPortEvent.PE: // 8
  case SerialPortEvent.CD: // 6
  case SerialPortEvent.CTS: // 3
  case SerialPortEvent.DSR: // 4
  case SerialPortEvent.RI: // 5
  case SerialPortEvent.OUTPUT_BUFFER_EMPTY: // 2
   break;
  case SerialPortEvent.DATA_AVAILABLE: // 1
   try {
    // 多次读取,将所有数据读入
    // while (inputStream.available() > 0) {
    // numBytes = inputStream.read(readBuffer);
    // }
    numBytes = inputStream.read(readBuffer);
    changeMessage(readBuffer, numBytes);
   } catch (IOException e) {
    e.printStackTrace();
   }
   break;
  }
 }

 // 通过observer pattern将收到的数据发送给observer
 // 将buffer中的空字节删除后再发送更新消息,通知观察者
 public void changeMessage(byte[] message, int length) {
  setChanged();
  byte[] temp = new byte[length];
  System.arraycopy(message, 0, temp, 0, length);
  // System.out.println("msg[" + numBytes + "]: [" + new String(temp) + "]");
  notifyObservers(temp);
 }

 static void listPorts() {
  Enumeration portEnum = CommPortIdentifier.getPortIdentifiers();
  while (portEnum.hasMoreElements()) {
   CommPortIdentifier portIdentifier = (CommPortIdentifier) portEnum.nextElement();
   System.out.println(portIdentifier.getName() + " - "
     + getPortTypeName(portIdentifier.getPortType()));
  }
 }

 static String getPortTypeName(int portType) {
  switch (portType) {
  case CommPortIdentifier.PORT_I2C:
   return "I2C";
  case CommPortIdentifier.PORT_PARALLEL:
   return "Parallel";
  case CommPortIdentifier.PORT_RAW:
   return "Raw";
  case CommPortIdentifier.PORT_RS485:
   return "RS485";
  case CommPortIdentifier.PORT_SERIAL:
   return "Serial";
  default:
   return "unknown type";
  }
 }

 /**
  * @return A HashSet containing the CommPortIdentifier for all serial ports that are not
  *         currently being used.
  */
 public static HashSet<CommPortIdentifier> getAvailableSerialPorts() {
  HashSet<CommPortIdentifier> h = new HashSet<CommPortIdentifier>();
  Enumeration thePorts = CommPortIdentifier.getPortIdentifiers();
  while (thePorts.hasMoreElements()) {
   CommPortIdentifier com = (CommPortIdentifier) thePorts.nextElement();
   switch (com.getPortType()) {
   case CommPortIdentifier.PORT_SERIAL:
    try {
     CommPort thePort = com.open("CommUtil", 50);
     thePort.close();
     h.add(com);
    } catch (PortInUseException e) {

     System.out.println("Port, " + com.getName() + ", is in use.");

    } catch (Exception e) {
     System.out.println("Failed to open port " + com.getName() + e);
    }
   }
  }
  return h;
 }

}

 

---------- 3 -----------------

package serial;

import java.util.Observable;
import java.util.Observer;

class CommDataObserver implements Observer {
 String name;

 public CommDataObserver(String name) {
  this.name = name;
 }

 public void update(Observable o, Object arg) {
  System.out.println("[" + name + "] GetMessage:\n [" + new String((byte[]) arg) + "]");
 }
}

 

你可能感兴趣的:(java,thread,jsp,windows,sun)