Skip to content

ironmp/JT809

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

80 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

JT809协议

MIT Licence

前提条件

  1. 掌握进制转换:二进制转十六进制;
  2. 掌握BCD编码、Hex编码;
  3. 掌握各种位移、异或;
  4. 掌握常用反射;
  5. 掌握快速ctrl+c、ctrl+v;
  6. 掌握以上装逼技能,就可以开始搬砖了。

JT809数据结构解析

数据包[JT809Package]

头标识 数据头 数据体 CRC校验码 尾标识
BeginFlag JT809Header JT809Bodies CRCCode EndFlag
5B - - - 5D

数据头[JT809Header]

数据长度 报文序列号 业务数据类型 下级平台接入码 协议版本号标识 报文加密标识位 数据加密的密匙
MsgLength MsgSN BusinessType MsgGNSSCENTERID Version EncryptFlag EncryptKey

数据体[JT809Bodies]

根据对应业务数据类型:BusinessType

车牌号 车辆颜色 子业务类型标识 后续数据长度 子业务数据体
VehicleNo VehicleColor SubBusinessType DataLength JT809SubBodies

子数据体[JT809SubBodies]

根据对应子业务数据类型 SubBusinessType 处理子业务数据体(JT809SubBodies)。

注意:数据内容(除去头和尾标识)进行转义判断

转义规则如下:

  1. 若数据内容中有出现字符 0x5b 的,需替换为字符 0x5a 紧跟字符 0x01;
  2. 若数据内容中有出现字符 0x5a 的,需替换为字符 0x5a 紧跟字符 0x02;
  3. 若数据内容中有出现字符 0x5d 的,需替换为字符 0x5e 紧跟字符 0x01;
  4. 若数据内容中有出现字符 0x5e 的,需替换为字符 0x5e 紧跟字符 0x02.

反转义的原因:确认JT809协议的TCP消息边界。

举个栗子1

1.组包:

业务数据类型 BusinessType:从链路报警信息交互消息

子业务类型标识 SubBusinessType:报警督办请求消息

JT809Package jT809Package = new JT809Package();

jT809Package.Header = new JT809Header
{
    MsgSN = 1666,
    EncryptKey = 9999,
    EncryptFlag= JT809Header_Encrypt.None,
    Version = new JT809Header_Version(1, 0, 0),
    BusinessType = JT809Enums.JT809BusinessType.从链路报警信息交互消息,
    MsgGNSSCENTERID = 20180920,
};

JT809_0x9400 bodies = new JT809_0x9400
{
    VehicleNo="粤A12345",
    VehicleColor= JT809Enums.JT809VehicleColorType.黄色,
    SubBusinessType= JT809Enums.JT809SubBusinessType.报警督办请求消息,
};

JT809_0x9400_0x9401 jT809_0x9400_0x9401 = new JT809_0x9400_0x9401
{
    WarnSrc = JT809WarnSrc.车载终端,
    WarnType = JT809WarnType.疲劳驾驶报警,
    WarnTime = DateTime.Parse("2018-09-27 10:24:00"),
    SupervisionID = "123FFAA1",
    SupervisionEndTime = DateTime.Parse("2018-09-27 11:24:00"),
    SupervisionLevel = 3,
    Supervisor = "smallchi",
    SupervisorTel = "12345678901",
    SupervisorEmail = "123456@qq.com"
};

bodies.SubBodies = jT809_0x9400_0x9401;

jT809Package.Bodies = bodies;

byte[] data = JT809Serializer.Serialize(jT809Package);

string hex = data.ToHexString();

// 输出结果Hex:
// 5B 00 00 00 92 00 00 06 82 94 00 01 33 EF B8 01 00 00 00 00 00 27 0F D4 C1 41 31 32 33 34 35 00 00 00 00 00 00 00 00 00 00 00 00 00 02 94 01 00 00 00 5C 01 00 02 00 00 00 00 5A 01 AC 3F 40 12 3F FA A1 00 00 00 00 5A 01 AC 4D 50 03 73 6D 61 6C 6C 63 68 69 00 00 00 00 00 00 00 00 31 32 33 34 35 36 37 38 39 30 31 00 00 00 00 00 00 00 00 00 31 32 33 34 35 36 40 71 71 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BA D8 5D

2.手动解包:

