JavaWeb 用于windows的串口数据读取

串口数据读取类,用于windows的串口数据读取;

1.例如观察者为羊,被观察者为狼 ,模仿的场景为狼叫羊跑,可参考博客:

https://blog.csdn.net/dada360778512/article/details/6977758

2.模拟串口传输数据,需要两个工具,Virtual Serial Port Driver、串口调试助手;可参考:

https://jingyan.baidu.com/article/046a7b3eae7028f9c27fa9f7.html

3.基于RXTX(提供串口和并口通信)开源类库对串口进行操作的。具体配置,详见:

https://blog.csdn.net/liu4071325/article/details/53392218

必备插件/工具包:
1.项目里引用:  RXTXcomm.jar

2.windows服务器需要以下三个文件:
       \JDK目录\jre\lib\ext ---> RXTXcomm.jar
      \JDK目录\bin ---> rxtxParallel.dll 和 rxtxSerial.dll

2.Linux服务器需要放置以下三个文件

       \JDK目录\jre\lib\ext ---> RXTXcomm.jar
      \JDK目录\bin --->librxtxParallel.so 和 librxtxSerial.so

感谢分享!

代码:

1.创建被观察者 SerialReader.java 

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的串口数据读取

* * 声明被观察者SerialReader,继承Observable
* 观察者,继承Observer
* * Observer模式 主要是观察者与被观察者之间的关系。
* */ 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"; // 波特率 public SerialReader() { } /** * 初始化端口操作的参数. * * @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); EWeightConstant.IS_OPEN_PORT = true; 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(); } public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } 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中的空字节删除后再发送更新消息,通知观察者 private String temp1 = ""; public void changeMessage(byte[] message, int length) { setChanged(); byte[] temp = new byte[length]; System.arraycopy(message, 0, temp, 0, length); // 判断数据是否稳定,稳定则只监听不执行更新数据 if (!"".equals(temp1)) { if (!temp1.equals(new String(temp).trim())) { temp1 = new String(temp).trim(); notifyObservers(temp); // System.out.println("msg[" + numBytes + "]: [" + new // String(temp).trim() +"]"); } } else { temp1 = new String(temp).trim(); 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())); } } /** * 读取所有串口名字 */ public static String getPortName() { CommPortIdentifier portId; Enumeration en = CommPortIdentifier.getPortIdentifiers(); while (en.hasMoreElements()) { portId = (CommPortIdentifier) en.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { return portId.getName(); } } return ""; } /** * 读取所有串口名字 */ public static void closePort() { CommPortIdentifier portId; Enumeration en = CommPortIdentifier.getPortIdentifiers(); while (en.hasMoreElements()) { portId = (CommPortIdentifier) en.nextElement(); if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { } } } 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"; } } public static HashSet getAvailableSerialPorts() { HashSet h = new HashSet(); 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; } }

2.创建观察者CommDataObserver.java


import java.util.Observable;
import java.util.Observer;
/**
 * 观察类,继承Observer
* 创建一个观察类,该观察类有自己的name名称 * */ public class CommDataObserver implements Observer { private String name; public CommDataObserver() { } public CommDataObserver(String name) { this.name = name; } /** * 监控串口,获取串口数据 */ public void update(Observable o, Object arg) { //获取串口返回数据 String weight = new String((byte[]) arg).trim(); //将获取到的数据,赋值到全局变量里,以便可以调用该数据 EWeightConstant.GOOD_WEIGHT = weight; //testing start 根据串口类型不同,返回的数据格式也不尽相同,此处调试打印而已 {{ System.out.println("weight="+weight); StringBuilder sb = new StringBuilder(weight);// 0.000或者00.000 sb.insert(weight.length() - 3, "."); System.out.println(sb.toString() + "kg"); //testing end }} } public String getName() { return name; } public void setName(String name) { this.name = name; } }

3.初始化端口数据,并创建被观察者和观察者,并加入观察GetWeightUtil.java


import java.util.HashMap;

import gnu.io.SerialPort;
/**
 * 获取串口工具类
 * 此处声明观察者和被观察者
 */
public class GetWeightUtil {
	
	/**
	 * 串口设置, 初始化端口数据
	 * @param com 端口
	 */
	public static void comConfig(String com) {
		//存储端口数据
		HashMap params = new HashMap();
		// 端口名称
		params.put(SerialReader.PARAMS_PORT, com);
		// 波特率
		params.put(SerialReader.PARAMS_RATE, 9600);
		// 设备超时时间 1秒
		params.put(SerialReader.PARAMS_TIMEOUT, 1000); 
		// 端口数据准备时间 1秒
		params.put(SerialReader.PARAMS_DELAY, 200); 
		// 数据位
		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 serialReader = new SerialReader(params);
		//创建观察者
		CommDataObserver obServer = new CommDataObserver("电子秤");
		//添加一个观察者,加入观察
		serialReader.addObserver(obServer);
		
		//TODO 调试用,输出到控制台 显示所有串口号
		SerialReader.listPorts();
	}
	
	public static void main(String[] args) throws Exception{
		comConfig("COM1");
		while(true){
			Thread.sleep(1000);
			System.out.println(EWeightConstant.GOOD_WEIGHT);	
		}
		
	}
}

4.EWeightConstant.java

/**
 * 记录串口的基础信息 全局变量
 *
 */
public class EWeightConstant {
	/**
	 * 串口数据
	 */
	public static String GOOD_WEIGHT = "0";
	/**
	 * 串口是否打开
	 */
	public static Boolean IS_OPEN_PORT = false;
}

5.Controller方法调用获取串口数据,并作用于业务开发

/**
	 * 前端 调用该方法,用于获取串口返回数据
	 * 如果想一直调用该串口返回数据,JS前端可做轮询
	 * @param request
	 * @return
	 */
    @RequestMapping(value = "/getWeight", method = RequestMethod.GET)
    @ResponseBody
    public String getWeight(HttpServletRequest request) {
    	// 获取数据的串口
    	final String E_WEIGHT_COM = "COM1";
    	try{
    		if(!EWeightConstant.IS_OPEN_PORT){
        		GetWeightUtil.comConfig(E_WEIGHT_COM);	
        	}
    	}catch(Exception e){
    		e.printStackTrace();
    	}
    	//全局变量,记录串口数据
    	String weight = EWeightConstant.GOOD_WEIGHT;
    	//输出串口数据,查看串口数据格式
    	System.out.println("获取串口原始数据格式  = " + weight);
    	if(StringUtils.equals(weight, "0")){
    		return weight;
    	}
    	//截取字符串,获取要取得数据部分
    	weight = weight.substring(weight.indexOf("+")+1, weight.indexOf("  "));
    	System.out.println("最终数据,返回截取后的数据="+weight);
    	return weight;
    }

 

你可能感兴趣的:(JAVA基础)