我是靠谱客的博主 开放诺言,最近开发中收集的这篇文章主要介绍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目录jrelibext ---> RXTXcomm.jar
      JDK目录bin ---> rxtxParallel.dll 和 rxtxSerial.dll

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

       JDK目录jrelibext ---> 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;

/**
 * <p>串口数据读取类,用于windows的串口数据读取</p>
 * 
 * 声明被观察者SerialReader,继承Observable<br/>
 * 观察者,继承Observer<br/>
 * 
 * Observer模式  主要是观察者与被观察者之间的关系。<br/>
 * 
 */
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<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;
	}
}

2.创建观察者CommDataObserver.java


import java.util.Observable;
import java.util.Observer;
/**
 * 观察类,继承Observer<br/>
 * 创建一个观察类,该观察类有自己的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<String, Comparable> params = new HashMap<String, Comparable>();
		// 端口名称
		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;
    }

 

最后

以上就是开放诺言为你收集整理的JavaWeb 用于windows的串口数据读取的全部内容,希望文章能够帮你解决JavaWeb 用于windows的串口数据读取所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(41)

评论列表共有 0 条评论

立即
投稿
返回
顶部