开发过程中碰到通过串口连接设备的需求,记录一下。在spring环境下。在启动项目时打开串口。
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
@Configuration
public class RS485Config {
private final static Logger LOGGER = LoggerFactory.getLogger(RS485Config.class);
static CommPortIdentifier portId;
static Enumeration<?> portList;
// 从串口输入流
InputStream inputStream;
// 向串口输出流
public static OutputStream outputStream;
// 串口的引用
static SerialPort serialPort;
@Value("${rs485enableFlag:false}")
private boolean rs485enableFlag = false;
@PostConstruct
public void openPorts() {
if (!rs485enableFlag) {
LOGGER.info("********** 串口设备未启用,请检查rs485enableFlag配置 **********");
return;
}
RS485Config cRead = new RS485Config();
int i = cRead.startComPort();
if (i == 1) {
LOGGER.info("********** 成功打开串口 **********");
} else {
return;
}
}
/**
* 通过程序打开COM3串口,设置监听器以及相关的参数
*
* @return 返回1 表示端口打开成功,返回 0表示端口打开失败
*/
public int startComPort() {
// 通过串口通信管理类获得当前连接上的串口列表
portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
// 获取相应串口对象
portId = (CommPortIdentifier) portList.nextElement();
LOGGER.info("********** 设备类型 [{}] **********", portId.getPortType());
LOGGER.info("********** 设备名称 [{}] **********", portId.getName());
// 判断端口类型是否为串口
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
// 判断如果COM3串口存在,就打开该串口
if (portId.getName().equals(portId.getName())){
try {
// 打开串口名字为COM_3(名字任意),延迟为1000毫秒
serialPort = (SerialPort) portId.open(portId.getName(), 1000);
} catch (PortInUseException e) {
LOGGER.error("********** 打开端口失败 **********", e);
return 0;
}
// 设置当前串口的输入输出流
try {
inputStream = serialPort.getInputStream();
outputStream = serialPort.getOutputStream();
} catch (IOException e) {
LOGGER.error("********** 打开端口失败 **********", e);
return 0;
}
// 设置监听器生效,即:当有数据时通知
serialPort.notifyOnDataAvailable(true);
// 设置串口的一些读写参数
try {
// 比特率、数据位、停止位、奇偶校验位-------比特率每个设备可能不一样,根据设备本身的值设置
serialPort.setSerialPortParams(9600,
SerialPort.DATABITS_8, SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
} catch (UnsupportedCommOperationException e) {
LOGGER.error("********** 打开端口失败 **********", e);
return 0;
}
return 1;
}
}
}
return 0;
}
}
使用的地方获取串口输入输出流即可,关键代码如下
if (RS485Config.outputStream != null) {
//order 是要发送相关指令,根据实际情况来。。循环发送,for循环略。
RS485Config.outputStream.write(order.getBytes());
RS485Config.outputStream.flush();
while ((c = RS485Config.inputStream.read()) != -1) {
sb.append((char)c);
}
String reciveMsg =sb.toString();
//全部转成小写
if (!reciveMsg.toLowerCase().contains("OK".toLowerCase())) {
logger.info("指令发送失败 response: {}", sb);
break;
} else {
logger.debug("指令发送成功 response: {}", sb);
continue;
}
}
循环检验设备比特率的方法,有的设备不知道比特率是多少,列举常用比特率多次尝试
mport gnu.io.CommPortIdentifier;
import gnu.io.SerialPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class CommUtil {
private static final Logger logger = LoggerFactory.getLogger(CommUtil.class);
private static final int[] baudRates = {9600, 19200, 57600, 115200};//常用比特率
public static void getCommPortDevices() {
logger.info("Detecting serial comm devices...");
Enumeration<CommPortIdentifier> portList = CommPortIdentifier.getPortIdentifiers();
while (portList.hasMoreElements()) {
CommPortIdentifier portId = portList.nextElement(); //portId = (CommPortIdentifier) portList.nextElement();
if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) {
logger.info("Found serial comm device: {}", portId.getName());
for (int baudRate : baudRates) {
logger.info(" Trying at {} ...", baudRate);
SerialPort serialPort = null;
try {
String re = "at+cscs=\"gsm\"\r"; //硬件相关指令,根据实际设备来填写
serialPort = (SerialPort) portId.open(portId.getName(), 1000);
serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_RTSCTS_IN);
serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
InputStream inStream = serialPort.getInputStream();
OutputStream outStream = serialPort.getOutputStream();
serialPort.enableReceiveTimeout(1000);
int c;
while ((c = inStream.read()) != -1) {
// do nothing;
}
outStream.write(re.getBytes());
StringBuilder sb = new StringBuilder();
while ((c = inStream.read()) != -1) {
sb.append((char)c);
}
if (!sb.toString().contains("OK")) {
logger.info(" No device detected, response: {}", sb);
} else {
logger.info(" Device found,");
sb.setLength(0); // clear the StringBuilder
outStream.write("AT+CGMM\r".getBytes());
while ((c = inStream.read()) != -1) {
sb.append((char)c);
}
String model = sb.toString()
.replaceAll("(\n|\r|AT\\+CGMM|OK)", "")
.replaceAll("\\s+", " ").trim();
logger.info(" Device model: {}", model);
break;
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
} finally {
if (serialPort != null) {
serialPort.close();
}
}
}
}
}
//return devices;
}
public static void main(String[] args) {
getCommPortDevices();
//logger.info("size: {}", devices.size());
}
}