1.原包:
5B 00 00 00 92 00 00 06 82 94 00 01 33 EF B8 01 00 00 00 00 00 27 0F D4 C1 41 31 32 33 34 35 00 00 00 00 00 00 00 00 00 00 00 00 00 02 94 01 00 00 00 5C 01 00 02 00 00 00 00 (5A 01) AC 3F 40 12 3F FA A1 00 00 00 00 (5A 01) AC 4D 50 03 73 6D 61 6C 6C 63 68 69 00 00 00 00 00 00 00 00 31 32 33 34 35 36 37 38 39 30 31 00 00 00 00 00 00 00 00 00 31 32 33 34 35 36 40 71 71 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BA D8 5D

2.进行反转义
5A 01 ->5B
5A 02 ->5A
5E 01 ->5D
5E 02 ->5E
反转义后
5B 00 00 00 92 00 00 06 82 94 00 01 33 EF B8 01 00 00 00 00 00 27 0F D4 C1 41 31 32 33 34 35 00 00 00 00 00 00 00 00 00 00 00 00 00 02 94 01 00 00 00 5C 01 00 02 00 00 00 00 5B AC 3F 40 12 3F FA A1 00 00 00 00 5B AC 4D 50 03 73 6D 61 6C 6C 63 68 69 00 00 00 00 00 00 00 00 31 32 33 34 35 36 37 38 39 30 31 00 00 00 00 00 00 00 00 00 31 32 33 34 35 36 40 71 71 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BA D8 5D

3.拆解
5B          --头标识
00 00 00 92 --数据头->数据长度
00 00 06 82 --数据头->报文序列号
94 00       --数据头->业务数据类型
01 33 EF B8 --数据头->下级平台接入码,上级平台给下级平台分配唯一标识码
01 00 00    --数据头->协议版本号标识
00          --数据头->报文加密标识位
00 00 27 0F --数据头->数据加密的密匙
D4 C1 41 31 32 33 34 35 00 00 00 00 00 00 00 00 00 00 00 00 00 --数据体->车牌号
02                                                             --数据体->车辆颜色
94 01                                                          --数据体->子业务类型标识
00 00 00 5C                                                    --数据体->后续数据长度
01                                                                                              --子数据体->报警信息来源
00 02                                                                                           --子数据体->报警类型
00 00 00 00 5B AC 3F 40                                                                         --子数据体->报警时间UTCDateTime
12 3F FA A1                                                                                     --子数据体->报警督办ID
00 00 00 00 5B AC 4D 50                                                                         --子数据体->督办截止时间
03                                                                                              --子数据体->督办级别
73 6D 61 6C 6C 63 68 69 00 00 00 00 00 00 00 00                                                 --子数据体->督办人
31 32 33 34 35 36 37 38 39 30 31 00 00 00 00 00 00 00 00 00                                     --子数据体->督办联系电话
31 32 33 34 35 36 40 71 71 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 --子数据体->督办联系电子邮件
BA D8       --CRC校验码
5D          --尾标识

3.程序解包:

//1.转成byte数组
var bytes = "5B 00 00 00 92 00 00 06 82 94 00 01 33 EF B8 01 00 00 00 00 00 27 0F D4 C1 41 31 32 33 34 35 00 00 00 00 00 00 00 00 00 00 00 00 00 02 94 01 00 00 00 5C 01 00 02 00 00 00 00 5A 01 AC 3F 40 12 3F FA A1 00 00 00 00 5A 01 AC 4D 50 03 73 6D 61 6C 6C 63 68 69 00 00 00 00 00 00 00 00 31 32 33 34 35 36 37 38 39 30 31 00 00 00 00 00 00 00 00 00 31 32 33 34 35 36 40 71 71 2E 63 6F 6D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BA D8 5D".ToHexBytes();

//2.将数组反序列化
JT809Package jT809Package = JT809Serializer.Deserialize(bytes);

//3.数据包头
Assert.Equal((uint)146, jT809Package.Header.MsgLength);
Assert.Equal((uint)1666, jT809Package.Header.MsgSN);
Assert.Equal((uint)9999, jT809Package.Header.EncryptKey);
Assert.Equal(JT809Header_Encrypt.None, jT809Package.Header.EncryptFlag);
Assert.Equal((uint)20180920, jT809Package.Header.MsgGNSSCENTERID);
Assert.Equal(JT809Enums.JT809BusinessType.从链路报警信息交互消息, jT809Package.Header.BusinessType);
Assert.Equal(new JT809Header_Version(1, 0, 0).ToString(), jT809Package.Header.Version.ToString());

