@@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 | |||||
# Visual Studio 15 | # Visual Studio 15 | ||||
VisualStudioVersion = 15.0.28307.271 | VisualStudioVersion = 15.0.28307.271 | ||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol", "JTNE.Protocol\JTNE.Protocol.csproj", "{5B164F58-141D-474E-A82E-672A1C252029}" | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol", "src\JTNE.Protocol\JTNE.Protocol.csproj", "{5B164F58-141D-474E-A82E-672A1C252029}" | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol.Test", "JTNE.Protocol.Test\JTNE.Protocol.Test.csproj", "{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}" | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol.Test", "test\JTNE.Protocol.Test\JTNE.Protocol.Test.csproj", "{30BB532E-4E49-4BB4-A1D4-61DC40F320DB}" | |||||
EndProject | EndProject | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol.Benchmark", "JTNE.Protocol.Benchmark\JTNE.Protocol.Benchmark.csproj", "{CC6DFCDE-4A75-4643-9416-D459EE9CC88C}" | |||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JTNE.Protocol.Benchmark", "test\JTNE.Protocol.Benchmark\JTNE.Protocol.Benchmark.csproj", "{CC6DFCDE-4A75-4643-9416-D459EE9CC88C}" | |||||
EndProject | EndProject | ||||
Global | Global | ||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
@@ -1,14 +1,11 @@ | |||||
using System; | using System; | ||||
namespace JTNE.Protocol.Attributes | |||||
{ | |||||
[AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] | |||||
public sealed class JTNEBodiesTypeAttribute : Attribute | |||||
{ | |||||
public JTNEBodiesTypeAttribute(Type jT808BodiesType) | |||||
{ | |||||
JT808BodiesType = jT808BodiesType; | |||||
namespace JTNE.Protocol.Attributes { | |||||
[AttributeUsage (AttributeTargets.Field, Inherited = false, AllowMultiple = false)] | |||||
public sealed class JTNEBodiesTypeAttribute : Attribute { | |||||
public JTNEBodiesTypeAttribute (Type jT808BodiesType) { | |||||
BodyType = jT808BodiesType; | |||||
} | } | ||||
public Type JT808BodiesType { get;} | |||||
public Type BodyType { get; } | |||||
} | } | ||||
} | |||||
} |
@@ -8,9 +8,9 @@ using System.Text; | |||||
namespace JTNE.Protocol.Formatters | namespace JTNE.Protocol.Formatters | ||||
{ | { | ||||
public class JTNEHeaderPackageFormatter : IJTNEFormatter<JTNEHeaderPackage> | |||||
public class JTNEHeaderPackageFormatter : IJTNEFormatter<JTNEPackageHeader> | |||||
{ | { | ||||
public JTNEHeaderPackage Deserialize(ReadOnlySpan<byte> bytes, out int readSize) | |||||
public JTNEPackageHeader Deserialize(ReadOnlySpan<byte> bytes, out int readSize) | |||||
{ | { | ||||
int offset = 0; | int offset = 0; | ||||
// 1.进行固定头校验 | // 1.进行固定头校验 | ||||
@@ -25,7 +25,7 @@ namespace JTNE.Protocol.Formatters | |||||
if (bCCCode != bCCCode2) | if (bCCCode != bCCCode2) | ||||
throw new JTNEException(JTNEErrorCode.BCCCodeError, $"request:{bCCCode}!=calculate:{bCCCode2}"); | throw new JTNEException(JTNEErrorCode.BCCCodeError, $"request:{bCCCode}!=calculate:{bCCCode2}"); | ||||
} | } | ||||
JTNEHeaderPackage jTNEPackage = new JTNEHeaderPackage(); | |||||
JTNEPackageHeader jTNEPackage = new JTNEPackageHeader(); | |||||
offset += 2; | offset += 2; | ||||
// 3.命令标识 | // 3.命令标识 | ||||
jTNEPackage.MsgId = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset); | jTNEPackage.MsgId = JTNEBinaryExtensions.ReadByteLittle(bytes, ref offset); | ||||
@@ -42,7 +42,7 @@ namespace JTNE.Protocol.Formatters | |||||
// todo: 8.2.解析出对应数据体 | // todo: 8.2.解析出对应数据体 | ||||
if (jTNEPackage.DataUnitLength > 0) | if (jTNEPackage.DataUnitLength > 0) | ||||
{ | { | ||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodiesImplTypeByMsgId(jTNEPackage.MsgId); | |||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodyTypeByMsgId(jTNEPackage.MsgId); | |||||
if (jTNEBodiesImplType != null) | if (jTNEBodiesImplType != null) | ||||
{ | { | ||||
int bodyReadSize = 0; | int bodyReadSize = 0; | ||||
@@ -63,7 +63,7 @@ namespace JTNE.Protocol.Formatters | |||||
return jTNEPackage; | return jTNEPackage; | ||||
} | } | ||||
public int Serialize(ref byte[] bytes, int offset, JTNEHeaderPackage value) | |||||
public int Serialize(ref byte[] bytes, int offset, JTNEPackageHeader value) | |||||
{ | { | ||||
// 1.起始符1 | // 1.起始符1 | ||||
offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.BeginFlag1); | offset += JTNEBinaryExtensions.WriteByteLittle(bytes, offset, value.BeginFlag1); | ||||
@@ -39,7 +39,7 @@ namespace JTNE.Protocol.Formatters { | |||||
// 8.1.根据数据加密方式进行解码 | // 8.1.根据数据加密方式进行解码 | ||||
// 8.2.解析出对应数据体 | // 8.2.解析出对应数据体 | ||||
if (jTNEPackage.DataUnitLength > 0) { | if (jTNEPackage.DataUnitLength > 0) { | ||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodiesImplTypeByMsgId ((byte)jTNEPackage.MsgId); | |||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodyTypeByMsgId ((byte)jTNEPackage.MsgId); | |||||
if (jTNEBodiesImplType != null) { | if (jTNEBodiesImplType != null) { | ||||
int bodyReadSize = 0; | int bodyReadSize = 0; | ||||
try { | try { | ||||
@@ -86,7 +86,7 @@ namespace JTNE.Protocol.Formatters { | |||||
// 7.记录当前偏移量 | // 7.记录当前偏移量 | ||||
int tmpOffset = offset; | int tmpOffset = offset; | ||||
// 8.数据体 | // 8.数据体 | ||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodiesImplTypeByMsgId ((byte)value.MsgId); | |||||
Type jTNEBodiesImplType = JTNEMsgIdFactory.GetBodyTypeByMsgId ((byte)value.MsgId); | |||||
int messageBodyOffset = 0; | int messageBodyOffset = 0; | ||||
if (jTNEBodiesImplType != null) { | if (jTNEBodiesImplType != null) { | ||||
if (value.Bodies != null) { | if (value.Bodies != null) { | ||||
@@ -13,23 +13,26 @@ namespace JTNE.Protocol.Internal { | |||||
InitMap (); | InitMap (); | ||||
} | } | ||||
internal static Type GetBodiesImplTypeByMsgId (byte msgId) => map.TryGetValue (msgId, out Type type) ? type : null; | |||||
/// <summary> | |||||
/// 根据 <see cref="JTNEPackage.MsgId"/> 获取 body 类型 | |||||
/// </summary> | |||||
/// <param name="msgId"></param> | |||||
/// <returns></returns> | |||||
internal static Type GetBodyTypeByMsgId (byte msgId) => map.TryGetValue (msgId, out Type type) ? type : null; | |||||
private static void InitMap () { | private static void InitMap () { | ||||
foreach (JTNEMsgId msgId in Enum.GetValues (typeof (JTNEMsgId))) { | foreach (JTNEMsgId msgId in Enum.GetValues (typeof (JTNEMsgId))) { | ||||
JTNEBodiesTypeAttribute jT808BodiesTypeAttribute = msgId.GetAttribute<JTNEBodiesTypeAttribute> (); | |||||
map.Add ((byte) msgId, jT808BodiesTypeAttribute?.JT808BodiesType); | |||||
JTNEBodiesTypeAttribute attr = msgId.GetAttribute<JTNEBodiesTypeAttribute> (); | |||||
map.Add ((byte) msgId, attr?.BodyType); | |||||
} | } | ||||
} | } | ||||
internal static void SetMap<TJTNEBodies> (byte msgId) | |||||
where TJTNEBodies : JTNEBodies { | |||||
internal static void SetMap<TJTNEBodies> (byte msgId) where TJTNEBodies : JTNEBodies { | |||||
if (!map.ContainsKey (msgId)) | if (!map.ContainsKey (msgId)) | ||||
map.Add (msgId, typeof (TJTNEBodies)); | map.Add (msgId, typeof (TJTNEBodies)); | ||||
} | } | ||||
internal static void ReplaceMap<TJTNEBodies> (byte msgId) | |||||
where TJTNEBodies : JTNEBodies { | |||||
internal static void ReplaceMap<TJTNEBodies> (byte msgId) where TJTNEBodies : JTNEBodies { | |||||
if (!map.ContainsKey (msgId)) | if (!map.ContainsKey (msgId)) | ||||
map.Add (msgId, typeof (TJTNEBodies)); | map.Add (msgId, typeof (TJTNEBodies)); | ||||
else | else | ||||
@@ -11,7 +11,7 @@ namespace JTNE.Protocol | |||||
/// 例如:不同的厂商可能加密方式不同,所以消息数据体不做加解密的判断。 | /// 例如:不同的厂商可能加密方式不同,所以消息数据体不做加解密的判断。 | ||||
/// </summary> | /// </summary> | ||||
[JTNEFormatter(typeof(JTNEHeaderPackageFormatter))] | [JTNEFormatter(typeof(JTNEHeaderPackageFormatter))] | ||||
public class JTNEHeaderPackage | |||||
public class JTNEPackageHeader | |||||
{ | { | ||||
/// <summary> | /// <summary> | ||||
/// 起始符1 | /// 起始符1 | ||||
@@ -14,6 +14,6 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JTNE.Protocol\JTNE.Protocol.csproj" /> | |||||
<ProjectReference Include="..\..\src\JTNE.Protocol\JTNE.Protocol.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -0,0 +1,21 @@ | |||||
using System; | |||||
using JTNE.Protocol.Enums; | |||||
using JTNE.Protocol.Internal; | |||||
using Xunit; | |||||
namespace JTNE.Protocol.Test.Internal { | |||||
public class JTNEMsgIdFactoryTests { | |||||
[Theory] | |||||
[InlineData (JTNEMsgId.Login)] | |||||
[InlineData (JTNEMsgId.UploadIM)] | |||||
[InlineData (JTNEMsgId.Logout)] | |||||
[InlineData (JTNEMsgId.PlatformLogin)] | |||||
[InlineData (JTNEMsgId.PlatformLogout)] | |||||
[InlineData (JTNEMsgId.HeartBeat)] | |||||
[InlineData (JTNEMsgId.CheckTime)] | |||||
public void TestGetBodiesImplTypeByMsgId (JTNEMsgId msgId) { | |||||
var body = JTNEMsgIdFactory.GetBodyTypeByMsgId ((byte) msgId); | |||||
Assert.NotNull (body); | |||||
} | |||||
} | |||||
} |
@@ -15,7 +15,7 @@ | |||||
</ItemGroup> | </ItemGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<ProjectReference Include="..\JTNE.Protocol\JTNE.Protocol.csproj" /> | |||||
<ProjectReference Include="..\..\src\JTNE.Protocol\JTNE.Protocol.csproj" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -1,14 +1,13 @@ | |||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | |||||
using JTNE.Protocol.Enums; | using JTNE.Protocol.Enums; | ||||
using JTNE.Protocol.Extensions; | using JTNE.Protocol.Extensions; | ||||
using JTNE.Protocol.MessageBody; | using JTNE.Protocol.MessageBody; | ||||
using Newtonsoft.Json; | |||||
using Xunit; | using Xunit; | ||||
using Xunit.Abstractions; | using Xunit.Abstractions; | ||||
namespace JTNE.Protocol.Test { | |||||
namespace JTNE.Protocol.Test | |||||
{ | |||||
public class JTNEHeaderPackageTest { | public class JTNEHeaderPackageTest { | ||||
private readonly ITestOutputHelper output; | private readonly ITestOutputHelper output; | ||||
@@ -18,7 +17,7 @@ namespace JTNE.Protocol.Test { | |||||
[Fact] | [Fact] | ||||
public void Test1 () { | public void Test1 () { | ||||
JTNEHeaderPackage jTNEHeaderPackage = new JTNEHeaderPackage (); | |||||
JTNEPackageHeader jTNEHeaderPackage = new JTNEPackageHeader (); | |||||
jTNEHeaderPackage.VIN = "123456789"; | jTNEHeaderPackage.VIN = "123456789"; | ||||
jTNEHeaderPackage.AskId = JTNEAskId.CMD.ToByteValue (); | jTNEHeaderPackage.AskId = JTNEAskId.CMD.ToByteValue (); | ||||
jTNEHeaderPackage.MsgId = JTNEMsgId.Login.ToByteValue (); | jTNEHeaderPackage.MsgId = JTNEMsgId.Login.ToByteValue (); | ||||
@@ -40,7 +39,7 @@ namespace JTNE.Protocol.Test { | |||||
[Fact] | [Fact] | ||||
public void Test2 () { | public void Test2 () { | ||||
var data = "232301FE313233343536373839000000000000000001002A130116173738000131323334353637383939383736353433323130300304313233343435363739383730FD".ToHexBytes (); | var data = "232301FE313233343536373839000000000000000001002A130116173738000131323334353637383939383736353433323130300304313233343435363739383730FD".ToHexBytes (); | ||||
JTNEHeaderPackage jTNEHeaderPackage = JTNESerializer.Deserialize<JTNEHeaderPackage> (data); | |||||
JTNEPackageHeader jTNEHeaderPackage = JTNESerializer.Deserialize<JTNEPackageHeader> (data); | |||||
Assert.Equal (JTNEAskId.CMD.ToByteValue (), jTNEHeaderPackage.AskId); | Assert.Equal (JTNEAskId.CMD.ToByteValue (), jTNEHeaderPackage.AskId); | ||||
Assert.Equal (JTNEMsgId.Login.ToByteValue (), jTNEHeaderPackage.MsgId); | Assert.Equal (JTNEMsgId.Login.ToByteValue (), jTNEHeaderPackage.MsgId); | ||||
Assert.Equal ("123456789", jTNEHeaderPackage.VIN); | Assert.Equal ("123456789", jTNEHeaderPackage.VIN); | ||||
@@ -55,42 +54,10 @@ namespace JTNE.Protocol.Test { | |||||
Assert.Equal ("9870", jTNE_0X01.BatteryNos[2]); | Assert.Equal ("9870", jTNE_0X01.BatteryNos[2]); | ||||
} | } | ||||
[Fact] | |||||
public void TestGuangtai () { | |||||
JTNEGlobalConfigs.Instance.Encoding = Encoding.GetEncoding ("GB18030"); | |||||
var data = "23 23 05 FE 30 30 30 30 30 30 30 30 30 30 30 30 30 32 31 31 31 01 00 29 14 07 14 13 26 22 00 01 CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB B3 B5 C1 AA CD F2 01 02 01 A1".ToHexBytes (); | |||||
var package = JTNESerializer.Deserialize (data); | |||||
Assert.Equal (JTNEAskId.CMD, package.AskId); | |||||
Assert.Equal (JTNEMsgId.PlatformLogin, package.MsgId); | |||||
Assert.Equal (41, package.DataUnitLength); | |||||
Assert.NotNull (package.Bodies); | |||||
Assert.IsType<JTNE_0x05> (package.Bodies); | |||||
output.WriteLine (Newtonsoft.Json.JsonConvert.SerializeObject (package.Bodies, Formatting.Indented)); | |||||
var loginbody = (JTNE_0x05) package.Bodies; | |||||
Assert.Equal ("威海广泰空港", loginbody.PlatformUserName); | |||||
Assert.Equal (1, loginbody.LoginNum); | |||||
Assert.Equal (JTNEEncryptMethod.None, loginbody.EncryptMethod); | |||||
} | |||||
[Fact] | |||||
public void TestGenerateReply(){ | |||||
JTNEGlobalConfigs.Instance.Encoding = Encoding.GetEncoding ("GB18030"); | |||||
var data = "23 23 05 FE 30 30 30 30 30 30 30 30 30 30 30 30 30 32 31 31 31 01 00 29 14 07 14 13 26 22 00 01 CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB B3 B5 C1 AA CD F2 01 02 01 A1".ToHexBytes (); | |||||
var package = JTNESerializer.Deserialize (data); | |||||
var reply = package.GenerateReply(JTNEAskId.Success); | |||||
Assert.NotNull(reply); | |||||
var bytes = JTNESerializer.Serialize(reply); | |||||
output.WriteLine(bytes.ToHexString()); | |||||
} | |||||
} | } | ||||
public static class JTNEReplyExtensions{ | public static class JTNEReplyExtensions{ | ||||
public static JTNEPackage GenerateReply(this JTNEPackage source,JTNEAskId askId){ | public static JTNEPackage GenerateReply(this JTNEPackage source,JTNEAskId askId){ | ||||
return new JTNEPackage(){ | return new JTNEPackage(){ | ||||
MsgId = source.MsgId, | MsgId = source.MsgId, |
@@ -0,0 +1,53 @@ | |||||
using System.Text; | |||||
using JTNE.Protocol.Enums; | |||||
using JTNE.Protocol.Extensions; | |||||
using JTNE.Protocol.MessageBody; | |||||
using Newtonsoft.Json; | |||||
using Xunit; | |||||
using Xunit.Abstractions; | |||||
namespace JTNE.Protocol.Test | |||||
{ | |||||
public class JTNEPackageParseTests{ | |||||
private readonly ITestOutputHelper output; | |||||
public JTNEPackageParseTests (ITestOutputHelper outputHelper) { | |||||
this.output = outputHelper; | |||||
} | |||||
const string data="232302FE303030303030303030303032303037343101009C1407160B210801FF04010000FFFFFFFFE5F6280732FFFE03D1FFFF020101FFFF4E204E204BFFFFFFFF03FFFFFFFFFFFF3000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0401FFFFFFFFFFFFFFFFFFFFFF05FFFFFFFFFFFFFFFFFF06FFFFFFFFFFFFFFFF4800482502450700000000000000000049"; | |||||
[Fact] | |||||
public void TestGuangtai () { | |||||
JTNEGlobalConfigs.Instance.Encoding = Encoding.GetEncoding ("GB18030"); | |||||
var data = "23 23 05 FE 30 30 30 30 30 30 30 30 30 30 30 30 30 32 31 31 31 01 00 29 14 07 14 13 26 22 00 01 CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB B3 B5 C1 AA CD F2 01 02 01 A1".ToHexBytes (); | |||||
var package = JTNESerializer.Deserialize (data); | |||||
Assert.Equal (JTNEAskId.CMD, package.AskId); | |||||
Assert.Equal (JTNEMsgId.PlatformLogin, package.MsgId); | |||||
Assert.Equal (41, package.DataUnitLength); | |||||
Assert.NotNull (package.Bodies); | |||||
Assert.IsType<JTNE_0x05> (package.Bodies); | |||||
output.WriteLine (Newtonsoft.Json.JsonConvert.SerializeObject (package.Bodies, Formatting.Indented)); | |||||
var loginbody = (JTNE_0x05) package.Bodies; | |||||
Assert.Equal ("威海广泰空港", loginbody.PlatformUserName); | |||||
Assert.Equal (1, loginbody.LoginNum); | |||||
Assert.Equal (JTNEEncryptMethod.None, loginbody.EncryptMethod); | |||||
} | |||||
[Fact] | |||||
public void TestGenerateReply(){ | |||||
JTNEGlobalConfigs.Instance.Encoding = Encoding.GetEncoding ("GB18030"); | |||||
var data = "23 23 05 FE 30 30 30 30 30 30 30 30 30 30 30 30 30 32 31 31 31 01 00 29 14 07 14 13 26 22 00 01 CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB CD FE BA A3 B9 E3 CC A9 BF D5 B8 DB B3 B5 C1 AA CD F2 01 02 01 A1".ToHexBytes (); | |||||
var package = JTNESerializer.Deserialize (data); | |||||
var reply = package.GenerateReply(JTNEAskId.Success); | |||||
Assert.NotNull(reply); | |||||
var bytes = JTNESerializer.Serialize(reply); | |||||
output.WriteLine(bytes.ToHexString()); | |||||
} | |||||
} | |||||
} |