SuperAlways/gbt32960-server

Netty的国标GBT32960新能源汽车远程监控协议服务器实现,支持2016和2025版本协议,提供高性能的TCP协议处理和完整的Web API接口

★ 10Forks 2GitHub ↗Compare

README

国标GBT32960协议网关

项目介绍

  • 基于Netty,实现GBT32960-2016,GBT32960-2025消息处理,与编码解码;
  • 无需修改代码,同时支持TCP;
  • 使用Spring WebFlux 提供支持高并发的Web接口服务;
  • 不依赖Spring,可移除Spring独立运行(编码解码可支持Android);
  • 最简洁、清爽、易用的部标开发框架。
  • 参考剑器近大佬的JT808项目进行开发设计,808项目地址:https://gitee.com/yezhihao/jt808-server/tree/master

主要特性

  • 代码足够精简,便于二次开发;
  • 致敬Spring、Hibernate设计理念,熟悉Web开发的同学上手极快;
  • 使用注解描述协议,告别繁琐的封包、解包;
  • 支持异步批量处理,显著提升MySQL入库性能;
  • 提供报文解释器(解析过程分析工具),编码解码不再抓瞎;
  • 全覆盖的测试用例,稳定发版。

协议支持(传输层协议支持TCP)

协议名称 版本 是否支持 备注
GBT 32960 2016 支持
GBT 32960 2025 支持

代码仓库

演示

验证步骤

1.验证消息定义

解码分析工具:org.alwayssuper.Elucidator(报文 <=> 对象)

使用src\test\java\Elucidator 分析报文内每个属性所处的位置以及转换后的值,以便查询报文解析出错的原因

package org.alwayssuper;

public class Elucidator extends JT808Beans {

    public static final GBTMessageAdapter coder = new GBTMessageAdapter("org.alwayssuper.protocol");

    public static void main(String[] args) {
        // 测试2025版本实时上报数据
        String hex = "242401FE4C46504832413142304B3141313233343501009719081F0E1E00000138393836303132333435363738393031323334350202035041434B30303030313233343536373839303132333435365041434B30303030323334353637383930313233343536375041434B30303030333435363738393031323334353637385041434B30303030343536373839303132333435363738395041434B303030303536373839303132333435363738393043";
        GBTMessage msg = H2025(G01_2025());

        msg = decode(hex);
        hex = encode(msg);
    }
}

Elucidator 运行效果如下:

2	[01] [1] 命令标识
3	[fe] [254] 应答标识
4	[4c46504832413142304b31413132333435] [LFPH2A1B0K1A12345] 唯一识别码
21	[01] [1] 数据单元加密方式
22	[0097] [151] 数据单元长度
24	[19081f0e1e00] [2025-08-31T14:30] 数据采集时间(YYMMDDHHMMSS)
30	[0001] [1] 登入流水号:车载终端每登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天
32	[3839383630313233343536373839303132333435] [89860123456789012345] ICCID:SIM卡ICCID号(ICCID应为终端从SIM卡获取的值,不应人为填写或修改)
52	[02] [2] 电池管理系统对应动力蓄电池包个数:电池管理系统对应动力蓄电池包个数m,有效范围:0~50数量
53	[02] [2] 该电池管理系统对应动力蓄电池包个数,有效范围:0~50
54	[03] [3] 该电池管理系统对应动力蓄电池包个数,有效范围:0~50
55	[5041434b3030303031323334353637383930313233343536] [PACK00001234567890123456] 动力蓄电池包编码:24字节编码,按GB/T34014标准
79	[5041434b3030303032333435363738393031323334353637] [PACK00002345678901234567] 动力蓄电池包编码:24字节编码,按GB/T34014标准
103	[5041434b3030303033343536373839303132333435363738] [PACK00003456789012345678] 动力蓄电池包编码:24字节编码,按GB/T34014标准
127	[5041434b3030303034353637383930313233343536373839] [PACK00004567890123456789] 动力蓄电池包编码:24字节编码,按GB/T34014标准
151	[5041434b3030303035363738393031323334353637383930] [PACK00005678901234567890] 动力蓄电池包编码:24字节编码,按GB/T34014标准

