- java version "1.8.0_231"
- Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
- Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
- # 官网 http://rxtx.qbang.org/wiki/index.php/Download
- # 版本 rxtx-2.2pre1-bins

- <dependencies>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.24</version>
- </dependency>
- <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
- <dependency>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- <version>4.1.42.Final</version>
- </dependency>
- </dependencies>
- package com.yushanma.config;
-
- import io.netty.channel.rxtx.RxtxChannelConfig;
- import lombok.Data;
-
- /**
- * desc
- *
- * @author Yushanma
- * @since 2023/6/4 17:20
- */
- @Data
- public final class ComConfig {
- /**
- * 串口名称,以COM开头(COM0、COM1、COM2等等)
- */
- private String serialPortName;
- /**
- * 波特率, 默认:9600
- */
- private int baudRate = 9600;
- /**
- * 数据位 默认8位
- * 可以设置的值:SerialPort.DATABITS_5、SerialPort.DATABITS_6、SerialPort.DATABITS_7、SerialPort.DATABITS_8
- */
- private RxtxChannelConfig.Databits dataBits = RxtxChannelConfig.Databits.DATABITS_8;
- /**
- * 停止位
- * 可以设置的值:SerialPort.STOPBITS_1、SerialPort.STOPBITS_2、SerialPort.STOPBITS_1_5
- */
- private RxtxChannelConfig.Stopbits stopBits = RxtxChannelConfig.Stopbits.STOPBITS_1;
- /**
- * 校验位
- * 可以设置的值:SerialPort.PARITY_NONE、SerialPort.PARITY_ODD、SerialPort.PARITY_EVEN、SerialPort.PARITY_MARK、SerialPort.PARITY_SPACE
- */
- private RxtxChannelConfig.Paritybit parity = RxtxChannelConfig.Paritybit.NONE;
- }
- package com.yushanma.utils;
-
- import java.util.List;
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.handler.codec.ByteToMessageDecoder;
-
- /**
- * 解码器
- *
- * @author Yushanma
- * @since 2023/6/4 17:17
- */
- public class ByteArrayDecoder extends ByteToMessageDecoder {
-
- @Override
- protected void decode(ChannelHandlerContext ctx, ByteBuf in, List throws Exception {
- // 标记一下当前的 readIndex 的位置
- in.markReaderIndex();
- int dataLength = in.readableBytes();
- byte[] array = new byte[dataLength];
- in.readBytes(array, 0, dataLength);
- if(array.length > 0){
- out.add(array);
- }
- }
- }
- package com.yushanma.utils;
-
- import io.netty.buffer.ByteBuf;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.handler.codec.MessageToByteEncoder;
-
- /**
- * 编码器
- *
- * @author Yushanma
- * @since 2023/6/4 17:18
- */
- public class ByteArrayEncoder extends MessageToByteEncoder<byte[]> {
-
- @Override
- protected void encode(ChannelHandlerContext ctx, byte[] msg, ByteBuf out) throws Exception {
- // 消息体,包含我们要发送的数据
- out.writeBytes(msg);
- }
- }
- package com.yushanma.handler;
-
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelHandler;
- import io.netty.channel.ChannelHandlerContext;
- import io.netty.channel.SimpleChannelInboundHandler;
- import io.netty.util.ReferenceCountUtil;
-
- import java.time.LocalDateTime;
-
- /**
- * Channel 事件处理器
- * 需要处理什么事件就重写 SimpleChannelInboundHandler 中对应的方法
- * @author Yushanma
- * @since 2023/6/4 17:19
- */
- @ChannelHandler.Sharable
- public class RxtxHandler extends SimpleChannelInboundHandler<byte[]> {
-
- /**
- * 当 COM 口接收到数据时
- * 根据不同的进制对数据包进行解码
- * 然后执行对应业务逻辑
- * @param ctx 上下文
- * @param msg 接收到的数据包
- * @throws Exception 异常
- */
- @Override
- protected void channelRead0(ChannelHandlerContext ctx, byte[] msg) throws Exception {
-
- // 十六进制发送编解码
- int dataLength = msg.length;
- ByteBuf buf = Unpooled.buffer(dataLength);
- buf.writeBytes(msg);
- System.out.println(LocalDateTime.now() + "接收到:");
- while(buf.isReadable()){
- System.out.print(buf.readByte() + " ");
- }
- System.out.println();
- // 释放资源
- ReferenceCountUtil.release(msg);
- }
- }
- package com.yushanma.server;
-
- import com.yushanma.config.ComConfig;
- import com.yushanma.handler.RxtxHandler;
- import com.yushanma.utils.ByteArrayDecoder;
- import com.yushanma.utils.ByteArrayEncoder;
- import io.netty.bootstrap.Bootstrap;
- import io.netty.buffer.ByteBuf;
- import io.netty.buffer.Unpooled;
- import io.netty.channel.ChannelFuture;
- import io.netty.channel.ChannelInitializer;
- import io.netty.channel.EventLoop;
- import io.netty.channel.EventLoopGroup;
- import io.netty.channel.oio.OioEventLoopGroup;
- import io.netty.channel.rxtx.RxtxChannel;
- import io.netty.channel.rxtx.RxtxDeviceAddress;
- import io.netty.util.concurrent.GenericFutureListener;
-
- import java.util.concurrent.CompletableFuture;
- import java.util.concurrent.Executors;
-
- /**
- * desc
- *
- * @author Yushanma
- * @since 2023/6/4 17:23
- */
- public class RxtxServer {
-
- private RxtxChannel channel;
-
- private ComConfig config;
-
- public RxtxServer(ComConfig config) {
- this.config = config;
- }
-
- public void createRxtx() throws Exception {
- // 串口使用阻塞io
- EventLoopGroup group = new OioEventLoopGroup();
- try {
- Bootstrap bootstrap = new Bootstrap();
- bootstrap.group(group)
- .channelFactory(() -> {
- RxtxChannel rxtxChannel = new RxtxChannel();
- rxtxChannel.config()
- .setBaudrate(config.getBaudRate()) // 波特率
- .setDatabits(config.getDataBits()) // 数据位
- .setParitybit(config.getParity()) // 校验位
- .setStopbits(config.getStopBits()); // 停止位
- return rxtxChannel;
- })
- .handler(new ChannelInitializer
() { - @Override
- protected void initChannel(RxtxChannel rxtxChannel) {
- rxtxChannel.pipeline().addLast(
- // 十六进制形式发送编解码
- new ByteArrayDecoder(),
- new ByteArrayEncoder(),
- new RxtxHandler()
- );
- }
- });
-
- ChannelFuture f = bootstrap.connect(new RxtxDeviceAddress(config.getSerialPortName())).sync();
- f.addListener(connectedListener);
-
- f.channel().closeFuture().sync();
- } finally {
- group.shutdownGracefully();
- }
- }
-
-
- // 连接监听
- GenericFutureListener
connectedListener = (ChannelFuture f) -> { - final EventLoop eventLoop = f.channel().eventLoop();
- if (!f.isSuccess()) {
- System.out.println("连接失败");
- } else {
- channel = (RxtxChannel) f.channel();
- System.out.println("连接成功");
- sendData();
- }
- };
-
- /**
- * 发送数据
- */
- public void sendData() {
- // 十六机制形式发送
- ByteBuf buf = Unpooled.buffer(2);
- buf.writeByte(3);
- buf.writeByte(2);
- channel.writeAndFlush(buf.array());
-
- // 文本形式发送
- //channel.writeAndFlush("2");
- }
-
- public void start() {
- CompletableFuture.runAsync(() -> {
- try {
- // 阻塞的函数
- createRxtx();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }, Executors.newSingleThreadExecutor());//不传默认使用ForkJoinPool,都是守护线程
- }
-
- public static void main(String[] args) {
- // 串口连接服务类
- ComConfig comConfig = new ComConfig();
- comConfig.setSerialPortName("COM1");
- comConfig.setBaudRate(9600);
- RxtxServer rxtxServer = new RxtxServer(comConfig);
- rxtxServer.start();
- try {
- // 连接串口需要一点时间,这里稍微等待一下
- Thread.sleep(5000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- // 发送数据
- rxtxServer.sendData();
- }
- }

这里注意,因为解码是按照十六进制解码,所以需要以“十六进制发送”,“十六进制显示”。