diff --git a/README.md b/README.md index e3207e0..54b66bf 100644 --- a/README.md +++ b/README.md @@ -11,3 +11,6 @@ |序号|消息体名称|消息ID|完成情况| |:------:|:------:|:------:|:------:| | 1 | 主链路登录请求消息 | 0x1001 | √ | +| 2 | 主链路登录应答消息 | 0x1002 | √ | +| 3 | 主链路注销请求消息 | 0x1003 | √ | +| 4 | 主链路注销应答消息 | 0x1004 | √ | diff --git a/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1002Test.cs b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1002Test.cs new file mode 100644 index 0000000..f98825a --- /dev/null +++ b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1002Test.cs @@ -0,0 +1,33 @@ +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; + +namespace JT809.Protocol.Test.JT809MessageBody +{ + public class JT809_0x1002Test + { + [Fact] + public void Test1() + { + JT809_0x1002 jT809_0X1002 = new JT809_0x1002(); + jT809_0X1002.Result = JT809Enums.JT809_0x1002_Result.成功; + jT809_0X1002.VerifyCode = 54456; + var hex = JT809Serializer.Serialize(jT809_0X1002).ToHexString(); + //"00 00 00 D4 B8" + } + + [Fact] + public void Test2() + { + var bytes = "00 00 00 D4 B8".ToHexBytes(); + JT809_0x1002 jT809_0X1002 = JT809Serializer.Deserialize(bytes); + Assert.Equal(JT809Enums.JT809_0x1002_Result.成功, jT809_0X1002.Result); + Assert.Equal((uint)54456, jT809_0X1002.VerifyCode); + } + } +} diff --git a/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1003Test.cs b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1003Test.cs new file mode 100644 index 0000000..c5921e9 --- /dev/null +++ b/src/JT809.Protocol.Test/JT809MessageBody/JT809_0x1003Test.cs @@ -0,0 +1,33 @@ +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; + +namespace JT809.Protocol.Test.JT809MessageBody +{ + public class JT809_0x1003Test + { + [Fact] + public void Test1() + { + JT809_0x1003 jT809_0X1003 = new JT809_0x1003(); + jT809_0X1003.UserId = 20180920; + jT809_0X1003.Password = "20180920"; + var hex = JT809Serializer.Serialize(jT809_0X1003).ToHexString(); + //"01 33 EF B8 32 30 31 38 30 39 32 30" + } + + [Fact] + public void Test2() + { + var bytes = "01 33 EF B8 32 30 31 38 30 39 32 30".ToHexBytes(); + JT809_0x1003 jT809_0X1003 = JT809Serializer.Deserialize(bytes); + Assert.Equal((uint)20180920, jT809_0X1003.UserId); + Assert.Equal("20180920", jT809_0X1003.Password); + } + } +} diff --git a/src/JT809.Protocol/JT809.Protocol.csproj b/src/JT809.Protocol/JT809.Protocol.csproj index 7b668e3..34d4f91 100644 --- a/src/JT809.Protocol/JT809.Protocol.csproj +++ b/src/JT809.Protocol/JT809.Protocol.csproj @@ -37,6 +37,7 @@ + diff --git a/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs b/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs index 40c418b..4b0874d 100644 --- a/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs +++ b/src/JT809.Protocol/JT809Enums/JT809BusinessType.cs @@ -23,16 +23,19 @@ namespace JT809.Protocol.JT809Enums ///主链路登录应答消息 /// [Description("主链路登录应答消息")] + [JT809BodiesType(typeof(JT809_0x1002))] UP_CONNECT_RSP = 0x1002, /// ///主链路注销请求消息 /// [Description("主链路注销请求消息")] + [JT809BodiesType(typeof(JT809_0x1003))] UP_DISCONNECT_REQ = 0x1003, /// ///主链路注销应答消息 /// [Description("主链路注销应答消息")] + [JT809BodiesType(typeof(JT809_0x1004))] UP_DISCONNECT_RSP = 0x1004, /// ///主链路连接保持请求消息 diff --git a/src/JT809.Protocol/JT809Enums/JT809_0x1002_Result.cs b/src/JT809.Protocol/JT809Enums/JT809_0x1002_Result.cs new file mode 100644 index 0000000..d6b8b6e --- /dev/null +++ b/src/JT809.Protocol/JT809Enums/JT809_0x1002_Result.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Enums +{ + /// + /// 验证结果 + /// + public enum JT809_0x1002_Result:byte + { + 成功=0x00, + IP地址不正确=0x01, + 接入码不正确=0x02, + 用户没用注册=0x03, + 密码错误=0x04, + 资源紧张_稍后再连接_已经占用= 0x05, + 其他 =0x06 + } +} diff --git a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs index c7f5eb2..093c6df 100644 --- a/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs +++ b/src/JT809.Protocol/JT809Extensions/JT809BinaryExtensions.cs @@ -268,6 +268,22 @@ namespace JT809.Protocol.JT809Extensions return codeBytes.Length; } + public static int WriteStringPadLeftLittle(IMemoryOwner memoryOwner, int offset, string data,int len) + { + data = data.PadLeft(len, '\0'); + byte[] codeBytes = encoding.GetBytes(data); + CopyTo(codeBytes, memoryOwner.Memory.Span, offset); + return codeBytes.Length; + } + + public static int WriteStringPadRightLittle(IMemoryOwner memoryOwner, int offset, string data, int len) + { + data = data.PadRight(len, '\0'); + byte[] codeBytes = encoding.GetBytes(data); + CopyTo(codeBytes, memoryOwner.Memory.Span, offset); + 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(); diff --git a/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs index 3663856..800c6cb 100644 --- a/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs +++ b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1001Formatter.cs @@ -24,8 +24,8 @@ namespace JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters public int Serialize(IMemoryOwner memoryOwner, int offset, JT809_0x1001 value) { offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.UserId); - offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.Password.PadRight(8,'\0')); - offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.DownLinkIP.PadRight(32, '\0')); + offset += JT809BinaryExtensions.WriteStringPadRightLittle(memoryOwner, offset, value.Password,8); + offset += JT809BinaryExtensions.WriteStringPadRightLittle(memoryOwner, offset, value.DownLinkIP,32); offset += JT809BinaryExtensions.WriteUInt16Little(memoryOwner, offset, value.DownLinkPort); return offset; } diff --git a/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1002Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1002Formatter.cs new file mode 100644 index 0000000..59a1da3 --- /dev/null +++ b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1002Formatter.cs @@ -0,0 +1,30 @@ +using JT809.Protocol.JT809Enums; +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809MessageBody; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters +{ + public class JT809_0x1002Formatter : IJT809Formatter + { + public JT809_0x1002 Deserialize(ReadOnlySpan bytes, out int readSize) + { + int offset = 0; + JT809_0x1002 jT809_0X1002 = new JT809_0x1002 (); + jT809_0X1002.Result=(JT809_0x1002_Result)JT809BinaryExtensions.ReadByteLittle(bytes, ref offset); + jT809_0X1002.VerifyCode= JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + readSize =offset; + return jT809_0X1002; + } + + public int Serialize(IMemoryOwner memoryOwner, int offset, JT809_0x1002 value) + { + offset += JT809BinaryExtensions.WriteByteLittle(memoryOwner, offset, (byte)value.Result); + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.VerifyCode); + return offset; + } + } +} diff --git a/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1003Formatter.cs b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1003Formatter.cs new file mode 100644 index 0000000..6443356 --- /dev/null +++ b/src/JT809.Protocol/JT809Formatters/JT809MessageBodyFormatters/JT809_0x1003Formatter.cs @@ -0,0 +1,30 @@ +using JT809.Protocol.JT809Enums; +using JT809.Protocol.JT809Extensions; +using JT809.Protocol.JT809MessageBody; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters +{ + public class JT809_0x1003Formatter : IJT809Formatter + { + public JT809_0x1003 Deserialize(ReadOnlySpan bytes, out int readSize) + { + int offset = 0; + JT809_0x1003 jT809_0X1003 = new JT809_0x1003(); + jT809_0X1003.UserId = JT809BinaryExtensions.ReadUInt32Little(bytes, ref offset); + jT809_0X1003.Password = JT809BinaryExtensions.ReadStringLittle(bytes, ref offset, 8); + readSize = offset; + return jT809_0X1003; + } + + public int Serialize(IMemoryOwner memoryOwner, int offset, JT809_0x1003 value) + { + offset += JT809BinaryExtensions.WriteUInt32Little(memoryOwner, offset, value.UserId); + offset += JT809BinaryExtensions.WriteStringPadLeftLittle(memoryOwner, offset, value.Password,8); + return offset; + } + } +} diff --git a/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs b/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs index e629d6c..69a7022 100644 --- a/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs +++ b/src/JT809.Protocol/JT809MessageBody/JT809_0x1001.cs @@ -8,6 +8,10 @@ namespace JT809.Protocol.JT809MessageBody { /// /// 主链路登录请求消息 + /// 链路类型:主链路 + /// 消息方向:下级平台往上级平台 + /// 业务数据类型标识: UP-CONNECT-REQ + /// 描述:下级平台向上级平台发送用户名和密码等登录信息 /// [JT809Formatter(typeof(JT809_0x1001Formatter))] public class JT809_0x1001: JT809Bodies diff --git a/src/JT809.Protocol/JT809MessageBody/JT809_0x1002.cs b/src/JT809.Protocol/JT809MessageBody/JT809_0x1002.cs new file mode 100644 index 0000000..9bc993c --- /dev/null +++ b/src/JT809.Protocol/JT809MessageBody/JT809_0x1002.cs @@ -0,0 +1,36 @@ +using JT809.Protocol.JT809Attributes; +using JT809.Protocol.JT809Enums; +using JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809MessageBody +{ + /// + /// 主链路登录应答消息 + /// 链路类型:主链路 + /// 消息方向:上级平台往下级平台 + /// 业务数据类型标识:UP_CONNCCT_RSP + /// 上级平台对下级平台登录请求信息、进行安全验证后,返回相应的验证结果。 + /// + [JT809Formatter(typeof(JT809_0x1002Formatter))] + public class JT809_0x1002 : JT809Bodies + { + /// + /// 验证结果,定义如下: + /// 0x00:成功; + /// 0x01:IP 地址不正确; + /// 0x02:接入码不正确; + /// 0x03:用户没用注册; + /// 0x04:密码错误; + /// 0x05:资源紧张,稍后再连接(已经占用; + /// 0x06:其他。 + /// + public JT809_0x1002_Result Result { get; set; } + /// + /// 校验码 + /// + public uint VerifyCode { get; set; } + } +} diff --git a/src/JT809.Protocol/JT809MessageBody/JT809_0x1003.cs b/src/JT809.Protocol/JT809MessageBody/JT809_0x1003.cs new file mode 100644 index 0000000..5202d49 --- /dev/null +++ b/src/JT809.Protocol/JT809MessageBody/JT809_0x1003.cs @@ -0,0 +1,28 @@ +using JT809.Protocol.JT809Attributes; +using JT809.Protocol.JT809Formatters.JT809MessageBodyFormatters; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809MessageBody +{ + /// + /// 主链路注销请求消息 + /// 链路类型:主链路 + /// 消息方向:下级平台往上级平台 + /// 业务数据类型标识:UP-DISCONNECT-REQ + /// 描述:下级平台在中断与上级平台的主链路连接时,应向上级平台发送主链路注销请求消息。 + /// + [JT809Formatter(typeof(JT809_0x1003Formatter))] + public class JT809_0x1003 : JT809Bodies + { + /// + /// 用户名 + /// + public uint UserId { get; set; } + /// + /// 密码 + /// + public string Password { get; set; } + } +} diff --git a/src/JT809.Protocol/JT809MessageBody/JT809_0x1004.cs b/src/JT809.Protocol/JT809MessageBody/JT809_0x1004.cs new file mode 100644 index 0000000..b7530ca --- /dev/null +++ b/src/JT809.Protocol/JT809MessageBody/JT809_0x1004.cs @@ -0,0 +1,20 @@ +using JT809.Protocol.JT809Attributes; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809MessageBody +{ + /// + /// 主链路注销应答消息 + /// 链路类型:主链路 + /// 消息方向:上级平台往下级平台 + /// 业务数据类型标识:UP_DISCONNECT_RSP + /// 描述:上级平台收到下级平台发送的主链路注销请求消息后,向下级平台返回主链路注销应答消息,并记录链路注销日志,下级平台接收到应答消息后,可中断主从链路联接。 + /// 主链路注销应答消息,数据体为空。 + /// + public class JT809_0x1004 : JT809Bodies + { + + } +}