diff --git a/README.md b/README.md index c8d0cc6..50c527e 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,4 @@ |:------:|:------:|:------:|:------:| | 1 | 0x1200 | √ | 主链路动态信息交换消息 | | 2 | 0x1201 | √ | 上传车辆注册信息 | +| 3 | 0x1202 | √ | 实时上传车辆定位信息 | \ No newline at end of file diff --git a/doc/JT-T809.pdf b/doc/JT-T809.pdf index c3b2c79..5b37a4b 100644 Binary files a/doc/JT-T809.pdf and b/doc/JT-T809.pdf differ diff --git a/doc/车牌颜色字典.png b/doc/车牌颜色字典.png deleted file mode 100644 index 34e9e5e..0000000 Binary files a/doc/车牌颜色字典.png and /dev/null differ diff --git a/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1202Test.cs b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1202Test.cs new file mode 100644 index 0000000..e1e4c7e --- /dev/null +++ b/src/JT809.Protocol.Test/JT809SubMessageBody/JT809_0x1200_0x1202Test.cs @@ -0,0 +1,59 @@ +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_0x1202Test + { + [Fact] + public void Test1() + { + JT809_0x1200_0x1202 jT809_0X1200_0X1202 = new JT809_0x1200_0x1202(); + jT809_0X1200_0X1202.VehiclePosition.Day = 19; + jT809_0X1200_0X1202.VehiclePosition.Month = 7; + jT809_0X1200_0X1202.VehiclePosition.Year = 2012; + jT809_0X1200_0X1202.VehiclePosition.Hour = 15; + jT809_0X1200_0X1202.VehiclePosition.Minute = 15; + jT809_0X1200_0X1202.VehiclePosition.Second = 15; + jT809_0X1200_0X1202.VehiclePosition.Lon = 133123456; + jT809_0X1200_0X1202.VehiclePosition.Lat = 24123456; + jT809_0X1200_0X1202.VehiclePosition.Vec1 = 50; + jT809_0X1200_0X1202.VehiclePosition.Vec2 = 51; + jT809_0X1200_0X1202.VehiclePosition.Vec3 = 150; + jT809_0X1200_0X1202.VehiclePosition.Direction = 45; + jT809_0X1200_0X1202.VehiclePosition.Altitude = 45; + jT809_0X1200_0X1202.VehiclePosition.State = 3; + jT809_0X1200_0X1202.VehiclePosition.Alarm = 257; + var hex = JT809Serializer.Serialize(jT809_0X1200_0X1202).ToHexString(); + //"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" + } + + [Fact] + public void Test2() + { + var bytes = "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".ToHexBytes(); + JT809_0x1200_0x1202 jT809_0X1200_0X1202 = JT809Serializer.Deserialize(bytes); + Assert.Equal(19, jT809_0X1200_0X1202.VehiclePosition.Day); + Assert.Equal(7, jT809_0X1200_0X1202.VehiclePosition.Month); + Assert.Equal(2012, jT809_0X1200_0X1202.VehiclePosition.Year); + Assert.Equal(15, jT809_0X1200_0X1202.VehiclePosition.Hour); + Assert.Equal(15, jT809_0X1200_0X1202.VehiclePosition.Minute); + Assert.Equal(15, jT809_0X1200_0X1202.VehiclePosition.Second); + Assert.Equal((uint)133123456, jT809_0X1200_0X1202.VehiclePosition.Lon); + Assert.Equal((uint)24123456, jT809_0X1200_0X1202.VehiclePosition.Lat); + Assert.Equal(50, jT809_0X1200_0X1202.VehiclePosition.Vec1); + Assert.Equal(51, jT809_0X1200_0X1202.VehiclePosition.Vec2); + Assert.Equal((ushort)45, jT809_0X1200_0X1202.VehiclePosition.Direction); + Assert.Equal((ushort)45, jT809_0X1200_0X1202.VehiclePosition.Altitude); + Assert.Equal((uint)3, jT809_0X1200_0X1202.VehiclePosition.State); + Assert.Equal((uint)257, jT809_0X1200_0X1202.VehiclePosition.Alarm); + } + } +} diff --git a/src/JT809.Protocol/JT809.Protocol.csproj b/src/JT809.Protocol/JT809.Protocol.csproj index cf095a2..0b294fc 100644 --- a/src/JT809.Protocol/JT809.Protocol.csproj +++ b/src/JT809.Protocol/JT809.Protocol.csproj @@ -44,6 +44,7 @@ + @@ -53,8 +54,4 @@ - - - - diff --git a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs index 7075451..d2a0f3b 100644 --- a/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs +++ b/src/JT809.Protocol/JT809Enums/JT809SubBusinessType.cs @@ -20,6 +20,7 @@ namespace JT809.Protocol.JT809Enums ///实时上传车辆定位信息 /// [Description("实时上传车辆定位信息")] + [JT809BodiesType(typeof(JT809_0x1200_0x1202))] UP_EXG_MSG_REAL_LOCATION = 0x1202, /// ///车辆定位信息自动补报 diff --git a/src/JT809.Protocol/JT809Enums/JT809_VehiclePositionExcrypt.cs b/src/JT809.Protocol/JT809Enums/JT809_VehiclePositionExcrypt.cs new file mode 100644 index 0000000..8f2408e --- /dev/null +++ b/src/JT809.Protocol/JT809Enums/JT809_VehiclePositionExcrypt.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Enums +{ + /// + /// 定位信息是否使用国家测绘局批准的地图保密插件进行加密。 + /// + public enum JT809_VehiclePositionExcrypt:byte + { + 未加密 = 0x00, + 已加密 = 0x01 + } +} diff --git a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs index 7a9461c..d6a4cc6 100644 --- a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs +++ b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs @@ -49,6 +49,14 @@ namespace JT809.Protocol.JT809Extensions return result * (int)Math.Pow(100, dig - 1); } + public static int ReadBCD32(ReadOnlySpan read, ref int offset, int len) + { + int result = Convert.ToInt32(read[offset].ToString("X")); + offset += len; + return result * (int)Math.Pow(100, len - 1); + } + + public static long ReadBCD64(this byte data, byte dig) { long result = Convert.ToInt64(data.ToString("X")); @@ -311,16 +319,6 @@ namespace JT809.Protocol.JT809Extensions return codeBytes.Length; } - public static int WriteBCDLittle(ref byte[] write, int offset, string data, int digit, int len) - { - ReadOnlySpan bcd = data.PadLeft(len, '0').AsSpan(); - for (int i = 0; i < digit; i++) - { - write[offset + i] = Convert.ToByte(bcd.Slice(i * 2, 2).ToString(), 16); - } - return digit; - } - public static int WriteBCDLittle(IMemoryOwner memoryOwner, int offset, string data, int digit, int len) { ReadOnlySpan bcd = data.PadLeft(len, '0').AsSpan(); diff --git a/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1202Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1202Formatter.cs new file mode 100644 index 0000000..b9db23b --- /dev/null +++ b/src/JT809.Protocol/JT809Formatters/JT809SubMessageBodyFormatters/JT809_0x1200_0x1202Formatter.cs @@ -0,0 +1,58 @@ +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809SubMessageBody; +using JT809.Protocol.JT809Enums; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters +{ + public class JT809_0x1200_0x1202Formatter : IJT809Formatter + { + public JT809_0x1200_0x1202 Deserialize(ReadOnlySpan bytes, out int readSize) + { + int offset = 0; + JT809_0x1200_0x1202 jT809_0X1200_0X1202 = new JT809_0x1200_0x1202(); + jT809_0X1200_0X1202.VehiclePosition.Encrypt = (JT809_VehiclePositionExcrypt)JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Day= JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Month = JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Year = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Hour = JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Minute = JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Second = JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Lon = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Lat = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Vec1 = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Vec2 = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Vec3 = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Direction = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Altitude = JT809BinaryExtensions.ReadUInt16Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.State = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + jT809_0X1200_0X1202.VehiclePosition.Alarm = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + readSize = offset; + return jT809_0X1200_0X1202; + } + + public int Serialize(IMemoryOwner memoryOwner, int offset, JT809_0x1200_0x1202 value) + { + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset,(byte) value.VehiclePosition.Encrypt); + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.VehiclePosition.Day); + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.VehiclePosition.Month); + offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.VehiclePosition.Year); + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.VehiclePosition.Hour); + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.VehiclePosition.Minute); + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, value.VehiclePosition.Second); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VehiclePosition.Lon); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VehiclePosition.Lat); + offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.VehiclePosition.Vec1); + offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.VehiclePosition.Vec2); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VehiclePosition.Vec3); + offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.VehiclePosition.Direction); + offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.VehiclePosition.Altitude); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VehiclePosition.State); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VehiclePosition.Alarm); + return offset; + } + } +} diff --git a/src/JT809.Protocol/JT809Properties/JT809VehiclePositionProperties.cs b/src/JT809.Protocol/JT809Properties/JT809VehiclePositionProperties.cs new file mode 100644 index 0000000..aad81ef --- /dev/null +++ b/src/JT809.Protocol/JT809Properties/JT809VehiclePositionProperties.cs @@ -0,0 +1,78 @@ +using JT809.Protocol.JT809Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Properties +{ + /// + /// 车辆定位 + /// + public class JT809VehiclePositionProperties + { + /// + /// 该字段标识传输的定位信息是否使用国家测绘局批准的地图保密插件进行加密。 + /// + public JT809_VehiclePositionExcrypt Encrypt { get; set; } + /// + /// 日 + /// + public byte Day { get; set; } + /// + /// 月 + /// + public byte Month { get; set; } + /// + /// 年 + /// + public ushort Year { get; set; } + /// + /// 时 + /// + public byte Hour { get; set; } + /// + /// 分 + /// + public byte Minute { get; set; } + /// + /// 秒 + /// + public byte Second { get; set; } + /// + /// 经度,单位为 1*10^-6 度。 + /// + public uint Lon { get; set; } + /// + /// 纬度,单位为 1*10^-6 度。 + /// + public uint Lat { get; set; } + /// + /// 速度,指卫星定位车载终端设备上传的行车速度信息,为必填项。单位为千米每小时(km/h)。 + /// + public ushort Vec1 { get; set; } + /// + /// 行驶记录速度,指车辆行驶记录设备上传的行车速度 信息,为必填项。单位为千米每小时(km/h)。 + /// + public ushort Vec2 { get; set; } + /// + /// 车辆当前总里程数,值车辆上传的行车里程数。单位单位为千米(km) + /// + public uint Vec3 { get; set; } + /// + /// 方向,0-359,单位为度(。),正北为 0,顺时针。 + /// + public ushort Direction { get; set; } + /// + /// 海拔高度,单位为米(m)。 + /// + public ushort Altitude { get; set; } + /// + /// 车辆状态,二进制表示,B31B30B29。。。。。。B2B1B0.具体定义按照 JT/T808-2011 中表 17 的规定 + /// + public uint State { get; set; } + /// + /// 报警状态,二进制表示,0 标识正常,1 表示报警: B31B30B29 。。。。。。 B2B1B0.具 体 定 义 按 照JT/T808-2011 中表 18 的规定 + /// + public uint Alarm { get; set; } + } +} diff --git a/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1202.cs b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1202.cs new file mode 100644 index 0000000..878613d --- /dev/null +++ b/src/JT809.Protocol/JT809SubMessageBody/JT809_0x1200_0x1202.cs @@ -0,0 +1,26 @@ +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 +{ + /// + /// 实时上传车辆定位信息 + /// 子业务类型标识:UP_EXG_MSG_REAL_LOCATION + /// + [JT809Formatter(typeof(JT809_0x1200_0x1202Formatter))] + public class JT809_0x1200_0x1202:JT809SubBodies + { + public JT809_0x1200_0x1202() + { + VehiclePosition = new JT809VehiclePositionProperties(); + } + /// + /// 车辆定位信息 + /// + public JT809VehiclePositionProperties VehiclePosition { get; set; } + } +}