//4.数据包体
JT809_0x9400 jT809_0X400 = (JT809_0x9400)jT809Package.Bodies;
Assert.Equal("粤A12345", jT809_0X400.VehicleNo);
Assert.Equal(JT809Enums.JT809VehicleColorType.黄色, jT809_0X400.VehicleColor);
Assert.Equal(JT809Enums.JT809SubBusinessType.报警督办请求消息, jT809_0X400.SubBusinessType);
Assert.Equal((uint)92, jT809_0X400.DataLength);

//5.子数据包体
JT809_0x9400_0x9401 jT809_0x9400_0x9401 = (JT809_0x9400_0x9401)jT809_0X400.JT809SubBodies;
Assert.Equal(JT809WarnSrc.车载终端, jT809_0x9400_0x9401.WarnSrc);
Assert.Equal(JT809WarnType.疲劳驾驶报警, jT809_0x9400_0x9401.WarnType);
Assert.Equal(DateTime.Parse("2018-09-27 10:24:00"), jT809_0x9400_0x9401.WarnTime);
Assert.Equal("123FFAA1", jT809_0x9400_0x9401.SupervisionID);
Assert.Equal(DateTime.Parse("2018-09-27 11:24:00"), jT809_0x9400_0x9401.SupervisionEndTime);
Assert.Equal(3, jT809_0x9400_0x9401.SupervisionLevel);
Assert.Equal("smallchi", jT809_0x9400_0x9401.Supervisor);
Assert.Equal("12345678901", jT809_0x9400_0x9401.SupervisorTel);
Assert.Equal("123456@qq.com", jT809_0x9400_0x9401.SupervisorEmail);

举个栗子2

// 设置全局配置
JT809GlobalConfig.Instance.SetHeaderOptions(new JT809Configs.JT809HeaderOptions
{
    EncryptKey= 9999,
    MsgGNSSCENTERID= 20180920
});

// 根据业务类型创建对应包
JT809Package jT809Package = JT809BusinessType.从链路报警信息交互消息.Create(new JT809_0x9400
{
    VehicleNo = "粤A12345",
    VehicleColor = JT809Enums.JT809VehicleColorType.黄色,
    SubBusinessType = JT809Enums.JT809SubBusinessType.报警督办请求消息,
    JT809SubBodies = new JT809_0x9400_0x9401
    {
        WarnSrc = JT809WarnSrc.车载终端,
        WarnType = JT809WarnType.疲劳驾驶报警,
        WarnTime = DateTime.Parse("2018-09-27 10:24:00"),
        SupervisionID = "123FFAA1",
        SupervisionEndTime = DateTime.Parse("2018-09-27 11:24:00"),
        SupervisionLevel = 3,
        Supervisor = "smallchi",
        SupervisorTel = "12345678901",
        SupervisorEmail = "123456@qq.com"
    }
});
var hex = JT809Serializer.Serialize(jT809Package);

举个栗子3

static void Main(string[] args)
{
    // 设置全局配置
    JT809GlobalConfig.Instance
            // 设置加密算法
            .SetEncrypt(new JT809EncryptImpl(
                new JT809Configs.JT809EncryptOptions()
                {
                    IA1 = 20000000,
                    IC1 = 20000000,
                    M1 = 30000000
                })
            )
            // 设置头部信息
            .SetHeaderOptions(new JT809Configs.JT809HeaderOptions
            {
                EncryptFlag = JT809Header_Encrypt.Common,
                Version = new JT809Header_Version(2, 3, 2),
                EncryptKey = 9999,
                MsgGNSSCENTERID = 20180920
            }
            )
            // 设置是否跳过校验和
            .SetSkipCRCCode(false);
    // todo:
}

举个栗子4