242401FE4C46504832413142304B3141313233343501009719081F0E1E00000138393836303132333435363738393031323334350202035041434B30303030313233343536373839303132333435365041434B30303030323334353637383930313233343536375041434B30303030333435363738393031323334353637385041434B30303030343536373839303132333435363738395041434B303030303536373839303132333435363738393043

2.模拟设备请求

运行 \协议文档\发包工具.exe

  1. 协议类型:【TCP Client】
  2. 远程主机地址:127.0.0.1
  3. 远程主机端口:7100
  4. 接收设置:⊙HEX
  5. 发送设置:⊙HEX
  6. 点击按钮【连接】
  7. 将上一个步骤中生成的报文,粘贴到文本框
  8. 点击按钮【发送】

注意:先选择HEX,再粘贴报文

232301FE4C41395A414C343334483043484430303701001E130801071F0C000138393836303631393030303031363134323538340100B6

如下图所示 使用发包工具模拟请求

3.下发命令到终端

已集成OpenAPI文档,启动后可访问如下地址

录入参数,点击发送 Knife4j UI

Console

开发步骤

1.定义消息

package org.alwayssuper.protocol.gbt32960;

@Message(GBTRequestType.车辆登出)
public class G04 extends GBTMessage {
   @Field(length = 6, desc = "登出时间(YYMMDDHHMMSS)")
   private LocalDateTime logoutTime;
   @Field(length = 2, desc = "登出流水号:登出流水号与当次登入流水号一致")
   private int logoutSeqNo;

   @Override
   public int getSerialNo() {
       return logoutSeqNo;
   }
}

2.处理终端上报的消息

package org.alwayssuper.web.endpoint;

@Endpoint
public class GBT32960Endpoint {
    

    @Mapping(types = GBTRequestType.车辆登出, desc = "车辆登出")
    public void G04(G04 message, Session session) {
        // 不在这里立即断开连接,由拦截器在应答发送后延迟断开
        log.info("{}车辆登出消息处理完成,等待应答发送后断开连接", session);
    }
}

3.下发消息到终端(通过Web接口)

package org.alwayssuper.web.controller;

@RestController
@RequestMapping("device")
public class GBT32960Controlle {

    private final MessageManager messageManager;

    @Operation(summary = "0x0B 数据单元加密密钥交换")
    @PostMapping("0x0B")
    public Mono<R<G0B>> G0B(@RequestBody G0B request) {
        return messageManager.requestR(request, G0B.class);
    }
}

注解说明:

  • @Message,消息类型,等价Hibernate的 @Table

  • @Field,消息属性,等价Hibernate的 @Column

  • @Endpoint,消息接入点,等价SpringMVC的 @Controller

  • @Mapping,消息映射到方法,等价SpringMVC中 @RequestMapping

  • @Async,异步消息处理,用于较为耗时的操作(例如文件写入)。

  • @AsyncBatch,消息批量处理,对于高并发的消息(例如:位置信息汇报),合并同类消息,提升入库性能。

目录结构

├── 协议文档
│   ├── GBT32960-2016协议文档
│   ├── GBT32960-2025协议文档
│   └── 发包工具.exe
│
├──commons
│   └── 共享工具类和基础组件
│
├──GBT32960-netmc
│   └── 基于Netty的自定义MVC框架
│       ├── TCP服务器实现
│       └── 会话管理
│
├──GBT32960-protostar
│   └── 注解驱动的序列化框架
│       └── 协议架构管理
│
├──GBT32960-protocol
│   └── GBT32960协议实现
│       ├── 消息定义和编解码器
│       └── 2016/2025版本支持
│
├──GBT32960-server
│   ├──main
│   │   └── web SpringBoot应用
│   │      ├── config GBT服务配置项
│   │      ├── endpoint GBT消息入口
│   │      └── controller REST API控制器
│   └──test
│      ├── Elucidator 报文解析工具
│      └── StressTest 压力测试

欢迎大家的关注和使用,gbt32960-server也将拥抱变化,持续发展。

项目会不定期进行更新,建议star和watch一份,您的支持是我最大的动力。

如有任何疑问或者BUG,请联系我,非常感谢。

项目负责人QQ:[191763414]

技术交流QQ群:[956610535]

Contributors

SuperAlways

Issues