@@ -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,7 +1,7 @@ | |||
<Project Sdk="Microsoft.NET.Sdk"> | |||
<PropertyGroup> | |||
<TargetFramework>net5</TargetFramework> | |||
<TargetFramework>net5.0</TargetFramework> | |||
<IsPackable>false</IsPackable> | |||
<LangVersion>9.0</LangVersion> | |||
</PropertyGroup> | |||
@@ -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()); | |||
} | |||
} | |||
} |
@@ -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"); | |||
@@ -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\**" /> | |||
@@ -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> | |||
采集记录仪执行标准版本 | |||
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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 | |||
{ | |||
@@ -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); | |||
} | |||
} | |||
} |