【JT/T 808协议】808 协议开发笔记 ② ( 终端注册 | 终端注册应答 | 字符编码转换网站 )

文章目录

  • 一、消息头 数据
    • 1、消息头拼接
    • 2、消息 ID 字段
    • 3、消息体属性 字段
    • 4、终端手机号 字段
    • 5、终端流水号 字段
  • 二、消息体 数据
  • 三、校验码计算
  • 四、最终计算结果
  • 五、终端注册应答
    • 1、分解终端应答数据
    • 2、终端应答 消息体 数据
  • 六、字符编码转换网站





一、消息头 数据




1、消息头拼接


808 协议的消息头结构如下 :

+----------+-------------+----------------+--------+------------+----------------+
| 消息ID   | 消息体属性   | 终端手机号      | 流水号 | 总包数     | 包序号         |
| 2字节    | 2字节       | 6字节(BCD)     | 2字节  | 2字节(可选)| 2字节(可选)    |
+----------+-------------+----------------+--------+------------+----------------+

这是生成的 终端注册 消息头数据 :

消息头数据 :

01 00 00 36 01 85 11 88 88 88 00 01

参考 下图进行解析 :

在这里插入图片描述


2、消息 ID 字段


0 ~ 1 字节 是消息 ID , " 01 00 00 36 01 85 11 88 88 88 00 01 "

0x0100 是 终端注册的 消息 ID ;

在这里插入图片描述


3、消息体属性 字段


2 ~ 3 字节 是消息体属性 , " 01 00 00 36 01 85 11 88 88 88 00 01 " , 也就是 00 36 ,

将其拆解成二进制形式 为

0000 0000 0011 0110

参考下面的 位数 进行对应 ,

保留位 是 00 , 分包位 是 0 , 数据加密方式是 000 ,

消息体长度是 00 0011 0110 , 对应的十六进制为 0x36 , 十进制为 54 , 消息体长度 54 字节 ;

在这里插入图片描述


4、终端手机号 字段


4 ~ 9 字节 是 终端手机号 , " 01 00 00 36 01 85 11 88 88 88 00 01 " , 也就是 18511888888 十一位手机号 , 前面加上一个 0 ;

这是 BCD 编码 , 每个字节 高四位 表示一个数字 , 第四位表示一个数字 ;

