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

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

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

在pom.xml文件中引入netty包

        <!--netty--><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.53.Final</version></dependency>

2、编写NettyServer类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.stereotype.Component;/*** @Author DCXPC* @Description //TODO 采用netty 监听服务器端口,并处理后面逻辑* @Date 2023/9/15 9:57**/
@Component
public class NettyServer {private final int port = 9007;public void start() throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workerGroup)// 指定Channel.channel(NioServerSocketChannel.class)//使用自定义处理类.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();// 添加自定义的ChannelHandlerpipeline.addLast(new MyChannelHandler());}})//服务端可连接队列数,对应TCP/IP协议listen函数中backlog参数.option(ChannelOption.SO_BACKLOG, 128)//保持长连接,2小时无数据激活心跳机制.childOption(ChannelOption.SO_KEEPALIVE, true);// 绑定端口,开始接收进来的连接ChannelFuture channelFuture = serverBootstrap.bind(port).sync();channelFuture.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}

3、编写自定义处理类MyChannelHandler

package com.ruoyi.common.netty;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;import java.text.SimpleDateFormat;
import java.util.Date;/*** @author DCXPC* @ClassName MyChannelHandler* @description: TODO 自定义的数据处理方法,用于处理收到的数据* @date 2023年09月14日*/
public class MyChannelHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 处理接收到的数据ByteBuf byteBuf = (ByteBuf) msg;System.out.println("----------------------------------------------------------------------------------------------------");System.out.println("Received time: " +sdf.format(new Date()));/**数据转换**/// 获取字节数组byte[] bytes = new byte[byteBuf.readableBytes()];byteBuf.getBytes(byteBuf.readerIndex(), bytes);// 将字节数组转换为十六进制字符串StringBuilder hexString = new StringBuilder();for (byte b : bytes) {String hex = Integer.toHexString(b & 0xFF);if (hex.length() == 1) {hexString.append('0'); // 如果得到的十六进制只有一位,则在前面补零}hexString.append(hex);}String hexStringResult = hexString.toString(); // 转换后的十六进制字符串System.out.println("Received data:"+hexStringResult);dealData(hexStringResult);/**接收到的数据是水文规约,需要翻译成有用的数据*/
//        dealData(
//                "7e7e" +//4
//                "01" +//6
//                "0034120201" +//16
//                "1234" +//20
//                "32" +//22
//                "003b" +//26
//                "02" +//28
//                "0102" +//32
//                "230914203800" +//44
//                "f1f1" +//48
//                "0034120201" +//58
//                "49" +//60
//                "f0f0" +//64
//                "2309142038" +//74
//                "3c23" +//水位引导    78
//                "00002321" +//水位2.321    86
//                "682a" +//表1瞬时流量引导     90
//                "0000004644" +//表1瞬时流量46.44    100
//                "6033" +//表1累积流量引导      104
//                "000012369332" +//表1累积流量12369.332     116
//                "692a" +//表2瞬时流量引导  120
//                "0000008723" +//表2瞬时流量87.23     130
//                "6133" +//表2累积流量引导        134
//                "000023223654" +//表2累积流量23223.654     146
//                "03ecaf");byteBuf.release();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {// 处理异常cause.printStackTrace();ctx.close();}//处理数据public void dealData(String hexMsg){String date = hexMsg.substring(32,44);System.out.println("发报时间:"+date);String waterleve = hexMsg.substring(78,86);System.out.println("水位高度:"+addpoint(waterleve,hexMsg.substring(77,78)));;String ssll1 = hexMsg.substring(90,100);System.out.println("表1瞬时流量:"+addpoint(ssll1,"2"));;String ljll1 = hexMsg.substring(104,116);System.out.println("表1累积流量:"+addpoint(ljll1,"3"));;String ssll2 = hexMsg.substring(120,130);System.out.println("表2瞬时流量:"+addpoint(ssll2,"2"));;String ljll2 = hexMsg.substring(134,146);System.out.println("表2累积流量:"+addpoint(ljll2,"3"));;}//小数点添加public float addpoint(String numStr,String locationStr){int locationNum = Integer.valueOf(locationStr);StringBuilder sb = new StringBuilder(numStr);sb.insert(numStr.length()-locationNum,".");float num = Float.valueOf(sb.toString());return num;}}

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

