Переглянути джерело

1.调整头部包类型将原先的结构体改为类

2.调整分包格式,数据包中增加分包数据体,以便进行数据合并
3.修改文档内容
tags/v2.3.3
SmallChi(Koike) 4 роки тому
джерело
коміт
ef625b2025
9 змінених файлів з 140 додано та 160 видалено
  1. +5
    -3
      README.md
  2. +1
    -1
      src/JT808.Protocol.Test/JT808.Protocol.Test.csproj
  3. +34
    -0
      src/JT808.Protocol.Test/JT808HeaderPackageTest.cs
  4. +14
    -22
      src/JT808.Protocol.Test/Simples/Demo5.cs
  5. +5
    -1
      src/JT808.Protocol/JT808.Protocol.csproj
  6. +10
    -5
      src/JT808.Protocol/JT808.Protocol.xml
  7. +12
    -12
      src/JT808.Protocol/JT808HeaderPackage.cs
  8. +59
    -83
      src/JT808.Protocol/JT808Package.cs
  9. +0
    -33
      src/JT808.Protocol/JT808SplitPackageBodies.cs

+ 5
- 3
README.md Переглянути файл

@@ -17,9 +17,9 @@

### 数据包[JT808Package]

| 头标识 | 数据头 | 数据体 | 校验码 | 尾标识 |
| 头标识 | 数据头 | 数据体/分包数据体 | 校验码 | 尾标识 |
| :----: | :---------: | :---------: | :----------: | :----: |
| Begin | JT808Header | JT808Bodies |CheckCode | End |
| Begin | JT808Header | JT808Bodies/JT808SubDataBodies |CheckCode | End |
| 7E | - | - | - | 7E |

### 数据头[JT808Header]
@@ -244,7 +244,9 @@ JT808Serializer DT2JT808Serializer = new JT808Serializer(DT2JT808Config);

1. 第一包数据上来采用平常的方式去解析数据;

2. 当N包数据上来,采用统一分包消息体去接收数据,最后在合并成一条。
2. 当第二包上来跟第一包的分包数据体(SubDataBodies)进行合并

3. 当N包数据上来,延续步骤2的方式。

> 普及知识点:一般行业分包是按256的整数倍,太多不行,太少也不行,必须刚刚好。



+ 1
- 1
src/JT808.Protocol.Test/JT808.Protocol.Test.csproj Переглянути файл

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>9.0</LangVersion>
</PropertyGroup>


+ 34
- 0
src/JT808.Protocol.Test/JT808HeaderPackageTest.cs Переглянути файл

@@ -0,0 +1,34 @@
using JT808.Protocol.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;

