1.Netty使用JSerialComm进行串口读取(一)
Netty本身集成了RXTX串口库,如下图,虽说未来要移除不支持,但是5版本的还存在,4版本的现在还一直存在,还是可以使用的。
不过这个库好久没更新了,同时对一些小众平台支持麻烦。
相反JSerialComm库更新积极,对一些小众平台支持度也很好。不过Netty本身没有集成JSerialComm串口库,不过已经有人做了Netty-Transport-jSerialComm开源项目支持该需求。在Netty官网https://netty.io/wiki/related-projects.html中推荐了该开源工程:
-
Netty-Transport-jSerialComm is a serial port transport for Netty using the jSerialComm library.
-
github地址:https://github.com/Ziver/Netty-Transport-jSerialComm
在github上查看项目6年多没有更新了,Netty还是引用得4.1.13.Final版本,已经很早的版本了。
SpringBoot2.7.4使用的是4.1.82.Final版本,最开始我以为只要把Netty版本更新一下就可以了,但是实际测试时发现升版本后的表现根本没法实际使用,所以就有了下列一系列折腾。
1.1. 期望的功能
我的使用要求是对方串口不提供心跳之类的数据,如果一定时间内没有数据可以提示读取超时信息,不能退出程序,有数据时还可正常接收串口数据。最终的使用效果如下图:
1.2. 测试代码修改
使用netty-transport-jserialcomm测试时,首先修改JSerialCommClientHandler类的实现,可以将接收的信息返回发送。修改如下:
public class JSerialCommClientHandler extends SimpleChannelInboundHandler<String> {
private static final ByteBuf HEARTBEAT_SEQUENCE = Unpooled
.unreleasableBuffer(Unpooled.copiedBuffer("Heartbeat",
CharsetUtil.UTF_8)); // 1
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush("AT\r\n");
}
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
if ("OK".equals(msg)) {
System.out.println("Serial port responded to AT");
} else {
System.out.println("Serial port responded with not-OK: " + msg);
}
//ctx.close();
ctx.writeAndFlush("RCV: "+msg+"\r\n");
}
}
串口助手的测试效果如下:
最终项目结构如下图:
红框内的文件是在开源项目基础上新增的类。
1.3. 遇见问题的介绍
使用Maven依赖netty 4.1.13.Final版本时,程序可以一直读取数据,即使没有数据也不会退出程序,但是使用 4.1.82.Final版本时串口如果在一定时间内如果没有数据,程序抛出读取超时异常并退出程序。
netty-transport-jserialcomm项目默认使用的Maven依赖是netty 4.1.13.Final版本,如下所示:
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>4.1.13.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>4.1.13.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>4.1.13.Final</version>
</dependency>
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>1.3.11</version>
</dependency>
</dependencies>
串口测试程序可以一直阻塞一直读取数据,如下图所示:
使用Netty 4.1.82.Final版本时,Maven依赖如下:
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.82.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>4.1.82.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>4.1.82.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>4.1.82.Final</version>
</dependency>
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
运行串口测试程序如果在一定时间内(默认为1秒,不过可以设置)没有数据读取,程序将抛出读取超时异常并退出程序运行。
警告: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
com.fazecast.jSerialComm**.SerialPortTimeoutException**: The read operation timed out before any data was returned.
其实此处有两个问题:
第一个问题:串口读取超时异常一路传播到最后也没有处理。
第二个问题:即使处理了该异常,程序仍然退出,这不能满足一些实际使用要求需求。该问题与设置很长的读取超时时间没关系,无论多长到时间后总会退出。
最终修改好的库与测试代码下载地址为:《Netty使用JSerialComm进行串口读取的更新库源代码及问题修正》
介绍如下:
Netty-Transport-jSerialComm升级版本(v2.0.0)
更新如下:
1)依赖的Netty从 4.1.13.Final版本升级到 4.1.82.Final版本
2)依赖的jSerialComm 从1.3.11版本升级到2.9.2版本
3)处理两个问题:
第一个问题是:串口读取超时异常一路传播到最后也没有处理。
第二个问题是:即使处理了该异常,测试程序仍然退出,这不能满足一些实际使用要求需求。该问题与设置很长的读取超时时间没关系,无论多长到时间后总会退出。
4)打包生成 netty-transport-jserialcomm-2.0.0.jar、netty-transport-jserialcomm-2.0.0-javadoc.jar、netty-transport-jserialcomm-2.0.0-sources.jar三个包