import com.ruoyi.common.netty.NettyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;/*** 启动程序** @author ruoyi*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class RuoYiApplication implements CommandLineRunner {@Autowiredprivate NettyServer nettyServer;private static final Logger log = LoggerFactory.getLogger(RuoYiApplication.class);public static void main(String[] args) {SpringApplication.run(RuoYiApplication.class, args);System.out.println("---项目启动成功---");}@Overridepublic void run(String... args) throws Exception {nettyServer.start();}
}

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringSecurity学习

1.认证 密码校验用户 密码加密存储 Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}} 我们没有以上代码配置&#xff0c;默认明文存储, {id}password…

selenium自动化chrome

from selenium import webdriver from selenium.common.exceptions import NoSuchElementException from selenium.webdriver.common.by import By from selenium.webdriver.chrome.options import Options from fake_useragent import UserAgent# 启动 Chrome 浏览器 chrome_o…

数据清洗:数据挖掘的前期准备工作

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

Nacos、ZooKeeper和Dubbo的区别

Nacos、ZooKeeper和Dubbo是三个不同的分布式系统组件&#xff0c;它们之间有以下几点区别&#xff1a; 功能定位&#xff1a;Nacos主要提供服务发现、配置管理和服务治理等功能&#xff0c;而ZooKeeper主要是分布式协调服务&#xff0c;提供了分布式锁、分布式队列等原语&#…

SpringMvc根据返回值类型不同处理响应

目录 一、介绍 二、返回值为void &#xff08;1&#xff09;控制层方法 三、返回值为String &#xff08;1&#xff09;控制层 四、返回值为ModelAndView &#xff08;1&#xff09;控制层方法 &#xff08;2&#xff09;jsp页面 一、介绍 我们可以通过控制器方法的返回…

sql存储引擎

-- 查询建表语句 --可以查看引擎 show create table account; -- 可以看到默认引擎 InnoDB ENGINEInnoDB -- 查看当前数据库支持得存储引擎 show engines ; # InnoDB 默认 存储引擎 # MyISAM sql早期默认 存储引擎 # MEMORY 存储在内存中 用来做临时表和缓存 存储引擎 …

怎样吃透一个java项目?

前言 对于刚开始看视频敲代码&#xff0c;最忌讳的便是一上来就完全照着视频做&#xff0c;这么做就算完完全全的跟着视频做出来一个项目&#xff0c;始终都无法将里面具体的知识化为己有&#xff0c;单纯来说只是简单的复刻&#xff0c;视频的作者本身是不会对他在做该项目过…

设备树的理解与运用

设备树&#xff1a; 本质是一个文件&#xff0c;包含很多节点&#xff0c;每个节点里边是对设备属性的描述&#xff08;包括GPIO&#xff0c;时钟&#xff0c;中断等等&#xff09;,其中节点&#xff08;node&#xff09;和属性&#xff08;property&#xff09;就是设备树最重…

Python实操如何去除EXCEL表格中的公式并保留原有的数值

import xlwings as xw app xw.App(visibleTrue, add_bookFalse) # 创建一个不可见的Excel应用程序实例 wb app.books.open(rE:\公式.xlsx) # 打开Excel文件 sheet wb.sheets[DC] # 修改为你的工作表名称 # 假设需要清除公式的范围是A1到B10range_to_clear sheet.range(A…

kubernetes集群yaml文件与kubectl工具

k8s集群中对资源管理和资源对象编排部署都可以通过声明样式(yaml)文件来解决&#xff0c;也就是可以把需要对资源对象操作编辑到yaml格式文件中&#xff0c;我们把文件叫做资源清单文件&#xff0c;通过kubectl命令直接使用资源清单文件就可以实现对大量的资源对象进行编排部署…

Linux中使用Docker安装ElasticSearch7.10.x集群

使用Docker安装ElasticSearch7.10.x单节点请访问这里 一、集群环境说明 服务器IP地址192.168.137.1&#xff0c;192.168.137.2&#xff0c;192.168.137.3 二、前期准备 1. 拉取镜像 docker pull elasticsearch:7.10.12. 首先需要创建一个用于生成秘钥的初始容器&#xff0…

【SpringMVC】自定义注解与AOP结合使用

目录 一、SpringMVC之自定义注解 1.1 Java注解简介 1.2 为什么要用注解 1.3 注解的分类 ⭐ 1.3.1 JDK基本注解 1.3.2 JDK元注解 1.3.3 自定义注解 1.4 自定义注解三种使用案例 1.4.1 案例一&#xff08;获取类与方法上的注解值&#xff09; 1.4.2 案例二&#xff0…

SPPNet:金字塔网络

文章目录 SPPNet解决的问题SPPNet结构Bag-of-WordsSPP的结构与插入的位置目标检测任务SPPNet的训练方法Single-size trainingMulti-size training对比实验分类任务 ImageNet 2012数据集目标检测Pascal VOC 2007数据集SPP结构是由提出ResNet的何大神在论文《Spatial Pyramid Poo…

【STL容器】vector

文章目录 前言vector1.1 vector的定义1.2 vector的迭代器1.3 vector的元素操作1.3.1 Member function1.3.2 capacity1.3.3 modify 1.4 vector的优缺点 前言 vector是STL的容器&#xff0c;它提供了动态数组的功能。 注&#xff1a;文章出现的代码并非STL库里的源码&#xff0c…

包管理工具--》发布一个自己的npm包

包管理工具系列文章目录 一、包管理工具--》npm的配置及使用&#xff08;一&#xff09; 二、包管理工具--》npm的配置及使用&#xff08;二&#xff09; 三、包管理工具--》发布一个自己的npm包 四、包管理工具--》yarn的配置及使用 五、包管理工具--》其他包管理器之cnpm…

花见Live Wallpaper Themes 4K Pro for mac(4k视频壁纸)

如果你希望让自己的Mac桌面焕发活力&#xff0c;那么Live Wallpaper & Themes 4K Pro正是一款值得尝试的软件。它提供了丰富的超高清4K动态壁纸和主题&#xff0c;可以让你轻松打造出个性化的桌面环境。 这款软件拥有众多令人惊叹的功能。其中最值得一提的是&#xff0c;它…

视频监控/安防监控/AI视频分析/边缘计算EasyCVR平台如何调取登录接口获取token?

安防视频监控管理平台/视频汇聚/视频云存储平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、云存储、AI智能分析等&#xff0c;视频监控智能分析平台EasyCVR融合性强、…

Vue3修改数组问题

Vue3修改数组问题 1. reactive2. ref总结 vue3中使用组合式式API时定义响应式数据需要使用reactive或者ref,两者使用时有些许不同,下面通过重新赋值数组来说明两者的不同 1. reactive 主要用来定义复杂一些的响应式数据 先清空再赋值 const datas reactive([{id:1,name: 孙…

DataGrip 2023 年下载、安装教程、亲测可用

文章目录 前言1. 下载2. 安装3、DataGrip 常用操作4 推荐阅读 前言 DataGrip 是 JetBrains 发布的多引擎数据库环境&#xff0c;支持 MySQL 和 PostgreSQL&#xff0c;Microsoft SQL Server 和 Oracle&#xff0c;Sybase&#xff0c;DB2&#xff0c;SQLite&#xff0c;还有 Hy…

使用dockerfile文件部署Python+PyWebIO项目

1、安装docker 教程详见之前的内容。https://blog.csdn.net/weixin_44691253/category_12101661.html 2、打包好Python项目 之前的文章中有提到我编写测试工具使用的框架&#xff1a;PythonRequestsPyWebIO框架详解&#xff0c;编写测试工具提高团队测试效率 打包项目时&am…