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 70c7584..0e7ccc5 100644 Binary files a/doc/808809补充协议.pdf and b/doc/808809补充协议.pdf differ 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(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 ///启动车辆定位信息交换应答 /// [Description("启动车辆定位信息交换应答")] + [JT809BodiesType(typeof(JT809_0x1200_0x1205))] UP_EXG_MSG_RETURN_STARTUP_ACK = 0x1205, /// ///结束车辆定位信息交换应答 /// [Description("结束车辆定位信息交换应答")] + [JT809BodiesType(typeof(JT809_0x1200_0x1206))] UP_EXG_MSG_RETURN_END_ACK = 0x1206, /// ///申请交换指定车辆定位信息请求 /// [Description("申请交换指定车辆定位信息请求")] + [JT809BodiesType(typeof(JT809_0x1200_0x1207))] UP_EXG_MSG_APPLY_FOR_MONITOR_STARTUP = 0x1207, /// ///取消交换指定车辆定位信息请求 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 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 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 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 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 + { + public JT809_0x1200_0x1207 Deserialize(ReadOnlySpan 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 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 +{ + /// + /// 启动车辆定位信息交换应答消息 + /// 子业务类型标识:UP_EXG_ MSG_ RETURN_ STARTUP ACK + /// 描述:本条消息是下级平台对上级平台下发的 DOWN_EXG_ MSG_ RETURN_STARTUP 消息的应答消息 + /// + 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 +{ + /// + /// 结束车辆定位信息交换应答消息 + /// 子业务类型标识:UP_EXG_MSG_RETURN_END_ACK + /// + 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 +{ + /// + /// 申请交换指定车辆定位信息请求消息 + /// 子业务类型标识:UP_EXG_MSG_APPLY-FOR_MONITOR_STARTUP + /// 描述:当下级平台需要在特定时问段内监控特殊车辆时,可上传此命令到上级平台申请对该车辆定位数据交换到下级平台,申请成功后,此车辆定位数据将在指定时间内交换到该平台(即使该车没有进入该平台所属区域也会交换) + /// + [JT809Formatter(typeof(JT809_0x1200_0x1207Formatter))] + public class JT809_0x1200_0x1207:JT809SubBodies + { + /// + /// 开始时间,用 UTC 时间表示 + /// + public DateTime StartTime { get; set; } + /// + /// 结束时间,用 UTC 时间表示 + /// + public DateTime EndTime { get; set; } + } +}