From 5712c5e5dbd8f9dd3bf42b98a37f883298f9d391 Mon Sep 17 00:00:00 2001 From: SmallChi <564952747@qq.com> Date: Sun, 23 Sep 2018 16:32:08 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A00x1203=E6=B6=88=E6=81=AF?= =?UTF-8?q?=E5=8F=8A=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- .../JT809_0x1200_0x1203Test.cs | 136 ++++++++++++++++++ .../JT809Enums/JT809SubBusinessType.cs | 1 + .../JT809_0x1200_0x1203Formatter.cs | 71 +++++++++ .../JT809_0x1200_0x1203.cs | 31 ++++ 5 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1203Test.cs create mode 100644 src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1203Formatter.cs create mode 100644 src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1203.cs diff --git a/README.md b/README.md index 50c527e..b8a8355 100644 --- a/README.md +++ b/README.md @@ -45,4 +45,5 @@ |:------:|:------:|:------:|:------:| | 1 | 0x1200 | √ | 主链路动态信息交换消息 | | 2 | 0x1201 | √ | 上传车辆注册信息 | -| 3 | 0x1202 | √ | 实时上传车辆定位信息 | \ No newline at end of file +| 3 | 0x1202 | √ | 实时上传车辆定位信息 | +| 4 | 0x1203 | √ | 车辆定位信息自动补报 | \ No newline at end of file diff --git a/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1203Test.cs b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1203Test.cs new file mode 100644 index 0000000..6835727 --- /dev/null +++ b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1203Test.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using JT809.Protocol; +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809MessageBody; +using JT809.Protocol.JT809Exceptions; +using JT809.Protocol.JT809SubMessageBody; + +namespace JT809.Protocol.Test.JT809SubMessageBody +{ + public class JT809_0x1200_0x1203Test + { + [Fact] + public void Test1() + { + JT809_0x1200_0x1203 jT809_0X1200_0X1203 = new JT809_0x1200_0x1203(); + jT809_0X1200_0X1203.GNSS = new List<JT809_0x1200_0x1202>(); + + JT809_0x1200_0x1202 jT809_0X1200_0X1202_1 = new JT809_0x1200_0x1202(); + jT809_0X1200_0X1202_1.VehiclePosition.Day = 19; + jT809_0X1200_0X1202_1.VehiclePosition.Month = 7; + jT809_0X1200_0X1202_1.VehiclePosition.Year = 2012; + jT809_0X1200_0X1202_1.VehiclePosition.Hour = 15; + jT809_0X1200_0X1202_1.VehiclePosition.Minute = 15; + jT809_0X1200_0X1202_1.VehiclePosition.Second = 15; + jT809_0X1200_0X1202_1.VehiclePosition.Lon = 133123456; + jT809_0X1200_0X1202_1.VehiclePosition.Lat = 24123456; + jT809_0X1200_0X1202_1.VehiclePosition.Vec1 = 50; + jT809_0X1200_0X1202_1.VehiclePosition.Vec2 = 51; + jT809_0X1200_0X1202_1.VehiclePosition.Vec3 = 150; + jT809_0X1200_0X1202_1.VehiclePosition.Direction = 45; + jT809_0X1200_0X1202_1.VehiclePosition.Altitude = 45; + jT809_0X1200_0X1202_1.VehiclePosition.State = 3; + jT809_0X1200_0X1202_1.VehiclePosition.Alarm = 257; + + JT809_0x1200_0x1202 jT809_0X1200_0X1202_2 = new JT809_0x1200_0x1202(); + jT809_0X1200_0X1202_2.VehiclePosition.Day = 19; + jT809_0X1200_0X1202_2.VehiclePosition.Month = 7; + jT809_0X1200_0X1202_2.VehiclePosition.Year = 2012; + jT809_0X1200_0X1202_2.VehiclePosition.Hour = 16; + jT809_0X1200_0X1202_2.VehiclePosition.Minute = 16; + jT809_0X1200_0X1202_2.VehiclePosition.Second = 16; + jT809_0X1200_0X1202_2.VehiclePosition.Lon = 133123456; + jT809_0X1200_0X1202_2.VehiclePosition.Lat = 24123456; + jT809_0X1200_0X1202_2.VehiclePosition.Vec1 = 50; + jT809_0X1200_0X1202_2.VehiclePosition.Vec2 = 51; + jT809_0X1200_0X1202_2.VehiclePosition.Vec3 = 150; + jT809_0X1200_0X1202_2.VehiclePosition.Direction = 45; + jT809_0X1200_0X1202_2.VehiclePosition.Altitude = 45; + jT809_0X1200_0X1202_2.VehiclePosition.State = 3; + jT809_0X1200_0X1202_2.VehiclePosition.Alarm = 257; + + JT809_0x1200_0x1202 jT809_0X1200_0X1202_3 = new JT809_0x1200_0x1202(); + jT809_0X1200_0X1202_3.VehiclePosition.Day = 19; + jT809_0X1200_0X1202_3.VehiclePosition.Month = 7; + jT809_0X1200_0X1202_3.VehiclePosition.Year = 2012; + jT809_0X1200_0X1202_3.VehiclePosition.Hour = 17; + jT809_0X1200_0X1202_3.VehiclePosition.Minute = 17; + jT809_0X1200_0X1202_3.VehiclePosition.Second = 17; + jT809_0X1200_0X1202_3.VehiclePosition.Lon = 133123456; + jT809_0X1200_0X1202_3.VehiclePosition.Lat = 24123456; + jT809_0X1200_0X1202_3.VehiclePosition.Vec1 = 50; + jT809_0X1200_0X1202_3.VehiclePosition.Vec2 = 51; + jT809_0X1200_0X1202_3.VehiclePosition.Vec3 = 150; + jT809_0X1200_0X1202_3.VehiclePosition.Direction = 45; + jT809_0X1200_0X1202_3.VehiclePosition.Altitude = 45; + jT809_0X1200_0X1202_3.VehiclePosition.State = 3; + jT809_0X1200_0X1202_3.VehiclePosition.Alarm = 257; + + + jT809_0X1200_0X1203.GNSS.Add(jT809_0X1200_0X1202_1); + jT809_0X1200_0X1203.GNSS.Add(jT809_0X1200_0X1202_2); + jT809_0X1200_0X1203.GNSS.Add(jT809_0X1200_0X1202_3); + + var hex = JT809Serializer.Serialize(jT809_0X1200_0X1203).ToHexString(); + //"03 00 13 07 07 DC 0F 0F 0F 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01 00 13 07 07 DC 10 10 10 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01 00 13 07 07 DC 11 11 11 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01" + } + + [Fact] + public void Test2() + { + var bytes = "03 00 13 07 07 DC 0F 0F 0F 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01 00 13 07 07 DC 10 10 10 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01 00 13 07 07 DC 11 11 11 07 EF 4D 80 01 70 18 40 00 32 00 33 00 00 00 96 00 2D 00 2D 00 00 00 03 00 00 01 01".ToHexBytes(); + JT809_0x1200_0x1203 jT809_0X1200_0X1203 = JT809Serializer.Deserialize<JT809_0x1200_0x1203>(bytes); + + Assert.Equal(3, jT809_0X1200_0X1203.GNSSCount); + + + Assert.Equal(19, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Day); + Assert.Equal(7, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Month); + Assert.Equal(2012, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Year); + Assert.Equal(15, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Hour); + Assert.Equal(15, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Minute); + Assert.Equal(15, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Second); + Assert.Equal((uint)133123456, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Lon); + Assert.Equal((uint)24123456, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Lat); + Assert.Equal(50, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Vec1); + Assert.Equal(51, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Vec2); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Direction); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Altitude); + Assert.Equal((uint)3, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.State); + Assert.Equal((uint)257, jT809_0X1200_0X1203.GNSS[0].VehiclePosition.Alarm); + + Assert.Equal(19, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Day); + Assert.Equal(7, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Month); + Assert.Equal(2012, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Year); + Assert.Equal(16, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Hour); + Assert.Equal(16, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Minute); + Assert.Equal(16, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Second); + Assert.Equal((uint)133123456, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Lon); + Assert.Equal((uint)24123456, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Lat); + Assert.Equal(50, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Vec1); + Assert.Equal(51, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Vec2); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Direction); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Altitude); + Assert.Equal((uint)3, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.State); + Assert.Equal((uint)257, jT809_0X1200_0X1203.GNSS[1].VehiclePosition.Alarm); + + Assert.Equal(19, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Day); + Assert.Equal(7, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Month); + Assert.Equal(2012, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Year); + Assert.Equal(17, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Hour); + Assert.Equal(17, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Minute); + Assert.Equal(17, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Second); + Assert.Equal((uint)133123456, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Lon); + Assert.Equal((uint)24123456, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Lat); + Assert.Equal(50, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Vec1); + Assert.Equal(51, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Vec2); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Direction); + Assert.Equal((ushort)45, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Altitude); + Assert.Equal((uint)3, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.State); + Assert.Equal((uint)257, jT809_0X1200_0X1203.GNSS[2].VehiclePosition.Alarm); + } + } +} diff --git a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs index d2a0f3b..5fa67da 100644 --- a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs +++ b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs @@ -26,6 +26,7 @@ namespace JT809.Protocol.JT809Enums ///车辆定位信息自动补报 ///</summary> [Description("车辆定位信息自动补报")] + [JT809BodiesType(typeof(JT809_0x1200_0x1203))] UP_EXG_MSG_HISTORY_LOCATION = 0x1203, ///<summary> ///启动车辆定位信息交换应答 diff --git a/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1203Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1203Formatter.cs new file mode 100644 index 0000000..f0a1048 --- /dev/null +++ b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1203Formatter.cs @@ -0,0 +1,71 @@ +using JT809.Protocol.JT809Enums; +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809Properties; +using JT809.Protocol.JT809SubMessageBody; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters +{ + public class JT809_0x1200_0x1203Formatter : IJT809Formatter<JT809_0x1200_0x1203> + { + public JT809_0x1200_0x1203 Deserialize(ReadOnlySpan<byte> bytes, out int readSize) + { + int offset = 0; + JT809_0x1200_0x1203 jT809_0X1200_0X1203 = new JT809_0x1200_0x1203(); + jT809_0X1200_0X1203.GNSSCount= JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + if (jT809_0X1200_0X1203.GNSSCount > 0) + { + jT809_0X1200_0X1203.GNSS = new List<JT809_0x1200_0x1202>(); + int bufReadSize; + int tempOffset = 0; + for (int i = 0; i < jT809_0X1200_0X1203.GNSSCount; i++) + { + try + { + if (i == 0) + { + tempOffset = offset + 36; + JT809_0x1200_0x1202 jT809_0x1200_0x1202 = JT809FormatterExtensions.GetFormatter<JT809_0x1200_0x1202>() + .Deserialize(bytes.Slice(offset, 36), out bufReadSize); + jT809_0X1200_0X1203.GNSS.Add(jT809_0x1200_0x1202); + } + else + { + JT809_0x1200_0x1202 jT809_0x1200_0x1202 = JT809FormatterExtensions.GetFormatter<JT809_0x1200_0x1202>() + .Deserialize(bytes.Slice(tempOffset, 36), out bufReadSize); + tempOffset += 36; + jT809_0X1200_0X1203.GNSS.Add(jT809_0x1200_0x1202); + } + } + catch (Exception) + { + tempOffset += 36; + } + } + } + readSize = jT809_0X1200_0X1203.GNSSCount * 36 + 1; + return jT809_0X1200_0X1203; + } + + public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809_0x1200_0x1203 value) + { + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, (byte)value.GNSS.Count); + foreach(var item in value.GNSS) + { + try + { + int positionOffset = JT809FormatterExtensions.GetFormatter<JT809_0x1200_0x1202>().Serialize(memoryOwner, offset, item); + offset = positionOffset; + } + catch (Exception ex) + { + + } + } + return offset; + } + } +} diff --git a/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1203.cs b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1203.cs new file mode 100644 index 0000000..97207f9 --- /dev/null +++ b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1203.cs @@ -0,0 +1,31 @@ +using JT809.Protocol.JT809Attributes; +using JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters; +using JT809.Protocol.JT809Properties; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809SubMessageBody +{ + /// <summary> + /// 车辆定位信息自动补报请求消息 + /// <para>子业务类型标识:UP_EXG_MSG_HISTORY_LOCATION</para> + /// <para>描述:如果平台间传输链路中断,下级平台重新登录并与上级平台建立通信链路后,下级平台应将中断期间内车载终端上传的车辆定位信息自动补报到上级平台。 + /// 如果系统断线期间,该车需发送的数据包条数大于 5,则以每包五条进行补发,直到补发完毕。 + /// 多条数据以卫星定位时间先后顺序排列。 + /// 本条消息上级平台采用定量回复,即收到一定数量的数据后,即通过从链路应答数据量。 + /// </para> + /// </summary> + [JT809Formatter(typeof(JT809_0x1200_0x1203Formatter))] + public class JT809_0x1200_0x1203 : JT809SubBodies + { + /// <summary> + /// 卫星定位数据个数 1<=GNSS_CNT<=5。 + /// </summary> + public byte GNSSCount { get; set; } + /// <summary> + /// 卫星定位数据集合 + /// </summary> + public IList<JT809_0x1200_0x1202> GNSS { get; set; } + } +} From ef0d9b0bf99ab37ff38a71634b0c9fcbf40c1d07 Mon Sep 17 00:00:00 2001 From: SmallChi <564952747@qq.com> Date: Mon, 24 Sep 2018 14:12:38 +0800 Subject: [PATCH 2/2] =?UTF-8?q?1.=E5=A2=9E=E5=8A=A00x1205|0x1206|0x1207?= =?UTF-8?q?=E6=B6=88=E6=81=AF=202.=E5=A2=9E=E5=8A=A00x1207=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=203.=E5=A2=9E=E5=8A=A0UTC=E6=97=B6=E9=97=B4=E7=9A=84?= =?UTF-8?q?=E6=89=A9=E5=B1=95=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++- doc/808809补充协议.pdf | Bin 423849 -> 422932 bytes .../JT809_0x1200_0x1207Test.cs | 36 ++++++++++++++++++ .../JT809Enums/JT809SubBusinessType.cs | 3 ++ .../JT809Extensions/JT809BinaryExtensions.cs | 26 +++++++++++++ .../JT809_0x1200_0x1207Formatter.cs | 29 ++++++++++++++ .../JT809_0x1200_0x1205.cs | 16 ++++++++ .../JT809_0x1200_0x1206.cs | 14 +++++++ .../JT809_0x1200_0x1207.cs | 26 +++++++++++++ 9 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1207Test.cs create mode 100644 src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1207Formatter.cs create mode 100644 src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1205.cs create mode 100644 src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1206.cs create mode 100644 src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1207.cs diff --git a/README.md b/README.md index b8a8355..2c28799 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,7 @@ | 1 | 0x1200 | √ | 主链路动态信息交换消息 | | 2 | 0x1201 | √ | 上传车辆注册信息 | | 3 | 0x1202 | √ | 实时上传车辆定位信息 | -| 4 | 0x1203 | √ | 车辆定位信息自动补报 | \ No newline at end of file +| 4 | 0x1203 | √ | 车辆定位信息自动补报 | +| 5 | 0x1205 | √ | 启动车辆定位信息交换应答消息 | +| 6 | 0x1206 | √ | 结束车辆定位信息交换应答消息 | +| 7 | 0x1207 | √ | 申请交换指定车辆定位信息请求消息 | \ No newline at end of file diff --git a/doc/808809补充协议.pdf b/doc/808809补充协议.pdf index 70c75849e148916ff6494ffbebe2d1b6e92b9d93..0e7ccc5a52d2144640984a12907e957e7a2bda3e 100644 GIT binary patch delta 7119 zcmdU!!Ef9|6o-{IM93VGKy6WEqy{c+JTsoLJtE2>n}$TCG)f{s3PE*tC+SAnb>#Ji zY%eR+N=V!)q4vZT!G%jC_JRawB#Oj;zy*~P2#Et1#2c@(o}IPo#C0UrmuzO=yf^c{ zdB10Szy9OW=T9$PompL6x{haUW9G?szkdIvVPF%P!S<dpH)pMeL9JaC;lt@yUbHHq z@S{L}-kP5`M6)K143b)JbPj}7@gsjf*tJ&uUC}aa_;yXPmj5TdW9!(;ss!z3WMXRF ztk+tbkKYQXZan@ZoVwCg15s`22e-HPL^ZP3+uM;0ywZS(*8BBZbk`&{Mb@&Y@7@Ks z4x`pWJ!-9ruo5&5f~JtcAn1M&t{?bSVJ(WodR4p~`W<Vjz8{Ius#I1sHkMrfXi-#y znzWFAR{gNig0$Q;ugCM-jb<y3H9v2?BbvK1vO`^dd}X4u`vzpF6+zA#gIuw63yC=; zkB%<V?x?Aonhp|W-4eCBzYrX4BKX#$WY*@Kd!ETSo27IMw$zMZb1hQ_S_1^3+-l6g zS_>jS5++C1nrH>>uqxzE0C06(bfZlRPC-9~3tLu_TKImYflQfrU?{J_PCRXS&j;hf zQ_(m(3>#z4k3Ze}y^{fhr(4K_ft8XdKto14J&mq-CJmW+od(v6@Of}-ow7L2j>C1i z{pfIV`uM?bThnijo_VaOLoO1fmI@$=L!FvQcm3H+;{1<5anb`8udq0jJEvBxvqP~l zaUGy?x%c<f#B2AmuqaxTi$$rbB3NXo@~}t(Iu;_eQ*A;2Pb`?blmnKlJ?s9&OSdwx z5Ji;oun?uP3Sfytm4+oIFoLDL_I|F_!YD<6<y!B~FB9*6mW4$Trd%vaWfj44rZ%4^ zVkE22lkyt<d19f6659LfqYHn1k%dGNr933IQdLEeoT=C6BFSp@c6rVIJdxNK5h-BT zdO!So;pI*S7F!XeTr5ge6~GdQDowy*0=j_N<I(O3_Z-ywsdMq0C<}=qNV!Oqsw#q{ z)K(v7Uq?d6qt)BC<KkZX&x;T5XCR@9Amt&UN<|ew5{D|SO5*H~AQ_J~PYAKSZx1J* zzL!Nr(V|=;N<kGNQfh~%Ssk8^M~Al&^JF`DwfE1H$%Buxuqb+zhlMFcRRl|^T|OqD z7YZAXF3)U&UBL2s@4@m5KmMG7g(;epi$$rd0$AcurRi5pU<AvUba{ff+grXowV5Sg zOcAAABuZ5kK~id$XIT&QN1@m;km(=;om`ITFb1~-JLX^v!$Ra`Hq$W<dm9?-B7`ZN z!J$Efh^HG8hdZzq%?@F>;eZPd0uvX>H4oVlmtYX$p)uw;@*N|@A6{W%m^x&h3-0yF za7(9+IgTeaZp0smJzS|j$Ke!|Cb8@G(*?I92&y(2?2mDex&6sQDJ1>LsYAHEbo6Y& zD{5O?AjY0M>JRo$`so@t1Vc}E2yb=Kh(kt41H%pyyVM_}uAVK-D3`A|;{2Z+5X>1o z>uXt%4*O%NL(UvqJ2NoX<r;SaXF)z<4`o&QQ;@{`!4PB3A&kLWy5Y%$xwalyI!|~G z76^7U$?5<djKN9L{Bhi+QX1rSk_GvhYDfr&glT61#$2Rvw=u=Z+#!EVs}isyb{rS> ze-ao5ZLS5eDZ`$Y1-U?`Aptw$Y8!zunxs070S7ag+aHVbFC8jOWB^zR*L4AYdcjCr z428-@X*mtV2eu{M43J1Wu2h&2g?@csgmdyYxApox0cvKgG<O0MP9?k#T?>N9ls5#> Zjtrv}`C$~R9{7PDw~U#Y8@HE?{{Z{QARhn# delta 7940 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 diff --git a/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1207Test.cs b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1207Test.cs new file mode 100644 index 0000000..7d13e3d --- /dev/null +++ b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1207Test.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; +using JT809.Protocol; +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809MessageBody; +using JT809.Protocol.JT809Exceptions; +using JT809.Protocol.JT809SubMessageBody; + +namespace JT809.Protocol.Test.JT809SubMessageBody +{ + public class JT809_0x1200_0x1207Test + { + [Fact] + public void Test1() + { + JT809_0x1200_0x1207 jT809_0X1200_0X1201 = new JT809_0x1200_0x1207 + { + StartTime = DateTime.Parse("2018-09-24 14:14:14"), + EndTime = DateTime.Parse("2018-09-24 23:23:23") + }; + var hex = JT809Serializer.Serialize(jT809_0X1200_0X1201).ToHexString(); + //"00 00 00 00 5B A8 80 B6 00 00 00 00 5B A9 01 6B" + } + + [Fact] + public void Test2() + { + var bytes = "00 00 00 00 5B A8 80 B6 00 00 00 00 5B A9 01 6B".ToHexBytes(); + JT809_0x1200_0x1207 jT809_0X1200_0X1201 = JT809Serializer.Deserialize<JT809_0x1200_0x1207>(bytes); + Assert.Equal(DateTime.Parse("2018-09-24 14:14:14"), jT809_0X1200_0X1201.StartTime); + Assert.Equal(DateTime.Parse("2018-09-24 23:23:23"), jT809_0X1200_0X1201.EndTime); + } + } +} diff --git a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs index 5fa67da..2d67fc8 100644 --- a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs +++ b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs @@ -32,16 +32,19 @@ namespace JT809.Protocol.JT809Enums ///启动车辆定位信息交换应答 ///</summary> [Description("启动车辆定位信息交换应答")] + [JT809BodiesType(typeof(JT809_0x1200_0x1205))] UP_EXG_MSG_RETURN_STARTUP_ACK = 0x1205, ///<summary> ///结束车辆定位信息交换应答 ///</summary> [Description("结束车辆定位信息交换应答")] + [JT809BodiesType(typeof(JT809_0x1200_0x1206))] UP_EXG_MSG_RETURN_END_ACK = 0x1206, ///<summary> ///申请交换指定车辆定位信息请求 ///</summary> [Description("申请交换指定车辆定位信息请求")] + [JT809BodiesType(typeof(JT809_0x1200_0x1207))] UP_EXG_MSG_APPLY_FOR_MONITOR_STARTUP = 0x1207, ///<summary> ///取消交换指定车辆定位信息请求 diff --git a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs index d6a4cc6..a5177d3 100644 --- a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs +++ b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs @@ -18,6 +18,8 @@ namespace JT809.Protocol.JT809Extensions private static ulong[] CRC = new ulong[256]; //建立CRC16表 + private static readonly DateTime UTCBaseTime = new DateTime(1970, 1, 1); + static JT809BinaryExtensions() { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); @@ -117,6 +119,18 @@ namespace JT809.Protocol.JT809Extensions return dateTime; } + public static DateTime ReadUTCDateTimeLittle(ReadOnlySpan<byte> buf, ref int offset) + { + ulong result = 0; + for (int i = 0; i < 8; i++) + { + ulong currentData = (ulong)buf[offset+i] << (8 * (8 - i - 1)); + result += currentData; + } + offset += 8; + return UTCBaseTime.AddSeconds(result).AddHours(8); + } + public static int ReadInt32Little(ReadOnlySpan<byte> read, ref int offset) { int value = (read[offset] << 24) | (read[offset + 1] << 16) | (read[offset + 2] << 8) | read[offset + 3]; @@ -367,6 +381,18 @@ namespace JT809.Protocol.JT809Extensions return len; } + public static int WriteUTCDateTimeLittle(IMemoryOwner<byte> memoryOwner, int offset, DateTime date) + { + ulong totalSecends = (ulong)(date.AddHours(-8) - UTCBaseTime).TotalSeconds; + //高位在前 + for (int i = 7; i >= 0; i--) + { + memoryOwner.Memory.Span[offset+i] = (byte)(totalSecends & 0xFF); //取低8位 + totalSecends = totalSecends >> 8; + } + return 8; + } + public static IEnumerable<byte> ToBytes(this string data, Encoding coding) { return coding.GetBytes(data); diff --git a/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1207Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1207Formatter.cs new file mode 100644 index 0000000..2c489c0 --- /dev/null +++ b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1207Formatter.cs @@ -0,0 +1,29 @@ +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809SubMessageBody; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters +{ + public class JT809_0x1200_0x1207Formatter : IJT809Formatter<JT809_0x1200_0x1207> + { + public JT809_0x1200_0x1207 Deserialize(ReadOnlySpan<byte> bytes, out int readSize) + { + int offset = 0; + JT809_0x1200_0x1207 jT809_0X1200_0X1207 = new JT809_0x1200_0x1207(); + jT809_0X1200_0X1207.StartTime = JT809BinaryExtensions.ReadUTCDateTimeLittle(bytes, ref offset); + jT809_0X1200_0X1207.EndTime = JT809BinaryExtensions.ReadUTCDateTimeLittle(bytes, ref offset); + readSize = offset; + return jT809_0X1200_0X1207; + } + + public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809_0x1200_0x1207 value) + { + offset += JT809BinaryExtensions.WriteUTCDateTimeLittle(memoryOwner, offset, value.StartTime); + offset += JT809BinaryExtensions.WriteUTCDateTimeLittle(memoryOwner, offset, value.EndTime); + return offset; + } + } +} diff --git a/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1205.cs b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1205.cs new file mode 100644 index 0000000..a846a94 --- /dev/null +++ b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1205.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809SubMessageBody +{ + /// <summary> + /// 启动车辆定位信息交换应答消息 + /// <para>子业务类型标识:UP_EXG_ MSG_ RETURN_ STARTUP ACK</para> + /// <para>描述:本条消息是下级平台对上级平台下发的 DOWN_EXG_ MSG_ RETURN_STARTUP 消息的应答消息</para> + /// </summary> + public class JT809_0x1200_0x1205:JT809SubBodies + { + + } +} diff --git a/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1206.cs b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1206.cs new file mode 100644 index 0000000..86fa0a0 --- /dev/null +++ b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1206.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809SubMessageBody +{ + /// <summary> + /// 结束车辆定位信息交换应答消息 + /// <para>子业务类型标识:UP_EXG_MSG_RETURN_END_ACK</para> + /// </summary> + public class JT809_0x1200_0x1206:JT809SubBodies + { + } +} diff --git a/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1207.cs b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1207.cs new file mode 100644 index 0000000..f484eb0 --- /dev/null +++ b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1207.cs @@ -0,0 +1,26 @@ +using JT809.Protocol.JT809Attributes; +using JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809SubMessageBody +{ + /// <summary> + /// 申请交换指定车辆定位信息请求消息 + /// <para>子业务类型标识:UP_EXG_MSG_APPLY-FOR_MONITOR_STARTUP</para> + /// <para>描述:当下级平台需要在特定时问段内监控特殊车辆时,可上传此命令到上级平台申请对该车辆定位数据交换到下级平台,申请成功后,此车辆定位数据将在指定时间内交换到该平台(即使该车没有进入该平台所属区域也会交换)</para> + /// </summary> + [JT809Formatter(typeof(JT809_0x1200_0x1207Formatter))] + public class JT809_0x1200_0x1207:JT809SubBodies + { + /// <summary> + /// 开始时间,用 UTC 时间表示 + /// </summary> + public DateTime StartTime { get; set; } + /// <summary> + /// 结束时间,用 UTC 时间表示 + /// </summary> + public DateTime EndTime { get; set; } + } +}