// 使用依赖注入的方式实现配置
// Install-Package JT809.Extensions.DependencyInjection
static async Task  Main(string[] args)
{
    var serverHostBuilder = new HostBuilder()
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.SetBasePath(AppDomain.CurrentDomain.BaseDirectory);
            config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
        })
        .ConfigureServices((hostContext, services) =>
        {
            // 方式1:
            //services.AddJT809Configure(hostContext.Configuration.GetSection("JT809Options"));
            // 方式2:
            services.AddJT809Configure(new JT809Options
            {
                HeaderOptions=new JT809Configs.JT809HeaderOptions {
                    MsgGNSSCENTERID=20181012,
                    EncryptFlag= JT809Header_Encrypt.Common,
                    EncryptKey= 9999,
                    Version = new  JT809Header_Version{
                        Major=2,
                        Minor=1,
                        Build= 2
                    }
                },
                EncryptOptions = new JT809Configs.JT809EncryptOptions {
                    IA1 = 20000000,
                    IC1 = 20000000,
                    M1 = 30000000
                }
            });
        });
    await serverHostBuilder.RunConsoleAsync();
}

NuGet安装

Package Name Version Downloads
Install-Package JT809 JT809 JT809
Install-Package JT809.Extensions.DependencyInjection JT809.Ext JT809.Ext

使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真)

BenchmarkDotNet=v0.11.3, OS=Windows 10.0.17134.471 (1803/April2018Update/Redstone4)
Intel Core i7-8700K CPU 3.70GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
  [Host]     : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3260.0
  Job-FVMQGI : .NET Framework 4.7.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.7.3260.0
  Job-YJYJYV : .NET Core 2.1.6 (CoreCLR 4.6.27019.06, CoreFX 4.6.27019.05), 64bit RyuJIT
  Job-LGLQDK : .NET Core 2.2.0 (CoreCLR 4.6.27110.04, CoreFX 4.6.27110.04), 64bit RyuJIT

Platform=AnyCpu  Runtime=Clr  Server=False  
Method Toolchain N Mean Error StdDev Gen 0/1k Op Gen 1/1k Op Gen 2/1k Op Allocated Memory/Op
JT809_0x9400_0x9401_Package_Deserialize Default 100 3.267 ms 0.0236 ms 0.0221 ms 70.3125 - - 447.72 KB
JT809_0x9400_0x9401_Package_Serialize Default 100 3.778 ms 0.0547 ms 0.0511 ms 74.2188 - - 460.91 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.1 100 2.428 ms 0.0193 ms 0.0171 ms 62.5000 - - 403.5 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.1 100 2.654 ms 0.0328 ms 0.0291 ms 66.4063 - - 408.03 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.2 100 2.466 ms 0.0149 ms 0.0116 ms 62.5000 - - 403.5 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.2 100 2.658 ms 0.0418 ms 0.0371 ms 66.4063 - - 408.03 KB
JT809_0x9400_0x9401_Package_Deserialize Default 10000 328.718 ms 5.0276 ms 4.4569 ms 7000.0000 - - 44784.51 KB
JT809_0x9400_0x9401_Package_Serialize Default 10000 375.466 ms 7.4380 ms 8.5656 ms 7000.0000 - - 46096.55 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.1 10000 242.558 ms 1.8886 ms 1.6742 ms 6333.3333 - - 40344.32 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.1 10000 271.849 ms 5.6158 ms 7.8726 ms 6000.0000 - - 40837.81 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.2 10000 249.261 ms 4.8036 ms 4.4933 ms 6500.0000 - - 40360.23 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.2 10000 274.853 ms 5.2753 ms 5.6445 ms 6000.0000 - - 40837.81 KB
JT809_0x9400_0x9401_Package_Deserialize Default 100000 3,245.827 ms 52.6422 ms 49.2415 ms 72000.0000 - - 447679.84 KB
JT809_0x9400_0x9401_Package_Serialize Default 100000 3,613.713 ms 15.8729 ms 14.0709 ms 75000.0000 - - 460885.07 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.1 100000 2,403.299 ms 3.0808 ms 2.4053 ms 65000.0000 - - 403220.45 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.1 100000 2,683.482 ms 37.0471 ms 34.6539 ms 66000.0000 - - 407869.06 KB
JT809_0x9400_0x9401_Package_Deserialize .NET Core 2.2 100000 2,527.455 ms 4.3616 ms 3.6421 ms 65000.0000 - - 403220.45 KB
JT809_0x9400_0x9401_Package_Serialize .NET Core 2.2 100000 2,734.308 ms 9.2382 ms 8.1894 ms 66000.0000 - - 407869.06 KB

