• SpringBoot基于Netty实现对接硬件,接受硬件报文


    主要项目框架采用的事若依的框架,就不做多介绍

    下面主要贴代码和部分注释

    在pom.xml文件中引入netty包

    1. <dependency>
    2. <groupId>io.nettygroupId>
    3. <artifactId>netty-allartifactId>
    4. <version>4.1.53.Finalversion>
    5. dependency>

    2、编写NettyServer类

    1. import io.netty.bootstrap.ServerBootstrap;
    2. import io.netty.channel.*;
    3. import io.netty.channel.nio.NioEventLoopGroup;
    4. import io.netty.channel.socket.SocketChannel;
    5. import io.netty.channel.socket.nio.NioServerSocketChannel;
    6. import org.springframework.stereotype.Component;
    7. /**
    8. * @Author DCXPC
    9. * @Description //TODO 采用netty 监听服务器端口,并处理后面逻辑
    10. * @Date 2023/9/15 9:57
    11. **/
    12. @Component
    13. public class NettyServer {
    14. private final int port = 9007;
    15. public void start() throws InterruptedException {
    16. EventLoopGroup bossGroup = new NioEventLoopGroup();
    17. EventLoopGroup workerGroup = new NioEventLoopGroup();
    18. try {
    19. ServerBootstrap serverBootstrap = new ServerBootstrap();
    20. serverBootstrap.group(bossGroup, workerGroup)
    21. // 指定Channel
    22. .channel(NioServerSocketChannel.class)
    23. //使用自定义处理类
    24. .childHandler(new ChannelInitializer() {
    25. @Override
    26. protected void initChannel(SocketChannel ch) throws Exception {
    27. ChannelPipeline pipeline = ch.pipeline();
    28. // 添加自定义的ChannelHandler
    29. pipeline.addLast(new MyChannelHandler());
    30. }
    31. })
    32. //服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数
    33. .option(ChannelOption.SO_BACKLOG, 128)
    34. //保持长连接,2小时无数据激活心跳机制
    35. .childOption(ChannelOption.SO_KEEPALIVE, true);
    36. // 绑定端口,开始接收进来的连接
    37. ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
    38. channelFuture.channel().closeFuture().sync();
    39. } finally {
    40. workerGroup.shutdownGracefully();
    41. bossGroup.shutdownGracefully();
    42. }
    43. }
    44. }

    3、编写自定义处理类MyChannelHandler

    1. package com.ruoyi.common.netty;
    2. import io.netty.buffer.ByteBuf;
    3. import io.netty.channel.ChannelHandlerContext;
    4. import io.netty.channel.ChannelInboundHandlerAdapter;
    5. import java.text.SimpleDateFormat;
    6. import java.util.Date;
    7. /**
    8. * @author DCXPC
    9. * @ClassName MyChannelHandler
    10. * @description: TODO 自定义的数据处理方法,用于处理收到的数据
    11. * @date 2023年09月14日
    12. */
    13. public class MyChannelHandler extends ChannelInboundHandlerAdapter {
    14. @Override
    15. public void channelRead(ChannelHandlerContext ctx, Object msg) {
    16. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    17. // 处理接收到的数据
    18. ByteBuf byteBuf = (ByteBuf) msg;
    19. System.out.println("----------------------------------------------------------------------------------------------------");
    20. System.out.println("Received time: " +sdf.format(new Date()));
    21. /**数据转换**/
    22. // 获取字节数组
    23. byte[] bytes = new byte[byteBuf.readableBytes()];
    24. byteBuf.getBytes(byteBuf.readerIndex(), bytes);
    25. // 将字节数组转换为十六进制字符串
    26. StringBuilder hexString = new StringBuilder();
    27. for (byte b : bytes) {
    28. String hex = Integer.toHexString(b & 0xFF);
    29. if (hex.length() == 1) {
    30. hexString.append('0'); // 如果得到的十六进制只有一位,则在前面补零
    31. }
    32. hexString.append(hex);
    33. }
    34. String hexStringResult = hexString.toString(); // 转换后的十六进制字符串
    35. System.out.println("Received data:"+hexStringResult);
    36. dealData(hexStringResult);
    37. /**接收到的数据是水文规约,需要翻译成有用的数据*/
    38. // dealData(
    39. // "7e7e" +//4
    40. // "01" +//6
    41. // "0034120201" +//16
    42. // "1234" +//20
    43. // "32" +//22
    44. // "003b" +//26
    45. // "02" +//28
    46. // "0102" +//32
    47. // "230914203800" +//44
    48. // "f1f1" +//48
    49. // "0034120201" +//58
    50. // "49" +//60
    51. // "f0f0" +//64
    52. // "2309142038" +//74
    53. // "3c23" +//水位引导 78
    54. // "00002321" +//水位2.321 86
    55. // "682a" +//表1瞬时流量引导 90
    56. // "0000004644" +//表1瞬时流量46.44 100
    57. // "6033" +//表1累积流量引导 104
    58. // "000012369332" +//表1累积流量12369.332 116
    59. // "692a" +//表2瞬时流量引导 120
    60. // "0000008723" +//表2瞬时流量87.23 130
    61. // "6133" +//表2累积流量引导 134
    62. // "000023223654" +//表2累积流量23223.654 146
    63. // "03ecaf");
    64. byteBuf.release();
    65. }
    66. @Override
    67. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    68. // 处理异常
    69. cause.printStackTrace();
    70. ctx.close();
    71. }
    72. //处理数据
    73. public void dealData(String hexMsg){
    74. String date = hexMsg.substring(32,44);
    75. System.out.println("发报时间:"+date);
    76. String waterleve = hexMsg.substring(78,86);
    77. System.out.println("水位高度:"+addpoint(waterleve,hexMsg.substring(77,78)));;
    78. String ssll1 = hexMsg.substring(90,100);
    79. System.out.println("表1瞬时流量:"+addpoint(ssll1,"2"));;
    80. String ljll1 = hexMsg.substring(104,116);
    81. System.out.println("表1累积流量:"+addpoint(ljll1,"3"));;
    82. String ssll2 = hexMsg.substring(120,130);
    83. System.out.println("表2瞬时流量:"+addpoint(ssll2,"2"));;
    84. String ljll2 = hexMsg.substring(134,146);
    85. System.out.println("表2累积流量:"+addpoint(ljll2,"3"));;
    86. }
    87. //小数点添加
    88. public float addpoint(String numStr,String locationStr){
    89. int locationNum = Integer.valueOf(locationStr);
    90. StringBuilder sb = new StringBuilder(numStr);
    91. sb.insert(numStr.length()-locationNum,".");
    92. float num = Float.valueOf(sb.toString());
    93. return num;
    94. }
    95. }

    4、在启动类上加上该启动配置

    1. import com.ruoyi.common.netty.NettyServer;
    2. import org.slf4j.Logger;
    3. import org.slf4j.LoggerFactory;
    4. import org.springframework.beans.factory.annotation.Autowired;
    5. import org.springframework.boot.CommandLineRunner;
    6. import org.springframework.boot.SpringApplication;
    7. import org.springframework.boot.autoconfigure.SpringBootApplication;
    8. import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
    9. /**
    10. * 启动程序
    11. *
    12. * @author ruoyi
    13. */
    14. @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
    15. public class RuoYiApplication implements CommandLineRunner {
    16. @Autowired
    17. private NettyServer nettyServer;
    18. private static final Logger log = LoggerFactory.getLogger(RuoYiApplication.class);
    19. public static void main(String[] args) {
    20. SpringApplication.run(RuoYiApplication.class, args);
    21. System.out.println("---项目启动成功---");
    22. }
    23. @Override
    24. public void run(String... args) throws Exception {
    25. nettyServer.start();
    26. }
    27. }

    5、后续有增加的功能时候,再进行更新

    文章参考:https://blog.51cto.com/u_16099206/6430191

    Java基础之《netty(12)—netty入门》_java netty tcp_csj50的博客-CSDN博客

  • 相关阅读:
    Spring Boot 配置文件
    VScode在服务器上远程调试python代码的工作目录问题
    【TS】函数重载--可选参数--默认参数
    汇编语言入门学习(有栈协程铺垫,32位寄存器,未完待续06/28)
    深度学习第四阶段:NLP第二章 Transformer学习笔记
    Jenkins 基础配置
    NumPy学习挑战第四关-NumPy数组属性
    Linux 高级IO
    [移动通讯]【Carrier Aggregation in LTE】【 Log analysis-2】
    日志pattern
  • 原文地址:https://blog.csdn.net/qq_34178998/article/details/132896583