diff --git a/README.md b/README.md index 05bb4f0..b561727 100644 --- a/README.md +++ b/README.md @@ -23,15 +23,15 @@ ### 数据头[JT808Header] -| 消息ID | 消息体属性 | 终端手机号 | 消息流水号 | 消息总包数(依赖是否分包) | 包序号(依赖是否分包) | -| :----: | :----------------------------: | :-------------: | :--------: |:---------: | :-------:| -| MsgId | JT808HeaderMessageBodyProperty | TerminalPhoneNo | MsgNum |PackgeCount | PackageIndex | +| 消息ID | 消息体属性 | 协议版本号(2019版本)|终端手机号 | 消息流水号 | 消息总包数(依赖是否分包) | 包序号(依赖是否分包) | +| :----: | :----------------------------: | :-------------: |:-------------: | :--------: |:---------: | :-------:| +| MsgId | JT808HeaderMessageBodyProperty | ProtocolVersion|TerminalPhoneNo | MsgNum |PackgeCount | PackageIndex | #### 数据头-消息体属性[JT808HeaderMessageBodyProperty] -| 是否分包 | 加密标识 | 消息体长度 | -| :------: | :------: | :--------: | -| IsPackge | Encrypt | DataLength | +|版本标识(2019版本)| 是否分包 | 加密标识 | 消息体长度 | +|:------:| :------: | :------: | :--------: | +|VersionFlag| IsPackge | Encrypt | DataLength | #### 消息体属性[JT808Bodies] @@ -306,17 +306,17 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 ## JT808终端通讯协议消息对照表 -| 序号 | 消息ID | 完成情况 | 测试情况 | 消息体名称 | -| :---: | :-----------: | :------: | :------: | :----------------------------: | +| 序号 | 消息ID | 完成情况 | 测试情况 | 消息体名称 |2019版本| +| :---: | :-----------: | :------: | :------: | :----------------------------: |:----------------------------:| | 1 | 0x0001 | √ | √ | 终端通用应答 | | 2 | 0x8001 | √ | √ | 平台通用应答 | | 3 | 0x0002 | √ | √ | 终端心跳 | | 4 | 0x8003 | √ | √ | 补传分包请求 | -| 5 | 0x0100 | √ | √ | 终端注册 | +| 5 | 0x0100 | √ | √ | 终端注册 |修改| | 6 | 0x8100 | √ | √ | 终端注册应答 | | 7 | 0x0003 | √ | √ | 终端注销 | -| 8 | 0x0102 | √ | √ | 终端鉴权 | -| 9 | 0x8103 | √ | √ | 设置终端参数 | +| 8 | 0x0102 | √ | √ | 终端鉴权 |修改| +| 9 | 0x8103 | √ | x | 设置终端参数 |修改且增加| | 10 | 0x8104 | √ | √ | 查询终端参数 | | 11 | 0x0104 | √ | √ | 查询终端参数应答 | | 12 | 0x8105 | √ | √ | 终端控制 | @@ -350,9 +350,9 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 | 40 | 0x8605 | √ | √ | 删除多边形区域 | | 41 | 0x8606 | √ | √ | 设置路线 | | 42 | 0x8607 | √ | √ | 删除路线 | -| 43 | 0x8700 | x | 下个版本 | 行驶记录仪数据采集命令 | -| 44 | 0x0700 | x | 下个版本 | 行驶记录仪数据上传 | -| 45 | 0x8701 | x | 下个版本 | 行驶记录仪参数下传命令 | +| 43 | 0x8700 | x | 不开发 | 行驶记录仪数据采集命令 | +| 44 | 0x0700 | x | 不开发 | 行驶记录仪数据上传 | +| 45 | 0x8701 | x | 不开发 | 行驶记录仪参数下传命令 | | 46 | 0x0701 | √ | √ | 电子运单上报 | | 47 | 0x0702 | √ | √ | 驾驶员身份信息采集上报 | | 48 | 0x8702 | √ | 消息体为空| 上报驾驶员身份信息请求 | @@ -375,3 +375,6 @@ Platform=AnyCpu Server=False Toolchain=.NET Core 3.0 | 65 | 0x0A00 | √ | √ | 终端 RSA 公钥 | | 66 | 0x8F00~0x8FFF | 保留 | 保留 | 平台下行消息保留 | | 67 | 0x0F00~0x0FFF | 保留 | 保留 | 终端上行消息保留 | +| 68 | 0x0004 | √ | √ | 查询服务器时间请求 |新增| +| 69 | 0x8004 | √ | √ | 查询服务器时间应答 |新增| +| 70 | 0x0005 | √ | √ | 终端补传分包请求 |新增| diff --git a/doc/JTT.808-2019.PDF b/doc/JTT.808-2019.PDF index dd195e2..7ea6824 100644 Binary files a/doc/JTT.808-2019.PDF and b/doc/JTT.808-2019.PDF differ diff --git a/src/JT808.Protocol.Test/JT808.Protocol.Test.csproj b/src/JT808.Protocol.Test/JT808.Protocol.Test.csproj index b4166dc..bd982a9 100644 --- a/src/JT808.Protocol.Test/JT808.Protocol.Test.csproj +++ b/src/JT808.Protocol.Test/JT808.Protocol.Test.csproj @@ -56,6 +56,8 @@ + + @@ -94,6 +96,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/JT808.Protocol.Test/JT808HeaderMessageBodyPropertyTest.cs b/src/JT808.Protocol.Test/JT808HeaderMessageBodyPropertyTest.cs index c84fae4..0f6b4f4 100644 --- a/src/JT808.Protocol.Test/JT808HeaderMessageBodyPropertyTest.cs +++ b/src/JT808.Protocol.Test/JT808HeaderMessageBodyPropertyTest.cs @@ -27,5 +27,49 @@ namespace JT808.Protocol.Test Assert.True(jT808HeaderMessageBodyProperty.IsPackage); 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); + } } } diff --git a/src/JT808.Protocol.Test/JT808HeaderTest.cs b/src/JT808.Protocol.Test/JT808HeaderTest.cs index 97f11f1..7bc0cbe 100644 --- a/src/JT808.Protocol.Test/JT808HeaderTest.cs +++ b/src/JT808.Protocol.Test/JT808HeaderTest.cs @@ -8,6 +8,7 @@ namespace JT808.Protocol.Test public class JT808HeaderTest { JT808Serializer JT808Serializer = new JT808Serializer(); + [Fact] public void Test3() { @@ -34,7 +35,7 @@ namespace JT808.Protocol.Test jT808HeaderProperty.MsgId = JT808MsgId.终端鉴权.ToUInt16Value(); 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] @@ -75,5 +76,39 @@ namespace JT808.Protocol.Test Assert.Equal(JT808MsgId.终端鉴权.ToValue(), jT808Header.MsgId); 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(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); + } } } diff --git a/src/JT808.Protocol.Test/MessageBody/JT808_0x0005Test.cs b/src/JT808.Protocol.Test/MessageBody/JT808_0x0005Test.cs new file mode 100644 index 0000000..daa4ff1 --- /dev/null +++ b/src/JT808.Protocol.Test/MessageBody/JT808_0x0005Test.cs @@ -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(bytes); + Assert.Equal(1234, jT808_0X8005.OriginalMsgNum); + Assert.Equal(new byte[] { 0x01, 0x02, 0x02, 0x03 }, jT808_0X8005.AgainPackageData); + Assert.Equal(2, jT808_0X8005.AgainPackageCount); + } + } +} diff --git a/src/JT808.Protocol.Test/MessageBody/JT808_0x0100Test.cs b/src/JT808.Protocol.Test/MessageBody/JT808_0x0100Test.cs index 961e665..4f03465 100644 --- a/src/JT808.Protocol.Test/MessageBody/JT808_0x0100Test.cs +++ b/src/JT808.Protocol.Test/MessageBody/JT808_0x0100Test.cs @@ -1,6 +1,7 @@ using Xunit; using JT808.Protocol.MessageBody; using JT808.Protocol.Extensions; +using JT808.Protocol.Enums; namespace JT808.Protocol.Test.MessageBody { @@ -52,5 +53,56 @@ namespace JT808.Protocol.Test.MessageBody Assert.Equal("CHI1230", JT808Bodies.TerminalId); 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(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); + } } } diff --git a/src/JT808.Protocol.Test/MessageBody/JT808_0x0102Test.cs b/src/JT808.Protocol.Test/MessageBody/JT808_0x0102Test.cs index 1b02e62..bbf625e 100644 --- a/src/JT808.Protocol.Test/MessageBody/JT808_0x0102Test.cs +++ b/src/JT808.Protocol.Test/MessageBody/JT808_0x0102Test.cs @@ -1,6 +1,7 @@ using Xunit; using JT808.Protocol.MessageBody; using JT808.Protocol.Extensions; +using JT808.Protocol.Enums; namespace JT808.Protocol.Test.MessageBody { @@ -26,6 +27,30 @@ namespace JT808.Protocol.Test.MessageBody 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(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] public void Test3() { diff --git a/src/JT808.Protocol.Test/MessageBody/JT808_0x8004Test.cs b/src/JT808.Protocol.Test/MessageBody/JT808_0x8004Test.cs new file mode 100644 index 0000000..d244654 --- /dev/null +++ b/src/JT808.Protocol.Test/MessageBody/JT808_0x8004Test.cs @@ -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(bytes); + Assert.Equal(DateTime.Parse("2019-11-26 15:58:50"), jT808_0X8004.Time); + } + } +} diff --git a/src/JT808.Protocol.Test/MessagePack/JT808MessagePackReaderTest.cs b/src/JT808.Protocol.Test/MessagePack/JT808MessagePackReaderTest.cs index 8a745cd..be981c4 100644 --- a/src/JT808.Protocol.Test/MessagePack/JT808MessagePackReaderTest.cs +++ b/src/JT808.Protocol.Test/MessagePack/JT808MessagePackReaderTest.cs @@ -8,6 +8,7 @@ using System.Buffers; using JT808.Protocol.Formatters; using JT808.Protocol.Interfaces; using JT808.Protocol.Internal; +using JT808.Protocol.Enums; 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); + } } } diff --git a/src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs b/src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs index bd65a07..b7722e5 100644 --- a/src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs +++ b/src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text; using Xunit; using System.Buffers; +using JT808.Protocol.Enums; namespace JT808.Protocol.Test.MessagePack { @@ -457,5 +458,15 @@ namespace JT808.Protocol.Test.MessagePack 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); } + + [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); + } } } diff --git a/src/JT808.Protocol/Attributes/JT808FormatterAttribute.cs b/src/JT808.Protocol/Attributes/JT808FormatterAttribute.cs deleted file mode 100644 index 18cf8cc..0000000 --- a/src/JT808.Protocol/Attributes/JT808FormatterAttribute.cs +++ /dev/null @@ -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; - } - } -} diff --git a/src/JT808.Protocol/Enums/JT808ErrorCode.cs b/src/JT808.Protocol/Enums/JT808ErrorCode.cs index 92e9837..ca0916d 100644 --- a/src/JT808.Protocol/Enums/JT808ErrorCode.cs +++ b/src/JT808.Protocol/Enums/JT808ErrorCode.cs @@ -7,11 +7,6 @@ /// CheckCodeNotEqual = 1001, /// - /// 没有标记 - /// - /// - GetFormatterAttributeError = 1002, - /// /// 消息头解析错误 /// HeaderParseError = 1003, diff --git a/src/JT808.Protocol/Interfaces/IJT808Config.cs b/src/JT808.Protocol/Interfaces/IJT808Config.cs index f27ad7c..e80d3a4 100644 --- a/src/JT808.Protocol/Interfaces/IJT808Config.cs +++ b/src/JT808.Protocol/Interfaces/IJT808Config.cs @@ -10,6 +10,7 @@ namespace JT808.Protocol { public interface IJT808Config { + [Obsolete("目前没用")] JT808Version Version { get;} string ConfigId { get; } /// diff --git a/src/JT808.Protocol/JT808.Protocol.csproj b/src/JT808.Protocol/JT808.Protocol.csproj index 6d7b056..983c0a7 100644 --- a/src/JT808.Protocol/JT808.Protocol.csproj +++ b/src/JT808.Protocol/JT808.Protocol.csproj @@ -14,7 +14,7 @@ https://github.com/SmallChi/JT808/blob/master/LICENSE https://github.com/SmallChi/JT808/blob/master/LICENSE false - 2.2.0-preview1 + 2.2.0-preview3 LICENSE @@ -65,6 +65,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/JT808.Protocol/JT808.Protocol.xml b/src/JT808.Protocol/JT808.Protocol.xml index 00528c6..5ec4efd 100644 --- a/src/JT808.Protocol/JT808.Protocol.xml +++ b/src/JT808.Protocol/JT808.Protocol.xml @@ -213,12 +213,6 @@ 校验和不相等 - - - 没有标记 - - - 消息头解析错误 @@ -2197,10 +2191,21 @@ + + + 消息体属性 + + + + + 协议版本号(2019版本) + + 终端手机号 根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 + (2019版本)手机号不足 20 位,则在前补充数字 0 @@ -2221,6 +2226,11 @@ 报序号 从1开始 + + + 版本标识(默认为1=true) + + 是否分包 @@ -2292,9 +2302,14 @@ 起始符 - + - 终止符 + 头数据 + + + + + 数据体 @@ -2303,17 +2318,17 @@ 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 - + - 头数据 + 终止符 - + - 数据体 + 808版本号 - + 用于负载或者分布式的时候,在网关只需要解到头部。 根据头部的消息Id进行分发处理,可以防止小部分性能损耗。 @@ -2365,6 +2380,42 @@ 跳过数据体序列化 + + + 查询服务器时间请求 + 2019版本 + + + + + 跳过数据体序列化 + + + + + 终端补传分包请求 + 2019版本 + + + + + 原始消息流水号 + 对应要求补传的原始消息第一包的消息流水号 + + + + + 重传包总数 + n + + + + + 重传包 ID 列表 + BYTE[2*n] + 重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 + + 终端注册 @@ -2389,21 +2440,22 @@ 制造商 ID - 5 个字节,终端制造商编码 + 2013版本 5 个字节,终端制造商编码 + 2019版本 11 个字节,终端制造商编码 终端型号 - 20 个字节,此终端型号由制造商自行定义,位数不 - 足时,后补“0X00”。 + 2013版本 20 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 + 2019版本 30 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 终端 ID - 7 个字节,由大写字母和数字组成,此终端 ID 由制 - 造商自行定义,位数不足时,后补“0X00”。 + 2013版本 7个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 + 2019版本 30个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 @@ -2428,6 +2480,22 @@ 鉴权码 + 鉴权码内容 2019版本 + + + + + 鉴权码长度 2019版本 + + + + + 终端IMEI 长度15 2019版本 + + + + + 软件版本号 长度20 后补 "0x00" 2019版本 @@ -3216,6 +3284,12 @@ 重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 + + + 查询服务器时间应答 + 2019版本 + + 终端注册应答 @@ -5420,7 +5494,7 @@ 主要用来一次性读取所有数据体内容操作 - + 解码(转义还原),计算校验和 diff --git a/src/JT808.Protocol/JT808Header.cs b/src/JT808.Protocol/JT808Header.cs index b560c00..c5eb137 100644 --- a/src/JT808.Protocol/JT808Header.cs +++ b/src/JT808.Protocol/JT808Header.cs @@ -13,10 +13,18 @@ namespace JT808.Protocol /// /// public ushort MsgId { get; set; } + /// + /// 消息体属性 + /// public JT808HeaderMessageBodyProperty MessageBodyProperty { get; set; } /// + /// 协议版本号(2019版本) + /// + public byte ProtocolVersion { get; set; } = 1; + /// /// 终端手机号 /// 根据安装后终端自身的手机号转换。手机号不足 12 位,则在前补充数字,大陆手机号补充数字 0,港澳台则根据其区号进行位数补充 + /// (2019版本)手机号不足 20 位,则在前补充数字 0 /// public string TerminalPhoneNo { get; set; } /// @@ -42,8 +50,20 @@ namespace JT808.Protocol jT808Header.MsgId = reader.ReadUInt16(); // 2.消息体属性 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(); // 4.判断有无分包 if (jT808Header.MessageBodyProperty.IsPackage) @@ -62,8 +82,20 @@ namespace JT808.Protocol writer.WriteUInt16(value.MsgId); // 2.消息体属性 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.消息流水号 writer.WriteUInt16(value.MsgNum); // 5.判断是否分包 diff --git a/src/JT808.Protocol/JT808HeaderMessageBodyProperty.cs b/src/JT808.Protocol/JT808HeaderMessageBodyProperty.cs index e093529..c90dd55 100644 --- a/src/JT808.Protocol/JT808HeaderMessageBodyProperty.cs +++ b/src/JT808.Protocol/JT808HeaderMessageBodyProperty.cs @@ -7,15 +7,34 @@ namespace JT808.Protocol { 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; Encrypt = jT808EncryptMethod; 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) { - IsPackage = (value >> 13) == 1; + VersionFlag = (value >> 14 & 0x01) == 1; + IsPackage = ((value >> 13) & 0x001) == 1; switch ((value & 0x400) >> 10) { case 0: @@ -31,6 +50,10 @@ namespace JT808.Protocol DataLength = value & 0x3FF; } /// + /// 版本标识(默认为1=true) + /// + public bool VersionFlag { get; set; } + /// /// 是否分包 /// true-1 表示消息体为长消息,进行分包发送处理 /// false-0 消息头中无消息包封装项字段。 @@ -49,6 +72,7 @@ namespace JT808.Protocol public int DataLength { get; set; } public ushort Wrap() { + // 1.是否分包 int tmpIsPacke = 0; if (IsPackage) @@ -75,8 +99,53 @@ namespace JT808.Protocol { // 判断有无数据体长度 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); } } } diff --git a/src/JT808.Protocol/JT808HeaderPackage.cs b/src/JT808.Protocol/JT808HeaderPackage.cs index ec47319..f644e97 100644 --- a/src/JT808.Protocol/JT808HeaderPackage.cs +++ b/src/JT808.Protocol/JT808HeaderPackage.cs @@ -34,6 +34,34 @@ namespace JT808.Protocol /// 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) { // 1. 验证校验和 @@ -56,8 +84,21 @@ namespace JT808.Protocol ushort messageBodyPropertyValue = reader.ReadUInt16(); // 3.2.1.解包消息体属性 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.读取消息流水号 jT808Package.Header.MsgNum = reader.ReadUInt16(); // 3.5.判断有无分包 diff --git a/src/JT808.Protocol/JT808Package.cs b/src/JT808.Protocol/JT808Package.cs index d109a83..7c7485a 100644 --- a/src/JT808.Protocol/JT808Package.cs +++ b/src/JT808.Protocol/JT808Package.cs @@ -25,27 +25,54 @@ namespace JT808.Protocol /// 起始符 /// public byte Begin { get; set; } = BeginFlag; - /// - /// 终止符 + /// 头数据 /// - public byte End { get; set; } = EndFlag; - + public JT808Header Header { get; set; } + /// + /// 数据体 + /// + public JT808Bodies Bodies { get; set; } /// /// 校验码 /// 从消息头开始,同后一字节异或,直到校验码前一个字节,占用一个字节。 /// public byte CheckCode { get; set; } - /// - /// 头数据 + /// 终止符 /// - public JT808Header Header { get; set; } - + public byte End { get; set; } = EndFlag; /// - /// 数据体 + /// 808版本号 /// - 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) { @@ -67,11 +94,23 @@ namespace JT808.Protocol jT808Package.Header.MsgId = reader.ReadUInt16(); // 3.2.读取消息体属性 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(); - // 3.5.判断有无分包 + // 3.5.判断有无分包 if (jT808Package.Header.MessageBodyProperty.IsPackage) { //3.5.1.读取消息包总数 @@ -131,9 +170,7 @@ namespace JT808.Protocol } } } - - - + // 5.读取校验码 jT808Package.CheckCode = reader.ReadByte(); // 6.读取终止位置 @@ -152,8 +189,21 @@ namespace JT808.Protocol writer.WriteUInt16(value.Header.MsgId); // 2.2.消息体属性(包含消息体长度所以先跳过) 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(); // 2.4.消息流水号 writer.WriteUInt16(value.Header.MsgNum); @@ -177,9 +227,8 @@ namespace JT808.Protocol } } // 3.1.处理数据体长度 - value.Header.MessageBodyProperty = new JT808HeaderMessageBodyProperty((ushort)(writer.GetCurrentPosition() - headerLength)); // 2.2.回写消息体属性 - writer.WriteUInt16Return(value.Header.MessageBodyProperty.Wrap(), msgBodiesPropertyPosition); + writer.WriteUInt16Return(value.Header.MessageBodyProperty.Wrap((writer.GetCurrentPosition() - headerLength)), msgBodiesPropertyPosition); // 4.校验码 writer.WriteXor(); // 5.终止符 diff --git a/src/JT808.Protocol/JT808Serializer.cs b/src/JT808.Protocol/JT808Serializer.cs index 8a69c2b..8f606be 100644 --- a/src/JT808.Protocol/JT808Serializer.cs +++ b/src/JT808.Protocol/JT808Serializer.cs @@ -1,4 +1,5 @@ -using JT808.Protocol.Extensions; +using JT808.Protocol.Enums; +using JT808.Protocol.Extensions; using JT808.Protocol.Formatters; using JT808.Protocol.Interfaces; using JT808.Protocol.Internal; @@ -27,13 +28,13 @@ namespace JT808.Protocol 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); 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(); } finally @@ -42,13 +43,13 @@ namespace JT808.Protocol } } - public ReadOnlySpan SerializeReadOnlySpan(JT808Package jT808Package, int minBufferSize = 4096) + public ReadOnlySpan SerializeReadOnlySpan(JT808Package package, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); 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(); } finally @@ -57,12 +58,12 @@ namespace JT808.Protocol } } - public JT808Package Deserialize(ReadOnlySpan bytes, int minBufferSize = 4096) + public JT808Package Deserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { - JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); + JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); return jT808Package.Deserialize(ref jT808MessagePackReader, jT808Config); } @@ -72,13 +73,13 @@ namespace JT808.Protocol } } - public byte [] Serialize(T obj, int minBufferSize = 4096) + public byte [] Serialize(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { var formatter = jT808Config.GetMessagePackFormatter(); - JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); + JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); return jT808MessagePackWriter.FlushAndGetEncodingArray(); } @@ -88,13 +89,13 @@ namespace JT808.Protocol } } - public ReadOnlySpan SerializeReadOnlySpan(T obj, int minBufferSize = 4096) + public ReadOnlySpan SerializeReadOnlySpan(T obj, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { var formatter = jT808Config.GetMessagePackFormatter(); - JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer); + JT808MessagePackWriter jT808MessagePackWriter = new JT808MessagePackWriter(buffer, version); formatter.Serialize(ref jT808MessagePackWriter, obj, jT808Config); return jT808MessagePackWriter.FlushAndGetEncodingReadOnlySpan(); } @@ -104,12 +105,12 @@ namespace JT808.Protocol } } - public T Deserialize(ReadOnlySpan bytes, int minBufferSize = 4096) + public T Deserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { - JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); + JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if(CheckPackageType(typeof(T))) jT808MessagePackReader.Decode(buffer); var formatter = jT808Config.GetMessagePackFormatter(); @@ -132,12 +133,12 @@ namespace JT808.Protocol /// /// /// - public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan bytes, int minBufferSize = 4096) + public JT808HeaderPackage HeaderDeserialize(ReadOnlySpan bytes, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { - JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); + JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); jT808MessagePackReader.Decode(buffer); return jT808HeaderPackage.Deserialize(ref jT808MessagePackReader,jT808Config); } @@ -146,13 +147,13 @@ namespace JT808.Protocol JT808ArrayPool.Return(buffer); } } - public dynamic Deserialize(ReadOnlySpan bytes, Type type, int minBufferSize = 4096) + public dynamic Deserialize(ReadOnlySpan bytes, Type type, JT808Version version = JT808Version.JTT2013, int minBufferSize = 4096) { byte[] buffer = JT808ArrayPool.Rent(minBufferSize); try { var formatter = jT808Config.GetMessagePackFormatterByType(type); - JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes); + JT808MessagePackReader jT808MessagePackReader = new JT808MessagePackReader(bytes, version); if (CheckPackageType(type)) jT808MessagePackReader.Decode(buffer); return JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(formatter,ref jT808MessagePackReader, jT808Config); diff --git a/src/JT808.Protocol/MessageBody/JT808_0x0004.cs b/src/JT808.Protocol/MessageBody/JT808_0x0004.cs new file mode 100644 index 0000000..2bd9e48 --- /dev/null +++ b/src/JT808.Protocol/MessageBody/JT808_0x0004.cs @@ -0,0 +1,16 @@ +namespace JT808.Protocol.MessageBody +{ + /// + /// 查询服务器时间请求 + /// 2019版本 + /// + public class JT808_0x0004 : JT808Bodies + { + /// + /// 跳过数据体序列化 + /// + public override bool SkipSerialization { get; set; } = true; + + public override ushort MsgId { get; } = 0x0004; + } +} diff --git a/src/JT808.Protocol/MessageBody/JT808_0x0005.cs b/src/JT808.Protocol/MessageBody/JT808_0x0005.cs new file mode 100644 index 0000000..c5a9867 --- /dev/null +++ b/src/JT808.Protocol/MessageBody/JT808_0x0005.cs @@ -0,0 +1,44 @@ +using JT808.Protocol.Formatters; +using JT808.Protocol.MessagePack; + +namespace JT808.Protocol.MessageBody +{ + /// + /// 终端补传分包请求 + /// 2019版本 + /// + public class JT808_0x0005 : JT808Bodies, IJT808MessagePackFormatter + { + public override ushort MsgId { get; } = 0x0005; + /// + /// 原始消息流水号 + /// 对应要求补传的原始消息第一包的消息流水号 + /// + public ushort OriginalMsgNum { get; set; } + /// + /// 重传包总数 + /// n + /// + public byte AgainPackageCount { get; set; } + /// + /// 重传包 ID 列表 + /// BYTE[2*n] + /// 重传包序号顺序排列,如“包 ID1 包 ID2......包 IDn”。 + /// + 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); + } + } +} diff --git a/src/JT808.Protocol/MessageBody/JT808_0x0100.cs b/src/JT808.Protocol/MessageBody/JT808_0x0100.cs index 6e8320b..94b83d0 100644 --- a/src/JT808.Protocol/MessageBody/JT808_0x0100.cs +++ b/src/JT808.Protocol/MessageBody/JT808_0x0100.cs @@ -1,4 +1,5 @@ -using JT808.Protocol.Formatters; +using JT808.Protocol.Enums; +using JT808.Protocol.Formatters; using JT808.Protocol.MessagePack; namespace JT808.Protocol.MessageBody @@ -27,21 +28,22 @@ namespace JT808.Protocol.MessageBody /// /// 制造商 ID - /// 5 个字节,终端制造商编码 + /// 2013版本 5 个字节,终端制造商编码 + /// 2019版本 11 个字节,终端制造商编码 /// public string MakerId { get; set; } /// /// 终端型号 - /// 20 个字节,此终端型号由制造商自行定义,位数不 - /// 足时,后补“0X00”。 + /// 2013版本 20 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 + /// 2019版本 30 个字节,此终端型号由制造商自行定义,位数不足时,后补“0X00”。 /// public string TerminalModel { get; set; } /// /// 终端 ID - /// 7 个字节,由大写字母和数字组成,此终端 ID 由制 - /// 造商自行定义,位数不足时,后补“0X00”。 + /// 2013版本 7个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 + /// 2019版本 30个字节,由大写字母和数字组成,此终端 ID 由制造商自行定义,位数不足时,后补“0X00”。 /// public string TerminalId { get; set; } @@ -64,9 +66,18 @@ namespace JT808.Protocol.MessageBody JT808_0x0100 jT808_0X0100 = new JT808_0x0100(); jT808_0X0100.AreaID = 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.PlateNo = reader.ReadRemainStringContent(); return jT808_0X0100; @@ -76,9 +87,18 @@ namespace JT808.Protocol.MessageBody { writer.WriteUInt16(value.AreaID); 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.WriteString(value.PlateNo); } diff --git a/src/JT808.Protocol/MessageBody/JT808_0x0102.cs b/src/JT808.Protocol/MessageBody/JT808_0x0102.cs index 189829e..97570ce 100644 --- a/src/JT808.Protocol/MessageBody/JT808_0x0102.cs +++ b/src/JT808.Protocol/MessageBody/JT808_0x0102.cs @@ -1,4 +1,5 @@ -using JT808.Protocol.Formatters; +using JT808.Protocol.Enums; +using JT808.Protocol.Formatters; using JT808.Protocol.MessagePack; namespace JT808.Protocol.MessageBody @@ -11,19 +12,54 @@ namespace JT808.Protocol.MessageBody public override ushort MsgId { get; } = 0x0102; /// /// 鉴权码 + /// 鉴权码内容 2019版本 /// public string Code { get; set; } + /// + /// 鉴权码长度 2019版本 + /// + public byte CodeLength { get; set; } + /// + /// 终端IMEI 长度15 2019版本 + /// + public string IMEI { get; set; } + /// + /// 软件版本号 长度20 后补 "0x00" 2019版本 + /// + public string SoftwareVersion { get; set; } public JT808_0x0102 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) { 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; } 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); + } } } } diff --git a/src/JT808.Protocol/MessageBody/JT808_0x8004.cs b/src/JT808.Protocol/MessageBody/JT808_0x8004.cs new file mode 100644 index 0000000..b15fe7c --- /dev/null +++ b/src/JT808.Protocol/MessageBody/JT808_0x8004.cs @@ -0,0 +1,29 @@ +using JT808.Protocol.Formatters; +using JT808.Protocol.MessagePack; +using System; + +namespace JT808.Protocol.MessageBody +{ + /// + /// 查询服务器时间应答 + /// 2019版本 + /// + public class JT808_0x8004 : JT808Bodies, IJT808MessagePackFormatter + { + 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); + } + } +} diff --git a/src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs b/src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs index 7bfe262..f90012d 100644 --- a/src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs +++ b/src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs @@ -1,5 +1,7 @@ using JT808.Protocol.Buffers; +using JT808.Protocol.Enums; using JT808.Protocol.Extensions; +using JT808.Protocol.Interfaces; using System; using System.Buffers; using System.Buffers.Binary; @@ -15,6 +17,7 @@ namespace JT808.Protocol.MessagePack public ReadOnlySpan Reader { get; private set; } public ReadOnlySpan SrcBuffer { get; } public int ReaderCount { get; private set; } + public JT808Version Version { get; set; } private byte _calculateCheckXorCode; private byte _realCheckXorCode; private bool _checkXorCodeVali; @@ -31,7 +34,7 @@ namespace JT808.Protocol.MessagePack /// 解码(转义还原),计算校验和 /// /// - public JT808MessagePackReader(ReadOnlySpan srcBuffer) + public JT808MessagePackReader(ReadOnlySpan srcBuffer, JT808Version version = JT808Version.JTT2013) { SrcBuffer = srcBuffer; ReaderCount = 0; @@ -39,6 +42,7 @@ namespace JT808.Protocol.MessagePack _calculateCheckXorCode = 0x00; _checkXorCodeVali = false; _decoded = false; + Version = version; Reader = srcBuffer; } /// diff --git a/src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs b/src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs index d8d5558..490e7d1 100644 --- a/src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs +++ b/src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs @@ -1,4 +1,5 @@ using JT808.Protocol.Buffers; +using JT808.Protocol.Enums; using System; using System.Buffers; using System.Buffers.Binary; @@ -9,9 +10,11 @@ namespace JT808.Protocol.MessagePack public ref struct JT808MessagePackWriter { private JT808BufferWriter writer; - public JT808MessagePackWriter(Span buffer) + public JT808Version Version { get; set; } + public JT808MessagePackWriter(Span buffer, JT808Version version= JT808Version.JTT2013) { this.writer = new JT808BufferWriter(buffer); + Version = version; } public byte[] FlushAndGetEncodingArray() {