JT809协议消息对照表

链路管理类

主链路

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1001 主链路登录请求消息
2 0x1002 主链路登录应答消息
3 0x1003 主链路注销请求消息
4 0x1004 主链路注销应答消息
5 0x1005 主链路连接保持请求消息
6 0x1006 主链路连接保持应答消息
7 0x1007 主链路断开通知消息
8 0x1008 下级平台主动关闭链路通知消息

从链路

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9001 从链路连接请求消息
2 0x9002 从链路连接应答消息
3 0x9003 从链路注销请求消息
4 0x9004 从链路注销应答消息
5 0x9005 从链路连接保持请求消息
6 0x9006 从链路连接保持应答消息
7 0x9007 从链路断开通知消息
8 0x9008 上级平台主动关闭链路通知消息

信息统计类

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9101 接收定位信息数量通知消息

车辆动态信息交换

主链路动态信息交换消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1200 主链路动态信息交换消息
2 0x1201 上传车辆注册信息(809补充协议文档)
3 0x1202 实时上传车辆定位信息
4 0x1203 车辆定位信息自动补报
5 0x1205 启动车辆定位信息交换应答消息
6 0x1206 结束车辆定位信息交换应答消息
7 0x1207 申请交换指定车辆定位信息请求消息
8 0x1208 取消交换指定车辆定位信息请求
9 0x1209 补发车辆定位信息请求
10 0x120A 上报车辆驾驶员身份识别信息应答
11 0x120B 上报车辆电子运单应答
12 0x120C 主动上报驾驶员身份信息(809补充协议文档)
13 0x120D 主动上报车辆电子运单信息(809补充协议文档)

从链路动态信息交换消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9200 从链路动态信息交换消息
2 0x9202 √(0x1202) 交换车辆定位信息消息(809补充协议文档)
3 0x9203 √(0x1203) 车辆定位信息交换补发消息
4 0x9204 交换车辆静态信息消息
5 0x9205 启动车辆定位信息交换请求消息
6 0x9206 结束车辆定位信息交换请求消息
7 0x9207 申请交换指定车辆定位信息应答消息
8 0x9208 取消申请交换指定车辆定位信息应答消息
9 0x9209 补发车辆定位信息应答消息
10 0x920A 上报驾驶员身份识别信息请求消息
11 0x920B 上报车辆电子运单请求消息

平台间信息交互类

主链路平台间信息交互消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1300 主链路平台间信息交互消息
2 0x1301 平台查岗应答消息(809补充协议文档)
3 0x1302 下发平台间报文应答消息(809补充协议文档)

从链路平台间信息交互消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9300 从链路平台间信息交互消息
2 0x9301 平台查岗请求(809补充协议文档)
3 0x9302 下发平台间报文请求(809补充协议文档)

车辆报警信息交互类

主链路报警信息交互消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1400 主链路平台间信息交互消息
2 0x1401 报警督办应答消息
3 0x1402 上报报警信息消息
4 0x1403 主动上报报警处理结果信息(809补充协议文档)

从链路报警信息交互消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9400 主链路平台间信息交互消息
2 0x9401 报警督办请求
3 0x9402 报警预警
4 0x9403 实时交换报警信息

车辆监管类

主链路车辆监管消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1500 主链路车辆监管消息
2 0x1501 车辆单向监听应答
3 0x1502 车辆拍照应答
4 0x1503 下发车辆报文应答
5 0x1504 上报车辆行驶记录应答(809补充协议文档)
6 0x1505 车辆应急接入监管平台应答消息

从链路车辆监管消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9500 从链路车辆监管消息
2 0x9501 车辆单向监听请求
3 0x9502 车辆拍照请求
4 0x9503 下发车辆报文请求
5 0x9504 上报车辆行驶记录请求(809补充协议文档)
6 0x9505 车辆应急接入监管平台请求消息(809补充协议文档)

车辆静态信息交换类

主链路静态信息交换消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x1600 主链路静态信息交换消息
2 0x1601 补报车辆静态信息应答

从链路静态信息交换消息

序号 消息ID 完成情况 测试情况 消息体名称
1 0x9600 从链路静态信息交换消息
2 0x9601 补报车辆静态信息应答

About

JT809协议、GB809协议、道路运输车辆卫星定位系统-平台数据交换协议

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C# 100.0%