namespace JT808.Protocol.Test
{
public class JT808HeaderPackageTest
{
JT808Serializer JT808Serializer = new JT808Serializer();

[Fact]
public void Test1()
{
var data1 = JT808Serializer.HeaderDeserialize("7E120523A204066657506200EB00020001015A00000023012012191042052012191050190000000000000000000101064446D10120121910221720121910420500000000000000000001010F1FE8EB0120121910023420121910221700000000000000000001010F182D5C0120121909471120121910015500000000000000000001010B38F2430120121909274020121909471100000000000000000001010F056DB40120121909080920121909274000000000000000000001010F0724380120121908483820121909080900000000000000000001010F0530AB0120121908290720121908483800000000000000000001010F05896C0120121908093720121908290700000000000000000001010F02CD3B0120121907500520121908093700000000000000000001010F056FEF0120121907303420121907500500000000000000000001010F043C3401201219072541201219073034000000000000000000010103C26C5F0120121907061120121907254100000000000000000001010F03F0C10120121906464220121907061100000000000000000001010F02F6330120121906271220121906464200000000000000000001010F02E43B0120121906074220121906271200000000000000000001010F033D670120121905481120121906074200000000000000000001010F088BF20120121905284120121905481100000000000000000001010F03F9FE0120121905091020121905284100000000000000000001010F05B1040120121904494020121905091000000000000000000001010F02B3540120121904301020121904494000000000000000000001010F0417B00120121904103920121904301000000000000000000001010F0538970120121903510820121904103900000000000000000001010F054E9E0120121903313820121903510800000000000000000001010F016ECB0120121903120820121903313800000000000000000001010F0333C00120121902523820121903120700000000000000000001010F029D230120121902330720121902523700000000000000000001010F0354E40120121902133720121902330700000000000000000001010F03303D0120121901540720121902133700000000000000000001010F04981E0120121901343720121901540700000000000000000001010F02AD940120121901150820121901343700000000000000000001010EFFD7CF0120121900553720121901150800000000000000000001010F07D9330120121900360720121900553700000000000000000001010F040E740C7E".ToHexBytes());
var data1_1 = data1.Bodies;
var data2 = JT808Serializer.HeaderDeserialize("7E1205203804066657506200EC000200020120121900163320121900360700000000000000000001010F0CE4CD0120121900002220121900163300000000000000000001010C6F9E7B5D7E".ToHexBytes());
var data2_1 = data2.Bodies;
Assert.Equal(data1.Bodies.ToArray(), data1_1);
Assert.Equal(data2.Bodies.ToArray(), data2_1);
var realBody = data1.Bodies.ToArray().Concat(data2.Bodies.ToArray()).ToArray();
}

[Fact]
public void Test2()
{
var json1 = JT808Serializer.Analyze("7E120523A204066657506200EB00020001015A00000023012012191042052012191050190000000000000000000101064446D10120121910221720121910420500000000000000000001010F1FE8EB0120121910023420121910221700000000000000000001010F182D5C0120121909471120121910015500000000000000000001010B38F2430120121909274020121909471100000000000000000001010F056DB40120121909080920121909274000000000000000000001010F0724380120121908483820121909080900000000000000000001010F0530AB0120121908290720121908483800000000000000000001010F05896C0120121908093720121908290700000000000000000001010F02CD3B0120121907500520121908093700000000000000000001010F056FEF0120121907303420121907500500000000000000000001010F043C3401201219072541201219073034000000000000000000010103C26C5F0120121907061120121907254100000000000000000001010F03F0C10120121906464220121907061100000000000000000001010F02F6330120121906271220121906464200000000000000000001010F02E43B0120121906074220121906271200000000000000000001010F033D670120121905481120121906074200000000000000000001010F088BF20120121905284120121905481100000000000000000001010F03F9FE0120121905091020121905284100000000000000000001010F05B1040120121904494020121905091000000000000000000001010F02B3540120121904301020121904494000000000000000000001010F0417B00120121904103920121904301000000000000000000001010F0538970120121903510820121904103900000000000000000001010F054E9E0120121903313820121903510800000000000000000001010F016ECB0120121903120820121903313800000000000000000001010F0333C00120121902523820121903120700000000000000000001010F029D230120121902330720121902523700000000000000000001010F0354E40120121902133720121902330700000000000000000001010F03303D0120121901540720121902133700000000000000000001010F04981E0120121901343720121901540700000000000000000001010F02AD940120121901150820121901343700000000000000000001010EFFD7CF0120121900553720121901150800000000000000000001010F07D9330120121900360720121900553700000000000000000001010F040E740C7E".ToHexBytes());
var json2 = JT808Serializer.Analyze("7E1205203804066657506200EC000200020120121900163320121900360700000000000000000001010F0CE4CD0120121900002220121900163300000000000000000001010C6F9E7B5D7E".ToHexBytes());
}
}
}

+ 14
- 22
src/JT808.Protocol.Test/Simples/Demo5.cs Переглянути файл

@@ -5,6 +5,8 @@ using System.Reflection;
using Xunit;
using System.Linq;
using JT808.Protocol.Internal;
using System.IO;
using System.Drawing;

