@@ -23,15 +23,15 @@ | |||||
### 数据头[JT808Header] | ### 数据头[JT808Header] | ||||
| 消息ID | 消息体属性 | 终端手机号 | 消息流水号 | 消息总包数(依赖是否分包) | 包序号(依赖是否分包) | | |||||
| :----: | :----------------------------: | :-------------: | :--------: |:---------: | :-------:| | |||||
| MsgId | JT808HeaderMessageBodyProperty | TerminalPhoneNo | MsgNum |PackgeCount | PackageIndex | | |||||
| 消息ID | 消息体属性 | 协议版本号(2019版本)|终端手机号 | 消息流水号 | 消息总包数(依赖是否分包) | 包序号(依赖是否分包) | | |||||
| :----: | :----------------------------: | :-------------: |:-------------: | :--------: |:---------: | :-------:| | |||||
| MsgId | JT808HeaderMessageBodyProperty | ProtocolVersion|TerminalPhoneNo | MsgNum |PackgeCount | PackageIndex | | |||||
#### 数据头-消息体属性[JT808HeaderMessageBodyProperty] | #### 数据头-消息体属性[JT808HeaderMessageBodyProperty] | ||||
| 是否分包 | 加密标识 | 消息体长度 | | |||||
| :------: | :------: | :--------: | | |||||
| IsPackge | Encrypt | DataLength | | |||||
|版本标识(2019版本)| 是否分包 | 加密标识 | 消息体长度 | | |||||
|:------:| :------: | :------: | :--------: | | |||||
|VersionFlag| IsPackge | Encrypt | DataLength | | |||||
#### 消息体属性[JT808Bodies] | #### 消息体属性[JT808Bodies] | ||||
@@ -306,17 +306,17 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 | |||||
## JT808终端通讯协议消息对照表 | ## JT808终端通讯协议消息对照表 | ||||
| 序号 | 消息ID | 完成情况 | 测试情况 | 消息体名称 | | |||||
| :---: | :-----------: | :------: | :------: | :----------------------------: | | |||||
| 序号 | 消息ID | 完成情况 | 测试情况 | 消息体名称 |2019版本| | |||||
| :---: | :-----------: | :------: | :------: | :----------------------------: |:----------------------------:| | |||||
| 1 | 0x0001 | √ | √ | 终端通用应答 | | | 1 | 0x0001 | √ | √ | 终端通用应答 | | ||||
| 2 | 0x8001 | √ | √ | 平台通用应答 | | | 2 | 0x8001 | √ | √ | 平台通用应答 | | ||||
| 3 | 0x0002 | √ | √ | 终端心跳 | | | 3 | 0x0002 | √ | √ | 终端心跳 | | ||||
| 4 | 0x8003 | √ | √ | 补传分包请求 | | | 4 | 0x8003 | √ | √ | 补传分包请求 | | ||||
| 5 | 0x0100 | √ | √ | 终端注册 | | |||||
| 5 | 0x0100 | √ | √ | 终端注册 |修改| | |||||
| 6 | 0x8100 | √ | √ | 终端注册应答 | | | 6 | 0x8100 | √ | √ | 终端注册应答 | | ||||
| 7 | 0x0003 | √ | √ | 终端注销 | | | 7 | 0x0003 | √ | √ | 终端注销 | | ||||
| 8 | 0x0102 | √ | √ | 终端鉴权 | | |||||
| 9 | 0x8103 | √ | √ | 设置终端参数 | | |||||
| 8 | 0x0102 | √ | √ | 终端鉴权 |修改| | |||||
| 9 | 0x8103 | √ | x | 设置终端参数 |修改且增加| | |||||
| 10 | 0x8104 | √ | √ | 查询终端参数 | | | 10 | 0x8104 | √ | √ | 查询终端参数 | | ||||
| 11 | 0x0104 | √ | √ | 查询终端参数应答 | | | 11 | 0x0104 | √ | √ | 查询终端参数应答 | | ||||
| 12 | 0x8105 | √ | √ | 终端控制 | | | 12 | 0x8105 | √ | √ | 终端控制 | | ||||
@@ -350,9 +350,9 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 | |||||
| 40 | 0x8605 | √ | √ | 删除多边形区域 | | | 40 | 0x8605 | √ | √ | 删除多边形区域 | | ||||
| 41 | 0x8606 | √ | √ | 设置路线 | | | 41 | 0x8606 | √ | √ | 设置路线 | | ||||
| 42 | 0x8607 | √ | √ | 删除路线 | | | 42 | 0x8607 | √ | √ | 删除路线 | | ||||
| 43 | 0x8700 | x | 下个版本 | 行驶记录仪数据采集命令 | | |||||
| 44 | 0x0700 | x | 下个版本 | 行驶记录仪数据上传 | | |||||
| 45 | 0x8701 | x | 下个版本 | 行驶记录仪参数下传命令 | | |||||
| 43 | 0x8700 | x | 不开发 | 行驶记录仪数据采集命令 | | |||||
| 44 | 0x0700 | x | 不开发 | 行驶记录仪数据上传 | | |||||
| 45 | 0x8701 | x | 不开发 | 行驶记录仪参数下传命令 | | |||||
| 46 | 0x0701 | √ | √ | 电子运单上报 | | | 46 | 0x0701 | √ | √ | 电子运单上报 | | ||||
| 47 | 0x0702 | √ | √ | 驾驶员身份信息采集上报 | | | 47 | 0x0702 | √ | √ | 驾驶员身份信息采集上报 | | ||||
| 48 | 0x8702 | √ | 消息体为空| 上报驾驶员身份信息请求 | | | 48 | 0x8702 | √ | 消息体为空| 上报驾驶员身份信息请求 | | ||||
@@ -375,3 +375,6 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 | |||||
| 65 | 0x0A00 | √ | √ | 终端 RSA 公钥 | | | 65 | 0x0A00 | √ | √ | 终端 RSA 公钥 | | ||||
| 66 | 0x8F00~0x8FFF | 保留 | 保留 | 平台下行消息保留 | | | 66 | 0x8F00~0x8FFF | 保留 | 保留 | 平台下行消息保留 | | ||||
| 67 | 0x0F00~0x0FFF | 保留 | 保留 | 终端上行消息保留 | | | 67 | 0x0F00~0x0FFF | 保留 | 保留 | 终端上行消息保留 | | ||||
| 68 | 0x0004 | √ | √ | 查询服务器时间请求 |新增| | |||||
| 69 | 0x8004 | √ | √ | 查询服务器时间应答 |新增| | |||||
| 70 | 0x0005 | √ | √ | 终端补传分包请求 |新增| |
@@ -56,6 +56,8 @@ | |||||
<Compile Include="MessageBody\JT808_0x0901Test.cs" /> | <Compile Include="MessageBody\JT808_0x0901Test.cs" /> | ||||
<Compile Include="MessageBody\JT808_0x0A00Test.cs" /> | <Compile Include="MessageBody\JT808_0x0A00Test.cs" /> | ||||
<Compile Include="MessageBody\JT808_0x8001Test.cs" /> | <Compile Include="MessageBody\JT808_0x8001Test.cs" /> | ||||
<Compile Include="MessageBody\JT808_0x0005Test.cs" /> | |||||
<Compile Include="MessageBody\JT808_0x8004Test.cs" /> | |||||
<Compile Include="MessageBody\JT808_0x8003Test.cs" /> | <Compile Include="MessageBody\JT808_0x8003Test.cs" /> | ||||
<Compile Include="MessageBody\JT808_0x8100Test.cs" /> | <Compile Include="MessageBody\JT808_0x8100Test.cs" /> | ||||
<Compile Include="MessageBody\JT808_0x8103CustomIdExtensions\JT808_0x8103_0x0075.cs" /> | <Compile Include="MessageBody\JT808_0x8103CustomIdExtensions\JT808_0x8103_0x0075.cs" /> | ||||
@@ -94,6 +96,10 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8"> | |||||
<PrivateAssets>all</PrivateAssets> | |||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||||
</PackageReference> | |||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> | ||||
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> | <PackageReference Include="NETStandard.Library" Version="2.0.3" /> | ||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> | <PackageReference Include="Newtonsoft.Json" Version="12.0.2" /> | ||||
@@ -27,5 +27,49 @@ namespace JT808.Protocol.Test | |||||
Assert.True(jT808HeaderMessageBodyProperty.IsPackage); | Assert.True(jT808HeaderMessageBodyProperty.IsPackage); | ||||
Assert.Equal(JT808EncryptMethod.RSA, jT808HeaderMessageBodyProperty.Encrypt); | Assert.Equal(JT808EncryptMethod.RSA, jT808HeaderMessageBodyProperty.Encrypt); | ||||
} | } | ||||
[Fact] | |||||
public void Test2019_1() | |||||
{ | |||||
//01 1 001 0011111111 | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(); | |||||
jT808HeaderMessageBodyProperty.DataLength = 255; | |||||
jT808HeaderMessageBodyProperty.IsPackage = true; | |||||
jT808HeaderMessageBodyProperty.Encrypt = JT808EncryptMethod.RSA; | |||||
jT808HeaderMessageBodyProperty.VersionFlag = true; | |||||
var result = jT808HeaderMessageBodyProperty.Wrap(); | |||||
Assert.Equal(25855, result); | |||||
} | |||||
[Fact] | |||||
public void Test2019_2() | |||||
{ | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(25855); | |||||
Assert.Equal(255, jT808HeaderMessageBodyProperty.DataLength); | |||||
Assert.True(jT808HeaderMessageBodyProperty.IsPackage); | |||||
Assert.True(jT808HeaderMessageBodyProperty.VersionFlag); | |||||
Assert.Equal(JT808EncryptMethod.RSA, jT808HeaderMessageBodyProperty.Encrypt); | |||||
} | |||||
[Fact] | |||||
public void Test2019_3() | |||||
{ | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(); | |||||
jT808HeaderMessageBodyProperty.DataLength = 255; | |||||
jT808HeaderMessageBodyProperty.IsPackage = false; | |||||
jT808HeaderMessageBodyProperty.Encrypt = JT808EncryptMethod.RSA; | |||||
jT808HeaderMessageBodyProperty.VersionFlag = true; | |||||
ushort result = jT808HeaderMessageBodyProperty.Wrap(); | |||||
Assert.Equal(17663, result); | |||||
} | |||||
[Fact] | |||||
public void Test2019_4() | |||||
{ | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(17663); | |||||
Assert.Equal(255, jT808HeaderMessageBodyProperty.DataLength); | |||||
Assert.False(jT808HeaderMessageBodyProperty.IsPackage); | |||||
Assert.True(jT808HeaderMessageBodyProperty.VersionFlag); | |||||
Assert.Equal(JT808EncryptMethod.RSA, jT808HeaderMessageBodyProperty.Encrypt); | |||||
} | |||||
} | } | ||||
} | } |
@@ -8,6 +8,7 @@ namespace JT808.Protocol.Test | |||||
public class JT808HeaderTest | public class JT808HeaderTest | ||||
{ | { | ||||
JT808Serializer JT808Serializer = new JT808Serializer(); | JT808Serializer JT808Serializer = new JT808Serializer(); | ||||
[Fact] | [Fact] | ||||
public void Test3() | public void Test3() | ||||
{ | { | ||||
@@ -34,7 +35,7 @@ namespace JT808.Protocol.Test | |||||
jT808HeaderProperty.MsgId = JT808MsgId.终端鉴权.ToUInt16Value(); | jT808HeaderProperty.MsgId = JT808MsgId.终端鉴权.ToUInt16Value(); | ||||
var hex = JT808Serializer.Serialize(jT808HeaderProperty).ToHexString(); | var hex = JT808Serializer.Serialize(jT808HeaderProperty).ToHexString(); | ||||
Assert.Equal("01 02 00 05 01 38 12 34 56 78 00 87".Replace(" ",""), hex); | |||||
Assert.Equal("01 02 00 05 01 38 12 34 56 78 00 87".Replace(" ", ""), hex); | |||||
} | } | ||||
[Fact] | [Fact] | ||||
@@ -75,5 +76,39 @@ namespace JT808.Protocol.Test | |||||
Assert.Equal(JT808MsgId.终端鉴权.ToValue(), jT808Header.MsgId); | Assert.Equal(JT808MsgId.终端鉴权.ToValue(), jT808Header.MsgId); | ||||
Assert.Equal(5, jT808Header.MessageBodyProperty.DataLength); | Assert.Equal(5, jT808Header.MessageBodyProperty.DataLength); | ||||
} | } | ||||
[Fact] | |||||
public void JT808Header_2019Test1() | |||||
{ | |||||
JT808Header jT808HeaderProperty = new JT808Header | |||||
{ | |||||
TerminalPhoneNo = "13812345678" | |||||
}; | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(); | |||||
jT808HeaderMessageBodyProperty.DataLength = 255; | |||||
jT808HeaderMessageBodyProperty.IsPackage = true; | |||||
jT808HeaderMessageBodyProperty.Encrypt = JT808EncryptMethod.RSA; | |||||
jT808HeaderMessageBodyProperty.VersionFlag = true; | |||||
jT808HeaderProperty.MessageBodyProperty = jT808HeaderMessageBodyProperty; | |||||
jT808HeaderProperty.MsgNum = 135; | |||||
jT808HeaderProperty.MsgId = JT808MsgId.终端鉴权.ToUInt16Value(); | |||||
jT808HeaderProperty.ProtocolVersion = 2; | |||||
var hex = JT808Serializer.Serialize(jT808HeaderProperty).ToHexString(); | |||||
Assert.Equal("010264FF0200000000013812345678008700000000", hex); | |||||
} | |||||
[Fact] | |||||
public void JT808Header_2019Test2() | |||||
{ | |||||
byte[] headerBytes = "010264FF0200000000013812345678008700000000".ToHexBytes(); | |||||
JT808Header jT808Header = JT808Serializer.Deserialize<JT808Header>(headerBytes); | |||||
Assert.Equal(135, jT808Header.MsgNum); | |||||
Assert.Equal(2, jT808Header.ProtocolVersion); | |||||
Assert.Equal("13812345678", jT808Header.TerminalPhoneNo); | |||||
Assert.True(jT808Header.MessageBodyProperty.IsPackage); | |||||
Assert.True(jT808Header.MessageBodyProperty.VersionFlag); | |||||
Assert.Equal(JT808MsgId.终端鉴权.ToValue(), jT808Header.MsgId); | |||||
Assert.Equal(255, jT808Header.MessageBodyProperty.DataLength); | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,33 @@ | |||||
using System.Text; | |||||
using Xunit; | |||||
using JT808.Protocol.Extensions; | |||||
using JT808.Protocol.MessageBody; | |||||
namespace JT808.Protocol.Test.MessageBody | |||||
{ | |||||
public class JT808_0x0005Test | |||||
{ | |||||
JT808Serializer JT808Serializer = new JT808Serializer(); | |||||
[Fact] | |||||
public void Test1() | |||||
{ | |||||
JT808_0x0005 jT808_0X8005 = new JT808_0x0005 | |||||
{ | |||||
OriginalMsgNum = 1234, | |||||
AgainPackageData = new byte[] { 0x01, 0x02, 0x02, 0x03 } | |||||
}; | |||||
var hex = JT808Serializer.Serialize(jT808_0X8005).ToHexString(); | |||||
Assert.Equal("04D20201020203", hex); | |||||
} | |||||
[Fact] | |||||
public void Test2() | |||||
{ | |||||
var bytes = "04D20201020203".ToHexBytes(); | |||||
JT808_0x0005 jT808_0X8005 = JT808Serializer.Deserialize<JT808_0x0005>(bytes); | |||||
Assert.Equal(1234, jT808_0X8005.OriginalMsgNum); | |||||
Assert.Equal(new byte[] { 0x01, 0x02, 0x02, 0x03 }, jT808_0X8005.AgainPackageData); | |||||
Assert.Equal(2, jT808_0X8005.AgainPackageCount); | |||||
} | |||||
} | |||||
} |
@@ -1,6 +1,7 @@ | |||||
using Xunit; | using Xunit; | ||||
using JT808.Protocol.MessageBody; | using JT808.Protocol.MessageBody; | ||||
using JT808.Protocol.Extensions; | using JT808.Protocol.Extensions; | ||||
using JT808.Protocol.Enums; | |||||
namespace JT808.Protocol.Test.MessageBody | namespace JT808.Protocol.Test.MessageBody | ||||
{ | { | ||||
@@ -52,5 +53,56 @@ namespace JT808.Protocol.Test.MessageBody | |||||
Assert.Equal("CHI1230", JT808Bodies.TerminalId); | Assert.Equal("CHI1230", JT808Bodies.TerminalId); | ||||
Assert.Equal("smallchi123000000000", JT808Bodies.TerminalModel); | Assert.Equal("smallchi123000000000", JT808Bodies.TerminalModel); | ||||
} | } | ||||
[Fact] | |||||
public void Test2019_1() | |||||
{ | |||||
JT808Package jT808_0X0100 = new JT808Package | |||||
{ | |||||
Header = new JT808Header | |||||
{ | |||||
MsgId = Enums.JT808MsgId.终端注册.ToUInt16Value(), | |||||
MsgNum = 10, | |||||
TerminalPhoneNo = "123456789", | |||||
ProtocolVersion=1, | |||||
}, | |||||
Bodies = new JT808_0x0100 | |||||
{ | |||||
AreaID = 40, | |||||
CityOrCountyId = 50, | |||||
MakerId = "1234", | |||||
PlateColor = 1, | |||||
PlateNo = "粤A12345", | |||||
TerminalId = "CHI123", | |||||
TerminalModel = "smallchi123" | |||||
} | |||||
}; | |||||
JT808HeaderMessageBodyProperty jT808HeaderMessageBodyProperty = new JT808HeaderMessageBodyProperty(true); | |||||
jT808_0X0100.Header.MessageBodyProperty = jT808HeaderMessageBodyProperty; | |||||
var hex = JT808Serializer.Serialize(jT808_0X0100).ToHexString(); | |||||
Assert.Equal("7E010040540100000000000123456789000A00280032303030303030303132333430303030303030303030303030303030303030736D616C6C63686931323330303030303030303030303030303030303030303030303043484931323301D4C1413132333435B27E", hex); | |||||
} | |||||
[Fact] | |||||
public void Test2019_2() | |||||
{ | |||||
byte[] bytes = "7E010040540100000000000123456789000A00280032303030303030303132333430303030303030303030303030303030303030736D616C6C63686931323330303030303030303030303030303030303030303030303043484931323301D4C1413132333435B27E".ToHexBytes(); | |||||
JT808Package jT808_0X0100 = JT808Serializer.Deserialize<JT808Package>(bytes); | |||||
Assert.Equal(JT808MsgId.终端注册.ToUInt16Value(), jT808_0X0100.Header.MsgId); | |||||
Assert.Equal(1, jT808_0X0100.Header.ProtocolVersion); | |||||
Assert.Equal(JT808Version.JTT2019, jT808_0X0100.Version); | |||||
Assert.True(jT808_0X0100.Header.MessageBodyProperty.VersionFlag); | |||||
Assert.Equal(10, jT808_0X0100.Header.MsgNum); | |||||
Assert.Equal("123456789", jT808_0X0100.Header.TerminalPhoneNo); | |||||
JT808_0x0100 JT808Bodies = (JT808_0x0100)jT808_0X0100.Bodies; | |||||
Assert.Equal(40, JT808Bodies.AreaID); | |||||
Assert.Equal(50, JT808Bodies.CityOrCountyId); | |||||
Assert.Equal("1234".PadLeft(11,'0'), JT808Bodies.MakerId); | |||||
Assert.Equal(1, JT808Bodies.PlateColor); | |||||
Assert.Equal("粤A12345", JT808Bodies.PlateNo); | |||||
Assert.Equal("CHI123".PadLeft(30, '0'), JT808Bodies.TerminalId); | |||||
Assert.Equal("smallchi123".PadLeft(30, '0'), JT808Bodies.TerminalModel); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,6 +1,7 @@ | |||||
using Xunit; | using Xunit; | ||||
using JT808.Protocol.MessageBody; | using JT808.Protocol.MessageBody; | ||||
using JT808.Protocol.Extensions; | using JT808.Protocol.Extensions; | ||||
using JT808.Protocol.Enums; | |||||
namespace JT808.Protocol.Test.MessageBody | namespace JT808.Protocol.Test.MessageBody | ||||
{ | { | ||||
@@ -26,6 +27,30 @@ namespace JT808.Protocol.Test.MessageBody | |||||
Assert.Equal("45612", jT808LoginRequest.Code); | Assert.Equal("45612", jT808LoginRequest.Code); | ||||
} | } | ||||
[Fact] | |||||
public void Test2019_1() | |||||
{ | |||||
JT808_0x0102 jT808LoginRequestProperty = new JT808_0x0102 | |||||
{ | |||||
Code = "45612", | |||||
IMEI="1234567890abcde", | |||||
SoftwareVersion="v2.0.0" | |||||
}; | |||||
string hex = JT808Serializer.Serialize(jT808LoginRequestProperty,JT808Version.JTT2019).ToHexString(); | |||||
Assert.Equal("05343536313231323334353637383930616263646576322E302E303030303030303030303030303030", hex); | |||||
} | |||||
[Fact] | |||||
public void Test2019_2() | |||||
{ | |||||
byte[] bodys = "05343536313231323334353637383930616263646576322E302E303030303030303030303030303030".ToHexBytes(); | |||||
JT808_0x0102 jT808LoginRequest = JT808Serializer.Deserialize<JT808_0x0102>(bodys, JT808Version.JTT2019); | |||||
Assert.Equal("45612", jT808LoginRequest.Code); | |||||
Assert.Equal(5, jT808LoginRequest.CodeLength); | |||||
Assert.Equal("1234567890abcde", jT808LoginRequest.IMEI); | |||||
Assert.Equal("v2.0.0".PadRight(20,'0'), jT808LoginRequest.SoftwareVersion); | |||||
} | |||||
[Fact] | [Fact] | ||||
public void Test3() | public void Test3() | ||||
{ | { | ||||
@@ -0,0 +1,31 @@ | |||||
using System.Text; | |||||
using Xunit; | |||||
using JT808.Protocol.Extensions; | |||||
using JT808.Protocol.MessageBody; | |||||
using System; | |||||
namespace JT808.Protocol.Test.MessageBody | |||||
{ | |||||
public class JT808_0x8004Test | |||||
{ | |||||
JT808Serializer JT808Serializer = new JT808Serializer(); | |||||
[Fact] | |||||
public void Test1() | |||||
{ | |||||
JT808_0x8004 jT808_0X8004 = new JT808_0x8004 | |||||
{ | |||||
Time = DateTime.Parse("2019-11-26 15:58:50") | |||||
}; | |||||
var hex = JT808Serializer.Serialize(jT808_0X8004).ToHexString(); | |||||
Assert.Equal("191126155850", hex); | |||||
} | |||||
[Fact] | |||||
public void Test2() | |||||
{ | |||||
var bytes = "191126155850".ToHexBytes(); | |||||
JT808_0x8004 jT808_0X8004 = JT808Serializer.Deserialize<JT808_0x8004>(bytes); | |||||
Assert.Equal(DateTime.Parse("2019-11-26 15:58:50"), jT808_0X8004.Time); | |||||
} | |||||
} | |||||
} |
@@ -8,6 +8,7 @@ using System.Buffers; | |||||
using JT808.Protocol.Formatters; | using JT808.Protocol.Formatters; | ||||
using JT808.Protocol.Interfaces; | using JT808.Protocol.Interfaces; | ||||
using JT808.Protocol.Internal; | using JT808.Protocol.Internal; | ||||
using JT808.Protocol.Enums; | |||||
namespace JT808.Protocol.Test.MessagePack | namespace JT808.Protocol.Test.MessagePack | ||||
{ | { | ||||
@@ -228,5 +229,15 @@ namespace JT808.Protocol.Test.MessagePack | |||||
} | } | ||||
} | } | ||||
} | } | ||||
[Fact] | |||||
public void VersionTest1() | |||||
{ | |||||
byte[] array = new byte[4096]; | |||||
var reader = new JT808MessagePackReader(array); | |||||
Assert.Equal(JT808Version.JTT2013, reader.Version); | |||||
reader.Version = JT808Version.JTT2019; | |||||
Assert.Equal(JT808Version.JTT2019, reader.Version); | |||||
} | |||||
} | } | ||||
} | } |
@@ -5,6 +5,7 @@ using System.Collections.Generic; | |||||
using System.Text; | using System.Text; | ||||
using Xunit; | using Xunit; | ||||
using System.Buffers; | using System.Buffers; | ||||
using JT808.Protocol.Enums; | |||||
namespace JT808.Protocol.Test.MessagePack | namespace JT808.Protocol.Test.MessagePack | ||||
{ | { | ||||
@@ -457,5 +458,15 @@ namespace JT808.Protocol.Test.MessagePack | |||||
var realBytes = msgpackWriter.FlushAndGetRealArray().ToHexString(); | var realBytes = msgpackWriter.FlushAndGetRealArray().ToHexString(); | ||||
Assert.Equal("7E 01 7E 00 7D 01 23 45 67 89 00 00 00 00 00 7E 7E 01 7D 02 00 7D 01 01 23 45 67 89 00 00 00 00 00 7E".Replace(" ", ""), realBytes); | Assert.Equal("7E 01 7E 00 7D 01 23 45 67 89 00 00 00 00 00 7E 7E 01 7D 02 00 7D 01 01 23 45 67 89 00 00 00 00 00 7E".Replace(" ", ""), realBytes); | ||||
} | } | ||||
[Fact] | |||||
public void VersionTest1() | |||||
{ | |||||
byte[] array = new byte[4096]; | |||||
var msgpackWriter = new JT808MessagePackWriter(array); | |||||
Assert.Equal(JT808Version.JTT2013, msgpackWriter.Version); | |||||
msgpackWriter.Version = JT808Version.JTT2019; | |||||
Assert.Equal(JT808Version.JTT2019, msgpackWriter.Version); | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,17 +0,0 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace JT808.Protocol.Attributes | |||||
{ | |||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] | |||||
public sealed class JT808FormatterAttribute : Attribute | |||||
{ | |||||
public Type FormatterType { get; private set; } | |||||
public JT808FormatterAttribute(Type formatterType) | |||||
{ | |||||
this.FormatterType = formatterType; | |||||
} | |||||
} | |||||
} |
@@ -7,11 +7,6 @@ | |||||
/// </summary> | /// </summary> | ||||
CheckCodeNotEqual = 1001, | CheckCodeNotEqual = 1001, | ||||
/// <summary> | /// <summary> | ||||
/// 没有标记 | |||||
/// <see cref="JT808.Protocol.Attributes.JT808FormatterAttribute"/> | |||||
/// </summary> | |||||
GetFormatterAttributeError = 1002, | |||||
/// <summary> | |||||
/// 消息头解析错误 | /// 消息头解析错误 | ||||
/// </summary> | /// </summary> | ||||
HeaderParseError = 1003, | HeaderParseError = 1003, | ||||
@@ -10,6 +10,7 @@ namespace JT808.Protocol | |||||
{ | { | ||||
public interface IJT808Config | public interface IJT808Config | ||||
{ | { | ||||
[Obsolete("目前没用")] | |||||
JT808Version Version { get;} | JT808Version Version { get;} | ||||
string ConfigId { get; } | string ConfigId { get; } | ||||
/// <summary> | /// <summary> | ||||
@@ -14,7 +14,7 @@ | |||||
<licenseUrl>https://github.com/SmallChi/JT808/blob/master/LICENSE</licenseUrl> | <licenseUrl>https://github.com/SmallChi/JT808/blob/master/LICENSE</licenseUrl> | ||||
<license>https://github.com/SmallChi/JT808/blob/master/LICENSE</license> | <license>https://github.com/SmallChi/JT808/blob/master/LICENSE</license> | ||||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | <GeneratePackageOnBuild>false</GeneratePackageOnBuild> | ||||
<Version>2.2.0-preview1</Version> | |||||
<Version>2.2.0-preview3</Version> | |||||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | <PackageLicenseFile>LICENSE</PackageLicenseFile> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | ||||
@@ -65,6 +65,10 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7"> | |||||
<PrivateAssets>all</PrivateAssets> | |||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | |||||
</PackageReference> | |||||
<PackageReference Include="Microsoft.CSharp" Version="4.6.0" /> | <PackageReference Include="Microsoft.CSharp" Version="4.6.0" /> | ||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" /> | <PackageReference Include="System.Text.Encoding.CodePages" Version="4.6.0" /> | ||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" /> | <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" /> | ||||
@@ -213,12 +213,6 @@ | |||||
校验和不相等 | 校验和不相等 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="F:JT808.Protocol.Enums.JT808ErrorCode.GetFormatterAttributeError"> | |||||
<summary> | |||||
没有标记 | |||||
<see cref="T:JT808.Protocol.Attributes.JT808FormatterAttribute"/> | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT808.Protocol.Enums.JT808ErrorCode.HeaderParseError"> | <member name="F:JT808.Protocol.Enums.JT808ErrorCode.HeaderParseError"> | ||||
<summary> | <summary> | ||||
消息头解析错误 | 消息头解析错误 | ||||
@@ -2197,10 +2191,21 @@ | |||||
<see cref="T:JT808.Protocol.Enums.JT808MsgId"/> | <see cref="T:JT808.Protocol.Enums.JT808MsgId"/> | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Header.MessageBodyProperty"> | |||||
<summary> | |||||
消息体属性 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808Header.ProtocolVersion"> | |||||
<summary> | |||||
协议版本号(2019版本) | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808Header.TerminalPhoneNo"> | <member name="P:JT808.Protocol.JT808Header.TerminalPhoneNo"> | ||||
<summary> | <summary> | ||||
终端手机号 | 终端手机号 | ||||
根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 | 根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 | ||||
(2019版本)手机号不足 20 位,则在前补充数字 0 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Header.MsgNum"> | <member name="P:JT808.Protocol.JT808Header.MsgNum"> | ||||
@@ -2221,6 +2226,11 @@ | |||||
报序号 从1开始 | 报序号 从1开始 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808HeaderMessageBodyProperty.VersionFlag"> | |||||
<summary> | |||||
版本标识(默认为1=true) | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808HeaderMessageBodyProperty.IsPackage"> | <member name="P:JT808.Protocol.JT808HeaderMessageBodyProperty.IsPackage"> | ||||
<summary> | <summary> | ||||
是否分包 | 是否分包 | ||||
@@ -2292,9 +2302,14 @@ | |||||
起始符 | 起始符 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Package.End"> | |||||
<member name="P:JT808.Protocol.JT808Package.Header"> | |||||
<summary> | <summary> | ||||
终止符 | |||||
头数据 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808Package.Bodies"> | |||||
<summary> | |||||
数据体 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Package.CheckCode"> | <member name="P:JT808.Protocol.JT808Package.CheckCode"> | ||||
@@ -2303,17 +2318,17 @@ | |||||
从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 | 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Package.Header"> | |||||
<member name="P:JT808.Protocol.JT808Package.End"> | |||||
<summary> | <summary> | ||||
头数据 | |||||
终止符 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.JT808Package.Bodies"> | |||||
<member name="P:JT808.Protocol.JT808Package.Version"> | |||||
<summary> | <summary> | ||||
数据体 | |||||
808版本号 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:JT808.Protocol.JT808Serializer.HeaderDeserialize(System.ReadOnlySpan{System.Byte},System.Int32)"> | |||||
<member name="M:JT808.Protocol.JT808Serializer.HeaderDeserialize(System.ReadOnlySpan{System.Byte},JT808.Protocol.Enums.JT808Version,System.Int32)"> | |||||
<summary> | <summary> | ||||
用于负载或者分布式的时候,在网关只需要解到头部。 | 用于负载或者分布式的时候,在网关只需要解到头部。 | ||||
根据头部的消息Id进行分发处理,可以防止小部分性能损耗。 | 根据头部的消息Id进行分发处理,可以防止小部分性能损耗。 | ||||
@@ -2365,6 +2380,42 @@ | |||||
跳过数据体序列化 | 跳过数据体序列化 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x0004"> | |||||
<summary> | |||||
查询服务器时间请求 | |||||
2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0004.SkipSerialization"> | |||||
<summary> | |||||
跳过数据体序列化 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x0005"> | |||||
<summary> | |||||
终端补传分包请求 | |||||
2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0005.OriginalMsgNum"> | |||||
<summary> | |||||
原始消息流水号 | |||||
对应要求补传的原始消息第一包的消息流水号 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0005.AgainPackageCount"> | |||||
<summary> | |||||
重传包总数 | |||||
n | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0005.AgainPackageData"> | |||||
<summary> | |||||
重传包 ID 列表 | |||||
BYTE[2*n] | |||||
重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x0100"> | <member name="T:JT808.Protocol.MessageBody.JT808_0x0100"> | ||||
<summary> | <summary> | ||||
终端注册 | 终端注册 | ||||
@@ -2389,21 +2440,22 @@ | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0100.MakerId"> | <member name="P:JT808.Protocol.MessageBody.JT808_0x0100.MakerId"> | ||||
<summary> | <summary> | ||||
制造商 ID | 制造商 ID | ||||
5 个字节,终端制造商编码 | |||||
2013版本 5 个字节,终端制造商编码 | |||||
2019版本 11 个字节,终端制造商编码 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0100.TerminalModel"> | <member name="P:JT808.Protocol.MessageBody.JT808_0x0100.TerminalModel"> | ||||
<summary> | <summary> | ||||
终端型号 | 终端型号 | ||||
20 个字节,此终端型号由制造商自行定义,位数不 | |||||
足时,后补“0X00”。 | |||||
2013版本 20 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 | |||||
2019版本 30 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0100.TerminalId"> | <member name="P:JT808.Protocol.MessageBody.JT808_0x0100.TerminalId"> | ||||
<summary> | <summary> | ||||
终端 ID | 终端 ID | ||||
7 个字节,由大写字母和数字组成,此终端 ID 由制 | |||||
造商自行定义,位数不足时,后补“0X00”。 | |||||
2013版本 7个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 | |||||
2019版本 30个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0100.PlateColor"> | <member name="P:JT808.Protocol.MessageBody.JT808_0x0100.PlateColor"> | ||||
@@ -2428,6 +2480,22 @@ | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0102.Code"> | <member name="P:JT808.Protocol.MessageBody.JT808_0x0102.Code"> | ||||
<summary> | <summary> | ||||
鉴权码 | 鉴权码 | ||||
鉴权码内容 2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0102.CodeLength"> | |||||
<summary> | |||||
鉴权码长度 2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0102.IMEI"> | |||||
<summary> | |||||
终端IMEI 长度15 2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0102.SoftwareVersion"> | |||||
<summary> | |||||
软件版本号 长度20 后补 "0x00" 2019版本 | |||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x0104"> | <member name="T:JT808.Protocol.MessageBody.JT808_0x0104"> | ||||
@@ -3216,6 +3284,12 @@ | |||||
重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 | 重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x8004"> | |||||
<summary> | |||||
查询服务器时间应答 | |||||
2019版本 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.JT808_0x8100"> | <member name="T:JT808.Protocol.MessageBody.JT808_0x8100"> | ||||
<summary> | <summary> | ||||
终端注册应答 | 终端注册应答 | ||||
@@ -5420,7 +5494,7 @@ | |||||
主要用来一次性读取所有数据体内容操作 | 主要用来一次性读取所有数据体内容操作 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.#ctor(System.ReadOnlySpan{System.Byte})"> | |||||
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.#ctor(System.ReadOnlySpan{System.Byte},JT808.Protocol.Enums.JT808Version)"> | |||||
<summary> | <summary> | ||||
解码(转义还原),计算校验和 | 解码(转义还原),计算校验和 | ||||
</summary> | </summary> | ||||
@@ -13,10 +13,18 @@ namespace JT808.Protocol | |||||
/// <see cref="JT808.Protocol.Enums.JT808MsgId"/> | /// <see cref="JT808.Protocol.Enums.JT808MsgId"/> | ||||
/// </summary> | /// </summary> | ||||
public ushort MsgId { get; set; } | public ushort MsgId { get; set; } | ||||
/// <summary> | |||||
/// 消息体属性 | |||||
/// </summary> | |||||
public JT808HeaderMessageBodyProperty MessageBodyProperty { get; set; } | public JT808HeaderMessageBodyProperty MessageBodyProperty { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 协议版本号(2019版本) | |||||
/// </summary> | |||||
public byte ProtocolVersion { get; set; } = 1; | |||||
/// <summary> | |||||
/// 终端手机号 | /// 终端手机号 | ||||
/// 根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 | /// 根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 | ||||
/// (2019版本)手机号不足 20 位,则在前补充数字 0 | |||||
/// </summary> | /// </summary> | ||||
public string TerminalPhoneNo { get; set; } | public string TerminalPhoneNo { get; set; } | ||||
/// <summary> | /// <summary> | ||||
@@ -42,8 +50,20 @@ namespace JT808.Protocol | |||||
jT808Header.MsgId = reader.ReadUInt16(); | jT808Header.MsgId = reader.ReadUInt16(); | ||||
// 2.消息体属性 | // 2.消息体属性 | ||||
jT808Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(reader.ReadUInt16()); | jT808Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(reader.ReadUInt16()); | ||||
// 3.终端手机号 | |||||
jT808Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
if (jT808Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
// 2019 版本 | |||||
// 3.协议版本号 | |||||
jT808Header.ProtocolVersion = reader.ReadByte(); | |||||
// 4.终端手机号 | |||||
jT808Header.TerminalPhoneNo = reader.ReadBCD(20, config.Trim); | |||||
} | |||||
else | |||||
{ | |||||
// 2013 版本 | |||||
// 3.终端手机号 | |||||
jT808Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
} | |||||
jT808Header.MsgNum = reader.ReadUInt16(); | jT808Header.MsgNum = reader.ReadUInt16(); | ||||
// 4.判断有无分包 | // 4.判断有无分包 | ||||
if (jT808Header.MessageBodyProperty.IsPackage) | if (jT808Header.MessageBodyProperty.IsPackage) | ||||
@@ -62,8 +82,20 @@ namespace JT808.Protocol | |||||
writer.WriteUInt16(value.MsgId); | writer.WriteUInt16(value.MsgId); | ||||
// 2.消息体属性 | // 2.消息体属性 | ||||
writer.WriteUInt16(value.MessageBodyProperty.Wrap()); | writer.WriteUInt16(value.MessageBodyProperty.Wrap()); | ||||
// 3.终端手机号 | |||||
writer.WriteBCD(value.TerminalPhoneNo, config.TerminalPhoneNoLength); | |||||
if (value.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
// 2019 版本 | |||||
// 3.协议版本号 | |||||
writer.WriteByte(value.ProtocolVersion); | |||||
// 4.终端手机号 | |||||
writer.WriteBCD(value.TerminalPhoneNo, 20); | |||||
} | |||||
else | |||||
{ | |||||
// 2013 版本 | |||||
// 3.终端手机号 | |||||
writer.WriteBCD(value.TerminalPhoneNo, config.TerminalPhoneNoLength); | |||||
} | |||||
// 4.消息流水号 | // 4.消息流水号 | ||||
writer.WriteUInt16(value.MsgNum); | writer.WriteUInt16(value.MsgNum); | ||||
// 5.判断是否分包 | // 5.判断是否分包 | ||||
@@ -7,15 +7,34 @@ namespace JT808.Protocol | |||||
{ | { | ||||
public struct JT808HeaderMessageBodyProperty | public struct JT808HeaderMessageBodyProperty | ||||
{ | { | ||||
public JT808HeaderMessageBodyProperty(int dataLength,bool isPackage, JT808EncryptMethod jT808EncryptMethod= JT808EncryptMethod.None) | |||||
public JT808HeaderMessageBodyProperty(int dataLength,bool isPackage, bool versionFlag= false, JT808EncryptMethod jT808EncryptMethod= JT808EncryptMethod.None) | |||||
{ | { | ||||
IsPackage = isPackage; | IsPackage = isPackage; | ||||
Encrypt = jT808EncryptMethod; | Encrypt = jT808EncryptMethod; | ||||
DataLength = dataLength; | DataLength = dataLength; | ||||
VersionFlag = versionFlag; | |||||
} | } | ||||
public JT808HeaderMessageBodyProperty(bool isPackage, bool versionFlag, JT808EncryptMethod jT808EncryptMethod = JT808EncryptMethod.None) | |||||
{ | |||||
IsPackage = isPackage; | |||||
Encrypt = jT808EncryptMethod; | |||||
DataLength = 0; | |||||
VersionFlag = versionFlag; | |||||
} | |||||
public JT808HeaderMessageBodyProperty(bool versionFlag, JT808EncryptMethod jT808EncryptMethod = JT808EncryptMethod.None) | |||||
{ | |||||
IsPackage = false; | |||||
Encrypt = jT808EncryptMethod; | |||||
DataLength = 0; | |||||
VersionFlag = versionFlag; | |||||
} | |||||
public JT808HeaderMessageBodyProperty(ushort value) | public JT808HeaderMessageBodyProperty(ushort value) | ||||
{ | { | ||||
IsPackage = (value >> 13) == 1; | |||||
VersionFlag = (value >> 14 & 0x01) == 1; | |||||
IsPackage = ((value >> 13) & 0x001) == 1; | |||||
switch ((value & 0x400) >> 10) | switch ((value & 0x400) >> 10) | ||||
{ | { | ||||
case 0: | case 0: | ||||
@@ -31,6 +50,10 @@ namespace JT808.Protocol | |||||
DataLength = value & 0x3FF; | DataLength = value & 0x3FF; | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
/// 版本标识(默认为1=true) | |||||
/// </summary> | |||||
public bool VersionFlag { get; set; } | |||||
/// <summary> | |||||
/// 是否分包 | /// 是否分包 | ||||
/// true-1 表示消息体为长消息,进行分包发送处理 | /// true-1 表示消息体为长消息,进行分包发送处理 | ||||
/// false-0 消息头中无消息包封装项字段。 | /// false-0 消息头中无消息包封装项字段。 | ||||
@@ -49,6 +72,7 @@ namespace JT808.Protocol | |||||
public int DataLength { get; set; } | public int DataLength { get; set; } | ||||
public ushort Wrap() | public ushort Wrap() | ||||
{ | { | ||||
// 1.是否分包 | // 1.是否分包 | ||||
int tmpIsPacke = 0; | int tmpIsPacke = 0; | ||||
if (IsPackage) | if (IsPackage) | ||||
@@ -75,8 +99,53 @@ namespace JT808.Protocol | |||||
{ | { | ||||
// 判断有无数据体长度 | // 判断有无数据体长度 | ||||
DataLength = 0; | DataLength = 0; | ||||
} | |||||
return (ushort)(tmpIsPacke | tmpEncrypt | DataLength); | |||||
} | |||||
// 3.是否分包 | |||||
int versionFlag = 0; | |||||
if (VersionFlag) | |||||
{ | |||||
versionFlag = 1 << 14; | |||||
} | |||||
return (ushort)(versionFlag|tmpIsPacke | tmpEncrypt | DataLength); | |||||
} | |||||
public ushort Wrap(int dataLength) | |||||
{ | |||||
// 1.是否分包 | |||||
int tmpIsPacke = 0; | |||||
if (IsPackage) | |||||
{ | |||||
tmpIsPacke = 1 << 13; | |||||
} | |||||
// 2.是否加密 | |||||
int tmpEncrypt; | |||||
// 2.3.数据加密方式 | |||||
switch (Encrypt) | |||||
{ | |||||
case JT808EncryptMethod.None: | |||||
tmpEncrypt = 0; | |||||
break; | |||||
case JT808EncryptMethod.RSA: | |||||
tmpEncrypt = 1 << 10; | |||||
break; | |||||
default: | |||||
tmpEncrypt = 0; | |||||
break; | |||||
} | |||||
// 2.4.数据长度 | |||||
DataLength = dataLength; | |||||
if (dataLength <= 0) | |||||
{ | |||||
// 判断有无数据体长度 | |||||
dataLength = 0; | |||||
} | |||||
// 3.是否分包 | |||||
int versionFlag = 0; | |||||
if (VersionFlag) | |||||
{ | |||||
versionFlag = 1 << 14; | |||||
} | |||||
return (ushort)(versionFlag | tmpIsPacke | tmpEncrypt | dataLength); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -34,6 +34,34 @@ namespace JT808.Protocol | |||||
/// </summary> | /// </summary> | ||||
public byte End { get; set; } | public byte End { get; set; } | ||||
public JT808Version Version | |||||
{ | |||||
get { | |||||
if (Header != null) | |||||
{ | |||||
try | |||||
{ | |||||
if (Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
return JT808Version.JTT2019; | |||||
} | |||||
else | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
catch | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
} | |||||
public JT808HeaderPackage Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | public JT808HeaderPackage Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | ||||
{ | { | ||||
// 1. 验证校验和 | // 1. 验证校验和 | ||||
@@ -56,8 +84,21 @@ namespace JT808.Protocol | |||||
ushort messageBodyPropertyValue = reader.ReadUInt16(); | ushort messageBodyPropertyValue = reader.ReadUInt16(); | ||||
// 3.2.1.解包消息体属性 | // 3.2.1.解包消息体属性 | ||||
jT808Package.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(messageBodyPropertyValue); | jT808Package.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(messageBodyPropertyValue); | ||||
// 3.3.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
if (jT808Package.Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
//2019版本 | |||||
// 3.3.读取协议版本号 | |||||
jT808Package.Header.ProtocolVersion = reader.ReadByte(); | |||||
// 3.4.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(20, config.Trim); | |||||
reader.Version = JT808Version.JTT2019; | |||||
} | |||||
else | |||||
{ | |||||
//2013版本 | |||||
// 3.3.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
} | |||||
// 3.4.读取消息流水号 | // 3.4.读取消息流水号 | ||||
jT808Package.Header.MsgNum = reader.ReadUInt16(); | jT808Package.Header.MsgNum = reader.ReadUInt16(); | ||||
// 3.5.判断有无分包 | // 3.5.判断有无分包 | ||||
@@ -25,27 +25,54 @@ namespace JT808.Protocol | |||||
/// 起始符 | /// 起始符 | ||||
/// </summary> | /// </summary> | ||||
public byte Begin { get; set; } = BeginFlag; | public byte Begin { get; set; } = BeginFlag; | ||||
/// <summary> | /// <summary> | ||||
/// 终止符 | |||||
/// 头数据 | |||||
/// </summary> | /// </summary> | ||||
public byte End { get; set; } = EndFlag; | |||||
public JT808Header Header { get; set; } | |||||
/// <summary> | |||||
/// 数据体 | |||||
/// </summary> | |||||
public JT808Bodies Bodies { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// 校验码 | /// 校验码 | ||||
/// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 | /// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 | ||||
/// </summary> | /// </summary> | ||||
public byte CheckCode { get; set; } | public byte CheckCode { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 头数据 | |||||
/// 终止符 | |||||
/// </summary> | /// </summary> | ||||
public JT808Header Header { get; set; } | |||||
public byte End { get; set; } = EndFlag; | |||||
/// <summary> | /// <summary> | ||||
/// 数据体 | |||||
/// 808版本号 | |||||
/// </summary> | /// </summary> | ||||
public JT808Bodies Bodies { get; set; } | |||||
public JT808Version Version | |||||
{ | |||||
get | |||||
{ | |||||
if (Header != null) | |||||
{ | |||||
try | |||||
{ | |||||
if (Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
return JT808Version.JTT2019; | |||||
} | |||||
else | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
catch | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
return JT808Version.JTT2013; | |||||
} | |||||
} | |||||
} | |||||
public JT808Package Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | public JT808Package Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | ||||
{ | { | ||||
@@ -67,11 +94,23 @@ namespace JT808.Protocol | |||||
jT808Package.Header.MsgId = reader.ReadUInt16(); | jT808Package.Header.MsgId = reader.ReadUInt16(); | ||||
// 3.2.读取消息体属性 | // 3.2.读取消息体属性 | ||||
jT808Package.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(reader.ReadUInt16()); | jT808Package.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty(reader.ReadUInt16()); | ||||
// 3.3.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
// 3.4.读取消息流水号 | |||||
if (jT808Package.Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
//2019版本 | |||||
jT808Package.Header.ProtocolVersion = reader.ReadByte(); | |||||
// 3.4.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(20, config.Trim); | |||||
reader.Version = JT808Version.JTT2019; | |||||
} | |||||
else | |||||
{ | |||||
//2013版本 | |||||
// 3.3.读取终端手机号 | |||||
jT808Package.Header.TerminalPhoneNo = reader.ReadBCD(config.TerminalPhoneNoLength, config.Trim); | |||||
} | |||||
// 3.4.读取消息流水号 | |||||
jT808Package.Header.MsgNum = reader.ReadUInt16(); | jT808Package.Header.MsgNum = reader.ReadUInt16(); | ||||
// 3.5.判断有无分包 | |||||
// 3.5.判断有无分包 | |||||
if (jT808Package.Header.MessageBodyProperty.IsPackage) | if (jT808Package.Header.MessageBodyProperty.IsPackage) | ||||
{ | { | ||||
//3.5.1.读取消息包总数 | //3.5.1.读取消息包总数 | ||||
@@ -131,9 +170,7 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
} | } | ||||
// 5.读取校验码 | // 5.读取校验码 | ||||
jT808Package.CheckCode = reader.ReadByte(); | jT808Package.CheckCode = reader.ReadByte(); | ||||
// 6.读取终止位置 | // 6.读取终止位置 | ||||
@@ -152,8 +189,21 @@ namespace JT808.Protocol | |||||
writer.WriteUInt16(value.Header.MsgId); | writer.WriteUInt16(value.Header.MsgId); | ||||
// 2.2.消息体属性(包含消息体长度所以先跳过) | // 2.2.消息体属性(包含消息体长度所以先跳过) | ||||
writer.Skip(2, out int msgBodiesPropertyPosition); | writer.Skip(2, out int msgBodiesPropertyPosition); | ||||
// 2.3.终端手机号 (写死大陆手机号码) | |||||
writer.WriteBCD(value.Header.TerminalPhoneNo, config.TerminalPhoneNoLength); | |||||
if (value.Header.MessageBodyProperty.VersionFlag) | |||||
{ | |||||
//2019版本 | |||||
// 2.3.协议版本号 | |||||
writer.WriteByte(value.Header.ProtocolVersion); | |||||
// 2.4.终端手机号 | |||||
writer.WriteBCD(value.Header.TerminalPhoneNo, 20); | |||||
writer.Version = JT808Version.JTT2019; | |||||
} | |||||
else | |||||
{ | |||||
//2013版本 | |||||
// 2.3.终端手机号 (写死大陆手机号码) | |||||
writer.WriteBCD(value.Header.TerminalPhoneNo, config.TerminalPhoneNoLength); | |||||
} | |||||
value.Header.MsgNum = value.Header.MsgNum > 0 ? value.Header.MsgNum : config.MsgSNDistributed.Increment(); | value.Header.MsgNum = value.Header.MsgNum > 0 ? value.Header.MsgNum : config.MsgSNDistributed.Increment(); | ||||
// 2.4.消息流水号 | // 2.4.消息流水号 | ||||
writer.WriteUInt16(value.Header.MsgNum); | writer.WriteUInt16(value.Header.MsgNum); | ||||
@@ -177,9 +227,8 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
// 3.1.处理数据体长度 | // 3.1.处理数据体长度 | ||||
value.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty((ushort)(writer.GetCurrentPosition() - headerLength)); | |||||
// 2.2.回写消息体属性 | // 2.2.回写消息体属性 | ||||
writer.WriteUInt16Return(value.Header.MessageBodyProperty.Wrap(), msgBodiesPropertyPosition); | |||||
writer.WriteUInt16Return(value.Header.MessageBodyProperty.Wrap((writer.GetCurrentPosition() - headerLength)), msgBodiesPropertyPosition); | |||||
// 4.校验码 | // 4.校验码 | ||||
writer.WriteXor(); | writer.WriteXor(); | ||||
// 5.终止符 | // 5.终止符 | ||||
@@ -1,4 +1,5 @@ | |||||
using JT808.Protocol.Extensions; | |||||
using JT808.Protocol.Enums; | |||||
using JT808.Protocol.Extensions; | |||||
using JT808.Protocol.Formatters; | using JT808.Protocol.Formatters; | ||||
using JT808.Protocol.Interfaces; | using JT808.Protocol.Interfaces; | ||||
using JT808.Protocol.Internal; | using JT808.Protocol.Internal; | ||||
@@ -27,13 +28,13 @@ namespace JT808.Protocol | |||||
private readonly IJT808Config jT808Config; | private readonly IJT808Config jT808Config; | ||||
public byte[] Serialize(JT808Package jT808Package, int minBufferSize = 4096) | |||||
public byte[] Serialize(JT808Package package, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); | |||||
jT808Package.Serialize(ref jT808MessagePackWriter, jT808Package, jT808Config); | |||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); | |||||
jT808Package.Serialize(ref jT808MessagePackWriter, package, jT808Config); | |||||
return jT808MessagePackWriter.FlushAndGetEncodingArray(); | return jT808MessagePackWriter.FlushAndGetEncodingArray(); | ||||
} | } | ||||
finally | finally | ||||
@@ -42,13 +43,13 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
public ReadOnlySpan<byte> SerializeReadOnlySpan(JT808Package jT808Package, int minBufferSize = 4096) | |||||
public ReadOnlySpan<byte> SerializeReadOnlySpan(JT808Package package, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); | |||||
jT808Package.Serialize(ref jT808MessagePackWriter, jT808Package, jT808Config); | |||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); | |||||
jT808Package.Serialize(ref jT808MessagePackWriter, package, jT808Config); | |||||
return jT808MessagePackWriter.FlushAndGetEncodingReadOnlySpan(); | return jT808MessagePackWriter.FlushAndGetEncodingReadOnlySpan(); | ||||
} | } | ||||
finally | finally | ||||
@@ -57,12 +58,12 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
public JT808Package Deserialize(ReadOnlySpan<byte> bytes, int minBufferSize = 4096) | |||||
public JT808Package Deserialize(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); | |||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); | |||||
jT808MessagePackReader.Decode(buffer); | jT808MessagePackReader.Decode(buffer); | ||||
return jT808Package.Deserialize(ref jT808MessagePackReader, jT808Config); | return jT808Package.Deserialize(ref jT808MessagePackReader, jT808Config); | ||||
} | } | ||||
@@ -72,13 +73,13 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
public byte [] Serialize<T>(T obj, int minBufferSize = 4096) | |||||
public byte [] Serialize<T>(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
var formatter = jT808Config.GetMessagePackFormatter<T>(); | var formatter = jT808Config.GetMessagePackFormatter<T>(); | ||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); | |||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); | |||||
formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); | formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); | ||||
return jT808MessagePackWriter.FlushAndGetEncodingArray(); | return jT808MessagePackWriter.FlushAndGetEncodingArray(); | ||||
} | } | ||||
@@ -88,13 +89,13 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
public ReadOnlySpan<byte> SerializeReadOnlySpan<T>(T obj, int minBufferSize = 4096) | |||||
public ReadOnlySpan<byte> SerializeReadOnlySpan<T>(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
var formatter = jT808Config.GetMessagePackFormatter<T>(); | var formatter = jT808Config.GetMessagePackFormatter<T>(); | ||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); | |||||
JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); | |||||
formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); | formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); | ||||
return jT808MessagePackWriter.FlushAndGetEncodingReadOnlySpan(); | return jT808MessagePackWriter.FlushAndGetEncodingReadOnlySpan(); | ||||
} | } | ||||
@@ -104,12 +105,12 @@ namespace JT808.Protocol | |||||
} | } | ||||
} | } | ||||
public T Deserialize<T>(ReadOnlySpan<byte> bytes, int minBufferSize = 4096) | |||||
public T Deserialize<T>(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); | |||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); | |||||
if(CheckPackageType(typeof(T))) | if(CheckPackageType(typeof(T))) | ||||
jT808MessagePackReader.Decode(buffer); | jT808MessagePackReader.Decode(buffer); | ||||
var formatter = jT808Config.GetMessagePackFormatter<T>(); | var formatter = jT808Config.GetMessagePackFormatter<T>(); | ||||
@@ -132,12 +133,12 @@ namespace JT808.Protocol | |||||
/// </summary> | /// </summary> | ||||
/// <param name="bytes"></param> | /// <param name="bytes"></param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan<byte> bytes, int minBufferSize = 4096) | |||||
public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan<byte> bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); | |||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); | |||||
jT808MessagePackReader.Decode(buffer); | jT808MessagePackReader.Decode(buffer); | ||||
return jT808HeaderPackage.Deserialize(ref jT808MessagePackReader,jT808Config); | return jT808HeaderPackage.Deserialize(ref jT808MessagePackReader,jT808Config); | ||||
} | } | ||||
@@ -146,13 +147,13 @@ namespace JT808.Protocol | |||||
JT808ArrayPool.Return(buffer); | JT808ArrayPool.Return(buffer); | ||||
} | } | ||||
} | } | ||||
public dynamic Deserialize(ReadOnlySpan<byte> bytes, Type type, int minBufferSize = 4096) | |||||
public dynamic Deserialize(ReadOnlySpan<byte> bytes, Type type, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) | |||||
{ | { | ||||
byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | byte[] buffer = JT808ArrayPool.Rent(minBufferSize); | ||||
try | try | ||||
{ | { | ||||
var formatter = jT808Config.GetMessagePackFormatterByType(type); | var formatter = jT808Config.GetMessagePackFormatterByType(type); | ||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); | |||||
JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); | |||||
if (CheckPackageType(type)) | if (CheckPackageType(type)) | ||||
jT808MessagePackReader.Decode(buffer); | jT808MessagePackReader.Decode(buffer); | ||||
return JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(formatter,ref jT808MessagePackReader, jT808Config); | return JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(formatter,ref jT808MessagePackReader, jT808Config); | ||||
@@ -0,0 +1,16 @@ | |||||
namespace JT808.Protocol.MessageBody | |||||
{ | |||||
/// <summary> | |||||
/// 查询服务器时间请求 | |||||
/// 2019版本 | |||||
/// </summary> | |||||
public class JT808_0x0004 : JT808Bodies | |||||
{ | |||||
/// <summary> | |||||
/// 跳过数据体序列化 | |||||
/// </summary> | |||||
public override bool SkipSerialization { get; set; } = true; | |||||
public override ushort MsgId { get; } = 0x0004; | |||||
} | |||||
} |
@@ -0,0 +1,44 @@ | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.MessagePack; | |||||
namespace JT808.Protocol.MessageBody | |||||
{ | |||||
/// <summary> | |||||
/// 终端补传分包请求 | |||||
/// 2019版本 | |||||
/// </summary> | |||||
public class JT808_0x0005 : JT808Bodies, IJT808MessagePackFormatter<JT808_0x0005> | |||||
{ | |||||
public override ushort MsgId { get; } = 0x0005; | |||||
/// <summary> | |||||
/// 原始消息流水号 | |||||
/// 对应要求补传的原始消息第一包的消息流水号 | |||||
/// </summary> | |||||
public ushort OriginalMsgNum { get; set; } | |||||
/// <summary> | |||||
/// 重传包总数 | |||||
/// n | |||||
/// </summary> | |||||
public byte AgainPackageCount { get; set; } | |||||
/// <summary> | |||||
/// 重传包 ID 列表 | |||||
/// BYTE[2*n] | |||||
/// 重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 | |||||
/// </summary> | |||||
public byte[] AgainPackageData { get; set; } | |||||
public JT808_0x0005 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||||
{ | |||||
JT808_0x0005 value = new JT808_0x0005(); | |||||
value.OriginalMsgNum = reader.ReadUInt16(); | |||||
value.AgainPackageCount = reader.ReadByte(); | |||||
value.AgainPackageData = reader.ReadArray(value.AgainPackageCount * 2).ToArray(); | |||||
return value; | |||||
} | |||||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0005 value, IJT808Config config) | |||||
{ | |||||
writer.WriteUInt16(value.OriginalMsgNum); | |||||
writer.WriteByte((byte)(value.AgainPackageData.Length / 2)); | |||||
writer.WriteArray(value.AgainPackageData); | |||||
} | |||||
} | |||||
} |
@@ -1,4 +1,5 @@ | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.Enums; | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.MessagePack; | using JT808.Protocol.MessagePack; | ||||
namespace JT808.Protocol.MessageBody | namespace JT808.Protocol.MessageBody | ||||
@@ -27,21 +28,22 @@ namespace JT808.Protocol.MessageBody | |||||
/// <summary> | /// <summary> | ||||
/// 制造商 ID | /// 制造商 ID | ||||
/// 5 个字节,终端制造商编码 | |||||
/// 2013版本 5 个字节,终端制造商编码 | |||||
/// 2019版本 11 个字节,终端制造商编码 | |||||
/// </summary> | /// </summary> | ||||
public string MakerId { get; set; } | public string MakerId { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 终端型号 | /// 终端型号 | ||||
/// 20 个字节,此终端型号由制造商自行定义,位数不 | |||||
/// 足时,后补“0X00”。 | |||||
/// 2013版本 20 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 | |||||
/// 2019版本 30 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 | |||||
/// </summary> | /// </summary> | ||||
public string TerminalModel { get; set; } | public string TerminalModel { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 终端 ID | /// 终端 ID | ||||
/// 7 个字节,由大写字母和数字组成,此终端 ID 由制 | |||||
/// 造商自行定义,位数不足时,后补“0X00”。 | |||||
/// 2013版本 7个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 | |||||
/// 2019版本 30个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 | |||||
/// </summary> | /// </summary> | ||||
public string TerminalId { get; set; } | public string TerminalId { get; set; } | ||||
@@ -64,9 +66,18 @@ namespace JT808.Protocol.MessageBody | |||||
JT808_0x0100 jT808_0X0100 = new JT808_0x0100(); | JT808_0x0100 jT808_0X0100 = new JT808_0x0100(); | ||||
jT808_0X0100.AreaID = reader.ReadUInt16(); | jT808_0X0100.AreaID = reader.ReadUInt16(); | ||||
jT808_0X0100.CityOrCountyId = reader.ReadUInt16(); | jT808_0X0100.CityOrCountyId = reader.ReadUInt16(); | ||||
jT808_0X0100.MakerId = reader.ReadString(5); | |||||
jT808_0X0100.TerminalModel = reader.ReadString(20); | |||||
jT808_0X0100.TerminalId = reader.ReadString(7); | |||||
if(reader.Version== JT808Version.JTT2019) | |||||
{ | |||||
jT808_0X0100.MakerId = reader.ReadString(11); | |||||
jT808_0X0100.TerminalModel = reader.ReadString(30); | |||||
jT808_0X0100.TerminalId = reader.ReadString(30); | |||||
} | |||||
else | |||||
{ | |||||
jT808_0X0100.MakerId = reader.ReadString(5); | |||||
jT808_0X0100.TerminalModel = reader.ReadString(20); | |||||
jT808_0X0100.TerminalId = reader.ReadString(7); | |||||
} | |||||
jT808_0X0100.PlateColor = reader.ReadByte(); | jT808_0X0100.PlateColor = reader.ReadByte(); | ||||
jT808_0X0100.PlateNo = reader.ReadRemainStringContent(); | jT808_0X0100.PlateNo = reader.ReadRemainStringContent(); | ||||
return jT808_0X0100; | return jT808_0X0100; | ||||
@@ -76,9 +87,18 @@ namespace JT808.Protocol.MessageBody | |||||
{ | { | ||||
writer.WriteUInt16(value.AreaID); | writer.WriteUInt16(value.AreaID); | ||||
writer.WriteUInt16(value.CityOrCountyId); | writer.WriteUInt16(value.CityOrCountyId); | ||||
writer.WriteString(value.MakerId.PadRight(5, '0')); | |||||
writer.WriteString(value.TerminalModel.PadRight(20, '0')); | |||||
writer.WriteString(value.TerminalId.PadRight(7, '0')); | |||||
if (writer.Version == JT808Version.JTT2019) | |||||
{ | |||||
writer.WriteString(value.MakerId.PadLeft(11, '0')); | |||||
writer.WriteString(value.TerminalModel.PadLeft(30, '0')); | |||||
writer.WriteString(value.TerminalId.PadLeft(30, '0')); | |||||
} | |||||
else | |||||
{ | |||||
writer.WriteString(value.MakerId.PadRight(5, '0')); | |||||
writer.WriteString(value.TerminalModel.PadRight(20, '0')); | |||||
writer.WriteString(value.TerminalId.PadRight(7, '0')); | |||||
} | |||||
writer.WriteByte(value.PlateColor); | writer.WriteByte(value.PlateColor); | ||||
writer.WriteString(value.PlateNo); | writer.WriteString(value.PlateNo); | ||||
} | } | ||||
@@ -1,4 +1,5 @@ | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.Enums; | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.MessagePack; | using JT808.Protocol.MessagePack; | ||||
namespace JT808.Protocol.MessageBody | namespace JT808.Protocol.MessageBody | ||||
@@ -11,19 +12,54 @@ namespace JT808.Protocol.MessageBody | |||||
public override ushort MsgId { get; } = 0x0102; | public override ushort MsgId { get; } = 0x0102; | ||||
/// <summary> | /// <summary> | ||||
/// 鉴权码 | /// 鉴权码 | ||||
/// 鉴权码内容 2019版本 | |||||
/// </summary> | /// </summary> | ||||
public string Code { get; set; } | public string Code { get; set; } | ||||
/// <summary> | |||||
/// 鉴权码长度 2019版本 | |||||
/// </summary> | |||||
public byte CodeLength { get; set; } | |||||
/// <summary> | |||||
/// 终端IMEI 长度15 2019版本 | |||||
/// </summary> | |||||
public string IMEI { get; set; } | |||||
/// <summary> | |||||
/// 软件版本号 长度20 后补 "0x00" 2019版本 | |||||
/// </summary> | |||||
public string SoftwareVersion { get; set; } | |||||
public JT808_0x0102 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | public JT808_0x0102 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | ||||
{ | { | ||||
JT808_0x0102 jT808_0X0102 = new JT808_0x0102(); | JT808_0x0102 jT808_0X0102 = new JT808_0x0102(); | ||||
jT808_0X0102.Code = reader.ReadRemainStringContent(); | |||||
if(reader.Version== JT808Version.JTT2019) | |||||
{ | |||||
jT808_0X0102.CodeLength = reader.ReadByte(); | |||||
jT808_0X0102.Code = reader.ReadString(jT808_0X0102.CodeLength); | |||||
jT808_0X0102.IMEI = reader.ReadString(15); | |||||
jT808_0X0102.SoftwareVersion = reader.ReadString(20); | |||||
} | |||||
else | |||||
{ | |||||
jT808_0X0102.Code = reader.ReadRemainStringContent(); | |||||
} | |||||
return jT808_0X0102; | return jT808_0X0102; | ||||
} | } | ||||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0102 value, IJT808Config config) | public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0102 value, IJT808Config config) | ||||
{ | { | ||||
writer.WriteString(value.Code); | |||||
if (writer.Version == JT808Version.JTT2019) | |||||
{ | |||||
writer.Skip(1, out int CodeLengthPosition); | |||||
writer.WriteString(value.Code); | |||||
writer.WriteByteReturn((byte)(writer.GetCurrentPosition() - CodeLengthPosition - 1), CodeLengthPosition); | |||||
writer.WriteString(value.IMEI); | |||||
writer.WriteString(value.SoftwareVersion.PadRight(20,'0')); | |||||
} | |||||
else | |||||
{ | |||||
writer.WriteString(value.Code); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -0,0 +1,29 @@ | |||||
using JT808.Protocol.Formatters; | |||||
using JT808.Protocol.MessagePack; | |||||
using System; | |||||
namespace JT808.Protocol.MessageBody | |||||
{ | |||||
/// <summary> | |||||
/// 查询服务器时间应答 | |||||
/// 2019版本 | |||||
/// </summary> | |||||
public class JT808_0x8004 : JT808Bodies, IJT808MessagePackFormatter<JT808_0x8004> | |||||
{ | |||||
public override ushort MsgId { get; } = 0x8004; | |||||
public DateTime Time { get; set; } = DateTime.Now; | |||||
public JT808_0x8004 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||||
{ | |||||
JT808_0x8004 value = new JT808_0x8004(); | |||||
value.Time = reader.ReadDateTime6(); | |||||
return value; | |||||
} | |||||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0x8004 value, IJT808Config config) | |||||
{ | |||||
writer.WriteDateTime6(value.Time); | |||||
} | |||||
} | |||||
} |
@@ -1,5 +1,7 @@ | |||||
using JT808.Protocol.Buffers; | using JT808.Protocol.Buffers; | ||||
using JT808.Protocol.Enums; | |||||
using JT808.Protocol.Extensions; | using JT808.Protocol.Extensions; | ||||
using JT808.Protocol.Interfaces; | |||||
using System; | using System; | ||||
using System.Buffers; | using System.Buffers; | ||||
using System.Buffers.Binary; | using System.Buffers.Binary; | ||||
@@ -15,6 +17,7 @@ namespace JT808.Protocol.MessagePack | |||||
public ReadOnlySpan<byte> Reader { get; private set; } | public ReadOnlySpan<byte> Reader { get; private set; } | ||||
public ReadOnlySpan<byte> SrcBuffer { get; } | public ReadOnlySpan<byte> SrcBuffer { get; } | ||||
public int ReaderCount { get; private set; } | public int ReaderCount { get; private set; } | ||||
public JT808Version Version { get; set; } | |||||
private byte _calculateCheckXorCode; | private byte _calculateCheckXorCode; | ||||
private byte _realCheckXorCode; | private byte _realCheckXorCode; | ||||
private bool _checkXorCodeVali; | private bool _checkXorCodeVali; | ||||
@@ -31,7 +34,7 @@ namespace JT808.Protocol.MessagePack | |||||
/// 解码(转义还原),计算校验和 | /// 解码(转义还原),计算校验和 | ||||
/// </summary> | /// </summary> | ||||
/// <param name="buffer"></param> | /// <param name="buffer"></param> | ||||
public JT808MessagePackReader(ReadOnlySpan<byte> srcBuffer) | |||||
public JT808MessagePackReader(ReadOnlySpan<byte> srcBuffer, JT808Version version = JT808Version.JTT2013) | |||||
{ | { | ||||
SrcBuffer = srcBuffer; | SrcBuffer = srcBuffer; | ||||
ReaderCount = 0; | ReaderCount = 0; | ||||
@@ -39,6 +42,7 @@ namespace JT808.Protocol.MessagePack | |||||
_calculateCheckXorCode = 0x00; | _calculateCheckXorCode = 0x00; | ||||
_checkXorCodeVali = false; | _checkXorCodeVali = false; | ||||
_decoded = false; | _decoded = false; | ||||
Version = version; | |||||
Reader = srcBuffer; | Reader = srcBuffer; | ||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -1,4 +1,5 @@ | |||||
using JT808.Protocol.Buffers; | using JT808.Protocol.Buffers; | ||||
using JT808.Protocol.Enums; | |||||
using System; | using System; | ||||
using System.Buffers; | using System.Buffers; | ||||
using System.Buffers.Binary; | using System.Buffers.Binary; | ||||
@@ -9,9 +10,11 @@ namespace JT808.Protocol.MessagePack | |||||
public ref struct JT808MessagePackWriter | public ref struct JT808MessagePackWriter | ||||
{ | { | ||||
private JT808BufferWriter writer; | private JT808BufferWriter writer; | ||||
public JT808MessagePackWriter(Span<byte> buffer) | |||||
public JT808Version Version { get; set; } | |||||
public JT808MessagePackWriter(Span<byte> buffer, JT808Version version= JT808Version.JTT2013) | |||||
{ | { | ||||
this.writer = new JT808BufferWriter(buffer); | this.writer = new JT808BufferWriter(buffer); | ||||
Version = version; | |||||
} | } | ||||
public byte[] FlushAndGetEncodingArray() | public byte[] FlushAndGetEncodingArray() | ||||
{ | { | ||||