使用 如下代码 , 可以实现 BCD 编码 到 数字字符串 之间的转换 ;

    /*** 读入数据时通过按位与操作将bcd编码转换成设备编号devId** @param bcd* @return*/public static String bcdToString(byte[] bcd) {// 存储转码后的字符串StringBuilder sb = new StringBuilder();// 循环数组解码 先将每个位上的for (int i = 0; i < bcd.length; i++) {// 转换低字节 十六进制的  0x0f 等于十进制的 15,二进制表示为00001111,直接取到低4位int low = (bcd[i] & 0x0f);// 转换高字节 十六进制的  0xf0 等于十进制的 240,二进制表示为11110000,右移4位的意思是取高4位int high = ((bcd[i] & 0xf0) >> 4);// 如果高字节等于0xf(二进制1111)说明是补的字节,直接抛掉if (high != 0xf) {sb.append(high);}sb.append(low);}// 返回解码字符串return sb.toString();}/*** 写出数据时将我们业务中的devId转换成bcd编码** @param bcd* @return*/public static byte[] strToBcd(String bcd) {// 获取字节数组长度int size = bcd.length() / 2;int remainder = bcd.length() % 2;// 存储BCD码字节byte[] bcdByte = new byte[size + remainder];// 转BCD码for (int i = 0; i < size; i++) {int high = Integer.parseInt(bcd.substring(2 * i, 2 * i + 1));int low = Integer.parseInt(bcd.substring(2 * i + 1, 2 * i + 2));bcdByte[i] = (byte) ((high << 4) | low);}// 如果存在余数,需要填Fif (remainder > 0) {int low = Integer.parseInt(bcd.substring(bcd.length() - 1));bcdByte[bcdByte.length - 1] = (byte) ((0xf << 4) | low);}// 返回BCD码字节数组return bcdByte;}

5、终端流水号 字段


10 ~ 11 字节 是 终端流水号 , " 00 00 00 36 01 85 11 88 88 88 00 01 " ,

终端流水号 , 每次发送数据后 , 自增 1 ;





二、消息体 数据



终端注册 消息体 数据如下 :

0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00    ....BYD..2......
0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
0048 - 0063: 00 00 00 00 00 00                                  ......

参考下图进行解析 :

在这里插入图片描述

  • 0 ~ 1 字节 : 是 省域 ID , short 双字节整型 , 下面 蓝色部分是 省域 ID 数据 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00 …

  • 2 ~ 3 字节 : 市县域 ID , short 整型 , 下面蓝色部分对应数据 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00

  • 4 ~ 8 字节 : 5 字节数据 , 制造商编码 , 下面蓝色部分是 " BYD " 字符串对应的 ASCII 码 , 后面是 两个 0 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00

  • 9 ~ 28 字节 : 20 字节的数据 , 终端型号 , 字符 2 对应的 ASCII 码 ; 下面蓝色字体部分 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00

  • 29 ~ 35 字节 : 7 字节的 二进制数据 , 这里设置的是 0 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00

  • 36 ~ 36 字节 : 1 字节的 二进制数据 , 颜色代码 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0048 - 0063: 00 00 00 00 00 00

  • 37 ~ 53 字节 : 17 字节的 二进制数据 , VIN 码 , 车架号 , 这里设置默认 0 ;

    0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00 …BYD…2…
    0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 …
    0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0048 - 0063: 00 00 00 00 00 00





三、校验码计算



终端注册

  • 消息头 :
	0000 - 0015: 01 00 00 36 01 85 11 88 88 88 00 01
  • 消息体 :
	0000 - 0015: 00 00 00 00 42 59 44 00 00 32 00 00 00 00 00 00    ....BYD..2......0016 - 0031: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................0048 - 0063: 00 00 00 00 00 00                                  ......                                  ....~
  • 校验位 :
	0000 - 0015: E4

将 消息头 + 消息体 两个字节数组 合并后 进行校验 , 使用如下函数 从第一字节开始 进行校验 直到最后一位 ,

    /*** 校验位 校验码指从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。** @return*/public static byte crc(ByteBuf byteBuf) {ByteBuf buf = byteBuf.copy();byte checksum = 0;while (buf.readableBytes() > 0) {checksum ^= buf.readUnsignedByte();}return checksum;}




四、最终计算结果



将上述 消息头 + 消息体 + 校验位 拼装起来 ,

查看 数据中是否有 0x7e 和 0x7d , 进行转义替换 ;

出现 0x7e 的转义处理 : 0x7e <————> 0x7d 后紧跟一个 0x02;
出现 0x7d 的转义处理 : 0x7d <————> 0x7d 后紧跟一个 0x01。


最终的 终端注册数据包为 :

	0000 - 0015: 01 00 00 36 01 85 11 88 88 88 00 01 00 00 00 00    ~...6.6.........0016 - 0031: 00 42 59 44 00 00 32 00 00 00 00 00 00 00 00 00    .BYD..2.........0032 - 0047: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................0048 - 0063: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................0064 - 0079: 00 00 00 E4 7E                                     ....~




五、终端注册应答



返回 终端注册应答 数据 :

	0000 - 0015: 7E 81 00 00 10 01 36 00 10 10 89 00 02 00 01 00    ~.....6.........0016 - 0031: BB CE CE D6 88 E2 47 AC BB 21 30 CE 39 48 7E       ..........089H~

1、分解终端应答数据


前后的 0x7E 是 标识位 ;

倒数第二位 0x48 是 校验位 ;

消息头的结构 :

+----------+-------------+----------------+--------+------------+----------------+
| 消息ID   | 消息体属性   | 终端手机号      | 流水号 | 总包数     | 包序号         |
| 2字节    | 2字节       | 6字节(BCD)     | 2字节  | 2字节(可选)| 2字节(可选)    |
+----------+-------------+----------------+--------+------------+----------------+

消息头提取出来 :

81 00 00 10 01 36 00 10 10 89 00 02

消息体数据提取出来 :

00 01 00 BB CE CE D6 88 E2 47 AC BB 21 30 CE 39 48 7E

参考下图进行解析 ;

在这里插入图片描述


2、终端应答 消息体 数据


消息体数据 :

00 01 00 BB CE CE D6 88 E2 47 AC BB 21 30 CE 39 48 7E

在这里插入图片描述

  • 00 01 是 应答 流水号 ;
  • 00 表示 终端注册 成功 ;
  • BB CE CE D6 88 E2 47 AC BB 21 30 CE 39 是 鉴权码 字符串对应的 二进制数据 ;




六、字符编码转换网站



字符编码转换网站 :

  • GBK 编码转换
  • UTF-8 编码转换
  • URL 编码转换

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

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

相关文章

使用ezuikit-js封装一个对接摄像头的组件

ezuikit-js 是一个基于 JavaScript 的视频播放库&#xff0c;主要用于在网页中嵌入实时视频流播放功能。它通常用于与支持 RTSP、RTMP、HLS 等协议的摄像头或视频流服务器进行交互&#xff0c;提供流畅的视频播放体验。 主要功能 多协议支持&#xff1a;支持 RTSP、RTMP、HLS …

一周学会Flask3 Python Web开发-flask3模块化blueprint配置

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 我们在项目开发的时候&#xff0c;多多少少会划分几个或者几十个业务模块&#xff0c;如果把这些模块的视图方法都写在app.py…

DSC数字选择性呼叫

GMDSS Digital Selective Calling WAVECOM Decoder Online Help 12.0.0 VHF Marine GMDSS/DSC Decode & Scicos Simulation Black Cat Systems &#xff08;一&#xff09;DSC调制方式 DSC&#xff08;Digital Selective Calling&#xff0c;数字选择性呼叫&#xff0…

科普:你的笔记本电脑中有三个IP:127.0.0.1、无线网 IP 和局域网 IP;两个域名:localhost和host.docker.internal

三个IP 你的笔记本电脑中有三个IP&#xff1a;127.0.0.1、无线网 IP 和局域网 IP。 在不同的场景下&#xff0c;需要选用不同的 IP 地址&#xff0c;如下为各自的特点及适用场景&#xff1a; 127.0.0.1&#xff08;回环地址&#xff09; 特点 127.0.0.1 是一个特殊的 IP 地…

《AI与NLP:开启元宇宙社交互动新纪元》

在科技飞速发展的当下&#xff0c;元宇宙正从概念逐步走向现实&#xff0c;成为人们关注的焦点。而在元宇宙诸多令人瞩目的特性中&#xff0c;社交互动体验是其核心魅力之一。人工智能&#xff08;AI&#xff09;与自然语言处理&#xff08;NLP&#xff09;技术的迅猛发展&…

量化方法bitsandbytes hqq eetq区别

量化方法bitsandbytes、HQQ&#xff08;Half-Quadratic Quantization&#xff09;和EETQ&#xff08;Efficient and Effective Ternary Quantization&#xff09;在深度学习模型压缩和加速中各有特点&#xff0c;以下是它们的区别&#xff1a; 1. bitsandbytes 概述: bitsand…

Hutool - Log:自动识别日志实现的日志门面

一、简介 在 Java 开发中&#xff0c;日志记录是一项非常重要的功能&#xff0c;它可以帮助开发者在开发和生产环境中监控程序的运行状态、排查问题。然而&#xff0c;Java 生态系统中有多种日志实现框架&#xff0c;如 Log4j、Logback、JDK 自带的日志框架等。为了在不同的项…

伪404兼容huawei生效显示404

根据上述思考&#xff0c;以下是详细的中文分步说明&#xff1a; --- **步骤 1&#xff1a;获取目标设备的User-Agent信息** 首先&#xff0c;我们需要收集目标设备的User-Agent字符串&#xff0c;包括&#xff1a; 1. **iPhone设备的User-Agent**&#xff1a; Mozi…

github配置sshkey

使用命令生成sshkey ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 依此会要求输入以下信息&#xff0c;可以使用默认值 设置保存密钥的路径 设置SSH密钥密码&#xff08;备注&#xff1a;空内容表示不设置SSH密钥密码&#xff09; 再次确认SSH密钥密…

深入理解WebSocket接口:如何使用C++实现行情接口

在现代网络应用中&#xff0c;实时数据传输变得越来越重要。通过WebSocket&#xff0c;我们可以建立一个持久连接&#xff0c;让服务器和客户端之间进行双向通信。这种技术不仅可以提供更快的响应速度&#xff0c;还可以减少不必要的网络流量。本文将详细介绍如何使用C来实现We…

FFMPEG编码容错处理解决办法之途径----升级库文件

在qt开发环境下接收网络数据&#xff0c;调用ffmpeg解码播放视频&#xff0c;出现闪屏现象&#xff0c;具体现象可以使用操作系统自带的ffplay播放器播放原始视频流可复现&#xff1b;而使用操作系统自带的mpv播放器播放视频则不会出现闪屏&#xff1b;闪屏时会报Could not fin…

什么是超越编程(逾编程)(元编程?)

超越编程(逾编程)(元编程&#xff1f;)(meta-programming) 目录 1. meta- 的词源 2. 逾编程(meta-programming) 的直实含义 2.1 定义 2.2 说明 3. 翻译成“元编程”应该是一种错误 1. meta- 的词源 这是一个源自希腊语的构词元素&#xff0c;其有三种含义&#xff…

基于Martin的全国基础底图实现

概述 前面有文章基于Martin实现MapboxGL自定义底图分享了Martin的使用&#xff0c;本文使用网络收集的数据实现了全国基础数据的收集和基础底图。 实现后效果 实现 1. 数据准备 实例中包含如下数据&#xff1a; 边界线和九段线数据省边界面数据省会城市点数据市边界面数据…

新版Tomcat MySQL IDEA 安装配置过程遇到的问题

一、IDEA闪退 打不开了 IDEA环境变量路径不对 二、Tomcat 一闪而过 主要是JDK环境变量不对 三、MySQL 重新安装、是否备份以及默认盘问题 看清楚教程基本没问题&#xff1a;Windows 安装配置及卸载MySQL8超详细保姆级教程_mysql8卸载-CSDN博客

链表_两两交换链表中的节点

链表_两两交换链表中的节点 一、leetcode-24二、题解1.引库2.代码 一、leetcode-24 两两交换链表中的节点 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能…

DAY08 List接口、Collections接口、Set接口

学习目标 能够说出List集合特点1.有序2.允许存储重复的元素3.有带索引的方法(练习 add,remove,set,get) 能够使用集合工具类Collections类:static void sort(List<T> list) 根据元素的自然顺序 对指定列表按升序进行排序。static <T> void sort(List<T> lis…

Zookeeper(58)如何在Zookeeper中实现分布式锁?

在 Zookeeper 中实现分布式锁是一种常见的用例。Zookeeper 提供了强一致性、高可用性的分布式协调服务&#xff0c;使得它非常适合用来实现分布式锁。以下是详细的步骤和代码示例&#xff0c;展示如何在 Zookeeper 中实现分布式锁。 1. Zookeeper 分布式锁的基本原理 Zookeep…

帆软报表FineReport入门:简单报表制作[扩展|左父格|上父格]

FineReport帮助文档 - 全面的报表使用教程和学习资料 数据库连接 点击号>>JDBC 选择要连接的数据库>>填写信息>>点击测试连接 数据库SQLite是帆软的内置数据库, 里面有练习数据 选择此数据库后,点击测试连接即可 数据库查询 方法一: 在左下角的模板数据集…

后台管理系统-项目初始化

认识vue-admin **核心交付:** 为什么要基于现成架子二次开发 什么是二次开发:基于已有的代码(项目工程,脚手架)开进行新功能的开发 所以看懂已有的框架中的既有代码,变得很重要了 1. 背景知识 后台管理系统是一种最常见的应用模式,不同的管理系统之间有很多相似的地方…

DAY07 Collection、Iterator、泛型、数据结构

学习目标 能够说出集合与数组的区别数组:1.是引用数据类型的一种2.可以存储多个元素3.数组的长度是固定的 int[] arr1 new int[10]; int[] arr2 {1,2,3};4.数组即可以存储基本类型的数据,又可以存储引用数据类型的数据int[],double[],String[],Student[]集合:1.是引用数据类…