namespace JT808.Protocol.Test.Simples
{
@@ -95,28 +97,18 @@ namespace JT808.Protocol.Test.Simples
Assert.Equal(10, jT808_0X0801_10.Header.PackageIndex);
Assert.Equal(10, jT808_0X0801_10.Header.PackgeCount);


var jT808_0X0801_body_1 = jT808_0X0801_1.Bodies as JT808_0x0801;
var jT808_0X0801_body_2 = jT808_0X0801_2.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_3 = jT808_0X0801_3.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_4 = jT808_0X0801_4.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_5 = jT808_0X0801_5.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_6 = jT808_0X0801_6.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_7 = jT808_0X0801_7.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_8 = jT808_0X0801_8.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_9 = jT808_0X0801_9.Bodies as JT808SplitPackageBodies;
var jT808_0X0801_body_10 = jT808_0X0801_10.Bodies as JT808SplitPackageBodies;
var imageBytes = jT808_0X0801_body_1.MultimediaDataPackage
.Concat(jT808_0X0801_body_2.Data)
.Concat(jT808_0X0801_body_3.Data)
.Concat(jT808_0X0801_body_4.Data)
.Concat(jT808_0X0801_body_5.Data)
.Concat(jT808_0X0801_body_6.Data)
.Concat(jT808_0X0801_body_7.Data)
.Concat(jT808_0X0801_body_8.Data)
.Concat(jT808_0X0801_body_9.Data)
.Concat(jT808_0X0801_body_10.Data).ToArray();
//using (MemoryStream ms = new MemoryStream(imageBytes))
var SplitBodyDataTotal = jT808_0X0801_1.SubDataBodies
.Concat(jT808_0X0801_2.SubDataBodies)
.Concat(jT808_0X0801_3.SubDataBodies)
.Concat(jT808_0X0801_4.SubDataBodies)
.Concat(jT808_0X0801_5.SubDataBodies)
.Concat(jT808_0X0801_6.SubDataBodies)
.Concat(jT808_0X0801_7.SubDataBodies)
.Concat(jT808_0X0801_8.SubDataBodies)
.Concat(jT808_0X0801_9.SubDataBodies)
.Concat(jT808_0X0801_10.SubDataBodies).ToArray();
JT808_0x0801 jT808_0x0801 = JT808Serializer.Deserialize<JT808_0x0801>(SplitBodyDataTotal);
//using (MemoryStream ms = new MemoryStream(jT808_0x0801.MultimediaDataPackage))
//{
// Image image = Image.FromStream(ms);
// image.Save("test.jpeg");


+ 5
- 1
src/JT808.Protocol/JT808.Protocol.csproj Переглянути файл

@@ -17,10 +17,14 @@
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<Version>2.3.2</Version>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<AnalysisLevel>5.0</AnalysisLevel>
<AnalysisLevel>latest</AnalysisLevel>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netstandard2.0|AnyCPU'">
<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<Compile Remove="Formatters\MessageBodyFormatters\**" />


+ 10
- 5
src/JT808.Protocol/JT808.Protocol.xml Переглянути файл

@@ -3408,6 +3408,11 @@
终止符
</summary>
</member>
<member name="P:JT808.Protocol.JT808HeaderPackage.Version">
<summary>
808版本号
</summary>
</member>
<member name="P:JT808.Protocol.JT808HeaderPackage.OriginalData">
<summary>
原数据
@@ -3443,6 +3448,11 @@
数据体
</summary>
</member>
<member name="P:JT808.Protocol.JT808Package.SubDataBodies">
<summary>
分包数据体
</summary>
</member>
<member name="P:JT808.Protocol.JT808Package.CheckCode">
<summary>
校验码
@@ -3467,11 +3477,6 @@
<param name="bytes"></param>
<returns></returns>
</member>
<member name="T:JT808.Protocol.JT808SplitPackageBodies">
<summary>
统一分包数据体
</summary>
</member>
<member name="T:JT808.Protocol.MessageBody.CarDVR.JT808_CarDVR_Down_0x00">
<summary>
采集记录仪执行标准版本


+ 12
- 12
src/JT808.Protocol/JT808HeaderPackage.cs Переглянути файл

@@ -1,16 +1,13 @@
using JT808.Protocol.Attributes;
using JT808.Protocol.Enums;
using JT808.Protocol.Enums;
using JT808.Protocol.Exceptions;
using JT808.Protocol.Formatters;
using JT808.Protocol.MessagePack;
using System;

namespace JT808.Protocol
{
/// <summary>
/// JT808头部数据包
/// </summary>
public ref struct JT808HeaderPackage
public record JT808HeaderPackage
{
/// <summary>
/// 起始符
@@ -23,7 +20,7 @@ namespace JT808.Protocol
/// <summary>
/// 数据体
/// </summary>
public ReadOnlySpan<byte> Bodies { get; set; }
public byte[] Bodies { get; set; }
/// <summary>
/// 校验码
/// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。
@@ -33,7 +30,10 @@ namespace JT808.Protocol
/// 终止符
/// </summary>
public byte End { get; set; }
public JT808Version Version
/// <summary>
/// 808版本号
/// </summary>
public JT808Version Version
{
get {
if (Header != null)
@@ -63,9 +63,9 @@ namespace JT808.Protocol
/// <summary>
/// 原数据
/// </summary>
public ReadOnlySpan<byte> OriginalData { get; set; }
public byte[] OriginalData { get; set; }

public JT808HeaderPackage(ref JT808MessagePackReader reader, IJT808Config config)
public JT808HeaderPackage(ref JT808MessagePackReader reader, IJT808Config config)
{
// 1. 验证校验和
if (!config.SkipCRCCode)
@@ -115,18 +115,18 @@ namespace JT808.Protocol
// 4.1.判断有无数据体
if (this.Header.MessageBodyProperty.DataLength > 0)
{
this.Bodies = reader.ReadContent();
this.Bodies = reader.ReadContent().ToArray();
}
else
{
this.Bodies = ReadOnlySpan<byte>.Empty;
this.Bodies = default;
}
// 5.读取校验码
this.CheckCode = reader.ReadByte();
// 6.读取终止位置
this.End = reader.ReadEnd();
// ---------------解包完成--------------
this.OriginalData = reader.SrcBuffer;
this.OriginalData = reader.SrcBuffer.ToArray();
}
}
}

+ 59
- 83
src/JT808.Protocol/JT808Package.cs Переглянути файл

@@ -5,7 +5,6 @@ using JT808.Protocol.Formatters;
using JT808.Protocol.Interfaces;
using JT808.Protocol.MessagePack;
using System;
using System.Runtime.InteropServices;
using System.Text.Json;

namespace JT808.Protocol
@@ -36,6 +35,10 @@ namespace JT808.Protocol
/// </summary>
public JT808Bodies Bodies { get; set; }
/// <summary>
/// 分包数据体
/// </summary>
public byte[] SubDataBodies { get; set; }
/// <summary>
/// 校验码
/// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。
/// </summary>
@@ -128,32 +131,14 @@ namespace JT808.Protocol
{
if (jT808Package.Header.MessageBodyProperty.IsPackage)
{
if (jT808Package.Header.PackageIndex > 1)
//读取分包的数据体
try
{
try
{
//4.2处理第二包之后的分包数据消息体
JT808SplitPackageBodies jT808SplitPackageBodies = new JT808SplitPackageBodies();
jT808Package.Bodies = jT808SplitPackageBodies.Deserialize(ref reader, config);
}
catch (Exception ex)
{
throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
}
jT808Package.SubDataBodies = reader.ReadArray(jT808Package.Header.MessageBodyProperty.DataLength).ToArray();
}
else
catch (Exception ex)
{
try
{
//4.2.处理消息体
jT808Package.Bodies = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(
instance,
ref reader, config);
}
catch (Exception ex)
{
throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
}
throw new JT808Exception(JT808ErrorCode.BodiesParseError, ex);
}
}
else
@@ -225,14 +210,25 @@ namespace JT808.Protocol
writer.WriteUInt16(value.Header.PackageIndex);
}
int headerLength = writer.GetCurrentPosition();
// 3.处理数据体部分
if (value.Bodies != null)
if (value.Header.MessageBodyProperty.IsPackage)
{
if (value.SubDataBodies != null)
{
//2.5.3.写入分包数据
writer.WriteArray(value.SubDataBodies);
}
}
else
{
if (!value.Bodies.SkipSerialization)
// 3.处理数据体部分
if (value.Bodies != null)
{
JT808MessagePackFormatterResolverExtensions.JT808DynamicSerialize(value.Bodies,
ref writer, value.Bodies,
config);
if (!value.Bodies.SkipSerialization)
{
JT808MessagePackFormatterResolverExtensions.JT808DynamicSerialize(value.Bodies,
ref writer, value.Bodies,
config);
}
}
}
// 3.1.处理数据体长度
@@ -318,58 +314,38 @@ namespace JT808.Protocol
// 4.1.判断有无数据体
if (headerMessageBodyProperty.DataLength > 0)
{
if (config.MsgIdFactory.TryGetValue(msgid, out object instance))
//数据体属性对象 开始
writer.WriteStartObject("数据体对象");
string description = "数据体";
if (headerMessageBodyProperty.IsPackage)
{
//数据体属性对象 开始
writer.WriteStartObject("数据体对象");
string description = "数据体";
if (instance is IJT808Description jT808Description)
//读取分包的数据体
try
{
//4.2.处理消息体
description = jT808Description.Description;
writer.WriteString($"[分包]数据体", reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray().ToHexString());
}
if (headerMessageBodyProperty.IsPackage)
catch (IndexOutOfRangeException ex)
{
if (packageIndex > 1)
{
try
{
//4.2处理第二包之后的分包数据消息体
writer.WriteString($"[分包]数据体", reader.ReadContent().ToArray().ToHexString());
}
catch (Exception ex)
{
writer.WriteString($"[分包]数据体异常", ex.StackTrace);
}
}
else
{
try
{
//数据体长度正常
writer.WriteString($"[分包]{description}", reader.ReadVirtualArray(reader.ReadCurrentRemainContentLength()).ToArray().ToHexString());
if (instance is IJT808Analyze analyze)
{
//4.2.处理消息体
analyze.Analyze(ref reader, writer, config);
}
}
catch (IndexOutOfRangeException ex)
{
writer.WriteString($"数据体解析异常,无可用数据体进行解析", ex.StackTrace);
}
catch (ArgumentOutOfRangeException ex)
{
writer.WriteString($"[分包]数据体解析异常,无可用数据体进行解析", ex.StackTrace);
}
catch (Exception ex)
{
writer.WriteString($"[分包]数据体异常", ex.StackTrace);
}
}
writer.WriteString($"数据体解析异常,无可用数据体进行解析", ex.StackTrace);
}
else
catch (ArgumentOutOfRangeException ex)
{
writer.WriteString($"[分包]数据体解析异常,无可用数据体进行解析", ex.StackTrace);
}
catch (Exception ex)
{
writer.WriteString($"[分包]数据体异常", ex.StackTrace);
}
}
else
{
if (config.MsgIdFactory.TryGetValue(msgid, out object instance))
{
if (instance is IJT808Description jT808Description)
{
//4.2.处理消息体
description = jT808Description.Description;
}
try
{
//数据体长度正常
@@ -380,7 +356,7 @@ namespace JT808.Protocol
analyze.Analyze(ref reader, writer, config);
}
}
catch(IndexOutOfRangeException ex)
catch (IndexOutOfRangeException ex)
{
writer.WriteString($"数据体解析异常,无可用数据体进行解析", ex.StackTrace);
}
@@ -393,13 +369,13 @@ namespace JT808.Protocol
writer.WriteString($"数据体异常", ex.StackTrace);
}
}
//数据体属性对象 结束
writer.WriteEndObject();
}
else
{
writer.WriteNull($"[Null]数据体");
else
{
writer.WriteString($"[未知]数据体", reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray().ToHexString());
}
}
//数据体属性对象 结束
writer.WriteEndObject();
}
else
{


+ 0
- 33
src/JT808.Protocol/JT808SplitPackageBodies.cs Переглянути файл

@@ -1,33 +0,0 @@
using JT808.Protocol.Attributes;
using JT808.Protocol.Formatters;
using JT808.Protocol.MessagePack;

namespace JT808.Protocol
{
/// <summary>
/// 统一分包数据体
/// </summary>
public class JT808SplitPackageBodies : JT808Bodies, IJT808MessagePackFormatter<JT808SplitPackageBodies>
{

public byte[] Data { get; set; }

public override ushort MsgId => 0xFFFF;

public override string Description => "统一分包数据体";

public JT808SplitPackageBodies Deserialize(ref JT808MessagePackReader reader, IJT808Config config)
{
JT808SplitPackageBodies jT808SplitPackageBodies = new JT808SplitPackageBodies
{
Data = reader.ReadContent().ToArray()
};
return jT808SplitPackageBodies;
}

public void Serialize(ref JT808MessagePackWriter writer, JT808SplitPackageBodies value, IJT808Config config)
{
writer.WriteArray(value.Data);
}
}
}

Завантаження…
Відмінити
Зберегти