1 关键代码
package com.stm.room.thirdApi.utils;
import gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import gnu.io.SerialPortEvent;
import gnu.io.SerialPortEventListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Enumeration;
public class SerialCommunication implements SerialPortEventListener {
private static final Logger logger = LogManager.getLogger(SerialCommunication.class);
private SerialPort serialPort;
private BufferedReader input;
private OutputStream output;
private static final int TIMEOUT = 2000; // 连接超时时间
private String portName; // 串口名称
private int baudRate; // 波特率
private boolean connected = false;
private SerialDataListener dataListener; // 数据监听器
private boolean readLine = true;
private boolean readHex = false; // 是否以16进制格式读取
private Integer sleepTime = null; //读取延时时间
public Integer getSleepTime() {
return sleepTime;
}
public void setSleepTime(Integer sleepTime) {
this.sleepTime = sleepTime;
}
public boolean isReadHex() {
return readHex;
}
public void setReadHex(boolean readHex) {
this.readHex = readHex;
}
public boolean isReadLine() {
return readLine;
}
public void setReadLine(boolean readLine) {
this.readLine = readLine;
}
public SerialCommunication(String portName, int baudRate) {
this.portName = portName;
this.baudRate = baudRate;
}
// 设置数据监听器
public void setDataListener(SerialDataListener dataListener) {
this.dataListener = dataListener;
}
// 初始化串口
public void initialize() {
try {
// 获取串口标识
CommPortIdentifier portId = findPortIdentifier();
if (portId == null) {
logger.error("Could not find COM port: {}", portName);
return;
}
// 打开串口
openSerialPort(portId);
// 获取输入输出流
input = new BufferedReader(new InputStreamReader(serialPort.getInputStream(), "UTF-8"));
output = serialPort.getOutputStream();
// 添加事件监听器
setupEventListener();
connected = true;
logger.info("Connected to {} at {} baud", portName, baudRate);
} catch (Exception e) {
logger.error("Error initializing serial port: {}", e.getMessage(), e);
reconnect();
}
}
private CommPortIdentifier findPortIdentifier() {
Enumeration<?> portEnum = CommPortIdentifier.getPortIdentifiers();
while (portEnum.hasMoreElements()) {
CommPortIdentifier currPortId = (CommPortIdentifier) portEnum.nextElement();
if (currPortId.getName().equals(portName)) {
return currPortId;
}
}
return null;
}
private void openSerialPort(CommPortIdentifier portId) throws Exception {
serialPort = (SerialPort) portId.open(this.getClass().getName(), TIMEOUT);
serialPort.setSerialPortParams(baudRate,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
}
private void setupEventListener() throws Exception {
serialPort.addEventListener(this);
serialPort.notifyOnDataAvailable(true);
}
// 串口事件监听
@Override
public void serialEvent(SerialPortEvent event) {
if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
try {
if (sleepTime != null) {
Thread.sleep(sleepTime);
}
String receivedData = readDataFromSerial();
if (receivedData != null && !receivedData.isEmpty()) {
processReceivedData(receivedData);
}
} catch (Exception e) {
logger.error("Error reading from serial port: {}", e.getMessage(), e);
reconnect();
}
}
}
private String readDataFromSerial() throws Exception {
if (readHex) {
return readHexData();
} else if (readLine) {
return readLineData();
} else {
return readRawData();
}
}
private String readHexData() throws Exception {
StringBuilder hexBuffer = new StringBuilder();
byte[] buffer = new byte[1024];
int bytesRead;
while (serialPort.getInputStream().available() > 0 &&
(bytesRead = serialPort.getInputStream().read(buffer)) != -1) {
for (int i = 0; i < bytesRead; i++) {
hexBuffer.append(String.format("%02X ", buffer[i]));
}
}
return hexBuffer.toString().trim();
}
private String readLineData() throws Exception {
StringBuilder buffer = new StringBuilder();
String line;
while (serialPort.getInputStream().available() > 0 &&
input.ready() &&
(line = input.readLine()) != null) {
buffer.append(line).append("\n");
}
return buffer.toString().trim();
}
private String readRawData() throws Exception {
StringBuilder buffer = new StringBuilder();
char[] cache = new char[1024];
int bytesRead;
while (serialPort.getInputStream().available() > 0 &&
(bytesRead = input.read(cache, 0, cache.length)) != -1) {
buffer.append(new String(cache, 0, bytesRead));
}
return buffer.toString().trim();
}
private void processReceivedData(String receivedData) {
logger.info("Received: {}", receivedData);
if (dataListener != null) {
if (readHex) {
dataListener.onDataReceived(receivedData);
} else {
// 文本数据按行回调
for (String dataLine : receivedData.split("\n")) {
dataListener.onDataReceived(dataLine);
}
}
}
}
// 发送数据
public void sendData(String data) {
try {
if (connected) {
output.write(data.getBytes());
output.flush();
logger.info("Sent: {}", data);
} else {
logger.error("Not connected to serial port.");
}
} catch (Exception e) {
logger.error("Error sending data: {}", e.getMessage(), e);
reconnect();
}
}
public void sendData(byte[] data) {
try {
if (connected) {
output.write(data);
output.flush();
if (this.isReadHex()) {
logger.info("Sent hex data: {}", bytesToHex(data));
} else {
logger.info("Sent Msg byte.size {} data: {}", data.length, new String(data, "UTF-8"));
}
} else {
logger.error("Not connected to serial port.");
}
} catch (Exception e) {
logger.error("Error sending data: {}", e.getMessage(), e);
reconnect();
}
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
return sb.toString().trim();
}
// 关闭串口
public synchronized void close() {
try {
if (serialPort != null) {
serialPort.removeEventListener();
if (input != null) input.close();
if (output != null) output.close();
serialPort.close();
connected = false;
logger.info("Disconnected from {}", portName);
}
} catch (Exception e) {
logger.error("Error closing serial port: {}", e.getMessage(), e);
}
}
// 掉线重连
private void reconnect() {
close();
logger.info("Attempting to reconnect in 5 seconds...");
try {
Thread.sleep(5000);
initialize();
} catch (InterruptedException e) {
logger.error("Reconnection interrupted: {}", e.getMessage(), e);
Thread.currentThread().interrupt();
}
}
public static void main(String[] args) {
test();
}
private static void test() {
// 默认串口号和波特率
String portName = "COM3";
int baudRate = 9600;
// 创建串口通信实例
SerialCommunication serialComm = new SerialCommunication(portName, baudRate);
serialComm.setReadHex(true); // 设置为16进制读取模式
serialComm.setSleepTime(500);
// 设置数据监听器
serialComm.setDataListener(data -> {
System.out.println("Hex data received: " + data);
// 这里可以添加16进制数据的处理逻辑
});
// 初始化串口
serialComm.initialize();
// 示例:发送16进制数据
try {
serialComm.sendData(SerialTool.hex2Bytes("EFAA01AA0300ADEF55"));
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.error("Main thread interrupted", e);
Thread.currentThread().interrupt();
} finally {
serialComm.close();
}
}
}
2 接口
package com.stm.room.thirdApi.utils;
public interface SerialDataListener {
void onDataReceived(String data);
}
3 需要用的jar和dll
mfz-rxtx-2.2-20081207-win-x64 自行下载