diff --git a/README.md b/README.md index 36154c3..0535ba5 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,12 @@ 反转义的原因:确认JT809协议的TCP消息边界。 -### 举个栗子 +### 举个栗子1 #### 1.组包: > 业务数据类型 MsgID:从链路报警信息交互消息 +> > 子业务类型标识 SubBusinessType:报警督办请求消息 ``` code @@ -183,8 +184,43 @@ Assert.Equal("123456@qq.com", jT809_0x9400_0x9401.SupervisorEmail); ``` +### 举个栗子3 +``` data2 +// 设置全局配置 +JT809GlobalConfig.Instance.SetHeaderOptions(new JT809Configs.JT809HeaderOptions +{ + EncryptKey= 9999, + MsgGNSSCENTERID= 20180920 +}); + +// 根据业务类型创建对应包 +JT809Package jT809Package = JT809BusinessType.DOWN_WARN_MSG.Create(new JT809_0x9400 +{ + VehicleNo = "粤A12345", + VehicleColor = JT809Enums.JT809VehicleColorType.黄色, + SubBusinessType = JT809Enums.JT809SubBusinessType.DOWN_WARN_MSG_URGE_TODO_REQ, + JT809SubBodies = new JT809_0x9400_0x9401 + { + WarnSrc = JT809WarnSrc.车载终端, + WarnType = JT809WarnType.疲劳驾驶报警, + WarnTime = DateTime.Parse("2018-09-27 10:24:00"), + SupervisionID = "123FFAA1", + SupervisionEndTime = DateTime.Parse("2018-09-27 11:24:00"), + SupervisionLevel = 3, + Supervisor = "smallchi", + SupervisorTel = "12345678901", + SupervisorEmail = "123456@qq.com" + } +}); +var hex = JT809Serializer.Serialize(jT809Package); +``` + ## NuGet安装 +| Package Name | Version | Downloads +|--------------| ------- | ---- +| JT809 | ![](https://img.shields.io/nuget/v/JT809.svg) | ![](https://img.shields.io/nuget/dt/JT809.svg) + Install-Package JT809 ## 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) diff --git a/src/JT809.Protocol.Test/JT809HeaderTest.cs b/src/JT809.Protocol.Test/JT809HeaderTest.cs index 7cdd98b..ed5d254 100644 --- a/src/JT809.Protocol.Test/JT809HeaderTest.cs +++ b/src/JT809.Protocol.Test/JT809HeaderTest.cs @@ -4,6 +4,8 @@ using System.Text; using Xunit; using JT809.Protocol; using JT809.Protocol.JT809Extensions; +using System.Threading.Tasks; +using System.Diagnostics; namespace JT809.Protocol.Test { @@ -37,5 +39,19 @@ namespace JT809.Protocol.Test Assert.Equal(JT809Header_Encrypt.None, jT809Header.EncryptFlag); Assert.Equal((uint)0, jT809Header.EncryptKey); } + + [Fact] + public void Test3() + { + Parallel.For(0, 1000, (i) => + { + JT809GlobalConfig.Instance.MsgSNDistributed.Increment(); + }); + Parallel.For(0, 1000, (i) => + { + JT809GlobalConfig.Instance.MsgSNDistributed.Increment(); + }); + var sn = JT809GlobalConfig.Instance.MsgSNDistributed.Increment(); + } } } diff --git a/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001EncryptPackageTest.cs b/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001EncryptPackageTest.cs index 03978f4..06c5ea4 100644 --- a/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001EncryptPackageTest.cs +++ b/src/JT809.Protocol.Test/JT809Packages/JT809_0x1001EncryptPackageTest.cs @@ -13,7 +13,7 @@ namespace JT809.Protocol.Test.JT809Packages { public JT809_0x1001EncryptPackageTest() { - JT809GlobalConfig.Instance.SetJT809Encrypt(new JT809EncryptImpl(new JT809Configs.JT809EncryptOptions() + JT809GlobalConfig.Instance.SetEncrypt(new JT809EncryptImpl(new JT809Configs.JT809EncryptOptions() { IA1 = 20000000, IC1 = 20000000, diff --git a/src/JT809.Protocol.Test/JT809Packages/JT809_0x9400_0x9401PackageTest.cs b/src/JT809.Protocol.Test/JT809Packages/JT809_0x9400_0x9401PackageTest.cs index 4a9eb8b..1f16dc2 100644 --- a/src/JT809.Protocol.Test/JT809Packages/JT809_0x9400_0x9401PackageTest.cs +++ b/src/JT809.Protocol.Test/JT809Packages/JT809_0x9400_0x9401PackageTest.cs @@ -83,5 +83,36 @@ namespace JT809.Protocol.Test.JT809Packages Assert.Equal("12345678901", jT809_0x9400_0x9401.SupervisorTel); Assert.Equal("123456@qq.com", jT809_0x9400_0x9401.SupervisorEmail); } + + [Fact] + public void Test3() + { + JT809GlobalConfig.Instance.SetHeaderOptions(new JT809Configs.JT809HeaderOptions + { + EncryptKey= 9999, + MsgGNSSCENTERID= 20180920 + }); + JT809Package jT809Package = JT809BusinessType.DOWN_WARN_MSG.Create(new JT809_0x9400 + { + VehicleNo = "粤A12345", + VehicleColor = JT809Enums.JT809VehicleColorType.黄色, + SubBusinessType = JT809Enums.JT809SubBusinessType.DOWN_WARN_MSG_URGE_TODO_REQ, + JT809SubBodies = new JT809_0x9400_0x9401 + { + WarnSrc = JT809WarnSrc.车载终端, + WarnType = JT809WarnType.疲劳驾驶报警, + WarnTime = DateTime.Parse("2018-09-27 10:24:00"), + SupervisionID = "123FFAA1", + SupervisionEndTime = DateTime.Parse("2018-09-27 11:24:00"), + SupervisionLevel = 3, + Supervisor = "smallchi", + SupervisorTel = "12345678901", + SupervisorEmail = "123456@qq.com" + } + }); + jT809Package.Header.MsgSN = 1666; + var hex = JT809Serializer.Serialize(jT809Package).ToHexString(); + //"5B000000920000068294000133EFB8010000000000270FD4C1413132333435000000000000000000000000000294010000005C010002000000005A01AC3F40123FFAA1000000005A01AC4D5003736D616C6C636869000000000000000031323334353637383930310000000000000000003132333435364071712E636F6D00000000000000000000000000000000000000BAD85D" + } } } diff --git a/src/JT809.Protocol/IMsgSNDistributed.cs b/src/JT809.Protocol/IMsgSNDistributed.cs new file mode 100644 index 0000000..6627532 --- /dev/null +++ b/src/JT809.Protocol/IMsgSNDistributed.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol +{ + public interface IMsgSNDistributed + { + uint Increment(); + } +} diff --git a/src/JT809.Protocol/JT809.Protocol.csproj b/src/JT809.Protocol/JT809.Protocol.csproj index 100b51f..7e6af51 100644 --- a/src/JT809.Protocol/JT809.Protocol.csproj +++ b/src/JT809.Protocol/JT809.Protocol.csproj @@ -54,6 +54,7 @@ + diff --git a/src/JT809.Protocol/JT809Configs/JT809HeaderOptions.cs b/src/JT809.Protocol/JT809Configs/JT809HeaderOptions.cs new file mode 100644 index 0000000..ec8be43 --- /dev/null +++ b/src/JT809.Protocol/JT809Configs/JT809HeaderOptions.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Configs +{ + public class JT809HeaderOptions + { + /// + /// 下级平台接入码,上级平台给下级平台分配唯一标识码。 + /// + public uint MsgGNSSCENTERID { get; set; } + /// + /// 协议版本号标识,上下级平台之间采用的标准协议版 + /// 编号;长度为 3 个字节来表示,0x01 0x02 0x0F 标识 + /// 的版本号是 v1.2.15,以此类推。 + /// + public JT809Header_Version Version { get; set; } = new JT809Header_Version(); + /// + /// 报文加密标识位 b: 0 表示报文不加密,1 表示报文加密。 + /// + public JT809Header_Encrypt EncryptFlag { get; set; } = JT809Header_Encrypt.None; + /// + /// 数据加密的密匙,长度为 4 个字节 + /// + public uint EncryptKey { get; set; } + } +} diff --git a/src/JT809.Protocol/JT809Extensions/JT809HexExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809HexExtensions.cs index 8d03670..fe93e2c 100644 --- a/src/JT809.Protocol/JT809Extensions/JT809HexExtensions.cs +++ b/src/JT809.Protocol/JT809Extensions/JT809HexExtensions.cs @@ -79,6 +79,7 @@ namespace JT809.Protocol.JT809Extensions public static string ToHexString(this byte[] source) { + //return string.Join(separator, source.Select(s => s.ToString("X2"))); return ToHexString(source, false); } diff --git a/src/JT809.Protocol/JT809Extensions/JT809PackageExtensions.cs b/src/JT809.Protocol/JT809Extensions/JT809PackageExtensions.cs new file mode 100644 index 0000000..6db7ae8 --- /dev/null +++ b/src/JT809.Protocol/JT809Extensions/JT809PackageExtensions.cs @@ -0,0 +1,117 @@ +using JT809.Protocol.JT809Enums; +using System; +using System.Collections.Generic; +using System.Text; + +namespace JT809.Protocol.JT809Extensions +{ + public static class JT809PackageExtensions + { + /// + /// 创建JT809Package对应的数据体: + /// + /// + /// JT809_0x1001 + /// + /// + /// JT809_0x1002 + /// + /// + /// JT809_0x1003 + /// + /// + /// JT809_0x1004 + /// + /// + /// JT809_0x1005 + /// + /// + /// JT809_0x1006 + /// + /// + /// JT809_0x1007 + /// + /// + /// JT809_0x1008 + /// + /// + /// JT809_0x1200 + /// + /// + /// JT809_0x1300 + /// + /// + /// JT809_0x1400 + /// + /// + /// JT809_0x1500 + /// + /// + /// JT809_0x1600 + /// + /// + /// JT809_0x9001 + /// + /// + /// JT809_0x9002 + /// + /// + /// JT809_0x9003 + /// + /// + /// JT809_0x9004 + /// + /// + /// JT809_0x9005 + /// + /// + /// JT809_0x9006 + /// + /// + /// JT809_0x9007 + /// + /// + /// JT809_0x9008 + /// + /// + /// JT809_0x9101 + /// + /// + /// JT809_0x9200 + /// + /// + /// JT809_0x9300 + /// + /// + /// JT809_0x9400 + /// + /// + /// JT809_0x9500 + /// + /// + /// JT809_0x9600 + /// + /// + /// + /// + /// + /// + /// + public static JT809Package Create(this JT809BusinessType msgID, TJT809Bodies jT809Bodies) + where TJT809Bodies: JT809Bodies + { + JT809Package jT809Package = new JT809Package(); + jT809Package.Bodies = jT809Bodies; + jT809Package.Header = new JT809Header() + { + MsgID = msgID, + MsgSN = JT809GlobalConfig.Instance.MsgSNDistributed.Increment(), + EncryptFlag = JT809GlobalConfig.Instance.HeaderOptions.EncryptFlag, + EncryptKey = JT809GlobalConfig.Instance.HeaderOptions.EncryptKey, + MsgGNSSCENTERID = JT809GlobalConfig.Instance.HeaderOptions.MsgGNSSCENTERID, + Version = JT809GlobalConfig.Instance.HeaderOptions.Version + }; + return jT809Package; + } + } +} diff --git a/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs b/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs index 782378e..9676adf 100644 --- a/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs +++ b/src/JT809.Protocol/JT809Formatters/JT809PackageFormatter.cs @@ -62,7 +62,7 @@ namespace JT809.Protocol.JT809Formatters jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), buffer.Slice(offset, checkIndex - offset), out readSize); break; case JT809Header_Encrypt.Common: - byte[] bodiesData = JT809GlobalConfig.Instance.JT809Encrypt.Decrypt(buffer.Slice(offset, checkIndex - offset).ToArray()); + byte[] bodiesData = JT809GlobalConfig.Instance.Encrypt.Decrypt(buffer.Slice(offset, checkIndex - offset).ToArray()); jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), bodiesData, out readSize); break; } @@ -101,7 +101,7 @@ namespace JT809.Protocol.JT809Formatters case JT809Header_Encrypt.None: break; case JT809Header_Encrypt.Common: - messageBodyData = JT809GlobalConfig.Instance.JT809Encrypt.Encrypt(messageBodyData); + messageBodyData = JT809GlobalConfig.Instance.Encrypt.Encrypt(messageBodyData); break; } } diff --git a/src/JT809.Protocol/JT809GlobalConfig.cs b/src/JT809.Protocol/JT809GlobalConfig.cs index e18c166..a99fe83 100644 --- a/src/JT809.Protocol/JT809GlobalConfig.cs +++ b/src/JT809.Protocol/JT809GlobalConfig.cs @@ -1,4 +1,6 @@ -using System; +using JT809.Protocol.JT809Configs; +using JT809.Protocol.JT809Internal; +using System; using System.Collections.Generic; using System.Text; @@ -8,7 +10,11 @@ namespace JT809.Protocol { private static readonly Lazy instance = new Lazy(() => new JT809GlobalConfig()); - private JT809GlobalConfig(){} + private JT809GlobalConfig() + { + MsgSNDistributed = new DefaultMsgSNDistributedImpl(); + HeaderOptions = new JT809HeaderOptions(); + } public static JT809GlobalConfig Instance { @@ -18,11 +24,27 @@ namespace JT809.Protocol } } - public IJT809Encrypt JT809Encrypt { get; private set; } + public IJT809Encrypt Encrypt { get; private set; } + + public IMsgSNDistributed MsgSNDistributed {get;private set;} + + public JT809HeaderOptions HeaderOptions { get; private set; } + + public JT809GlobalConfig SetEncrypt(IJT809Encrypt jT809Encrypt) + { + instance.Value.Encrypt = jT809Encrypt; + return instance.Value; + } + + public JT809GlobalConfig SetMsgSNDistributed(IMsgSNDistributed msgSNDistributed) + { + instance.Value.MsgSNDistributed = msgSNDistributed; + return instance.Value; + } - public JT809GlobalConfig SetJT809Encrypt(IJT809Encrypt jT809Encrypt) + public JT809GlobalConfig SetHeaderOptions(JT809HeaderOptions jT809HeaderOptions) { - instance.Value.JT809Encrypt = jT809Encrypt; + instance.Value.HeaderOptions = jT809HeaderOptions; return instance.Value; } } diff --git a/src/JT809.Protocol/JT809Internal/DefaultMsgSNDistributedImpl.cs b/src/JT809.Protocol/JT809Internal/DefaultMsgSNDistributedImpl.cs new file mode 100644 index 0000000..efabcda --- /dev/null +++ b/src/JT809.Protocol/JT809Internal/DefaultMsgSNDistributedImpl.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace JT809.Protocol.JT809Internal +{ + internal class DefaultMsgSNDistributedImpl : IMsgSNDistributed + { + int _counter = 0; + + public uint Increment() + { + return (uint)Interlocked.Increment(ref _counter); + } + } +} diff --git a/src/JT809.Protocol/JT809Serializer.cs b/src/JT809.Protocol/JT809Serializer.cs index b5c1fd8..78ac39a 100644 --- a/src/JT809.Protocol/JT809Serializer.cs +++ b/src/JT809.Protocol/JT809Serializer.cs @@ -10,11 +10,11 @@ namespace JT809.Protocol { public static class JT809Serializer { - public static byte[] Serialize(JT809Package jT809Package) + public static byte[] Serialize(JT809Package jT809Package, int minBufferSize = 4096) { var formatter = JT809FormatterExtensions.GetFormatter(); var pool = MemoryPool.Shared; - IMemoryOwner buffer = pool.Rent(4096); + IMemoryOwner buffer = pool.Rent(minBufferSize); try { var len = formatter.Serialize(buffer, 0, jT809Package); @@ -35,11 +35,11 @@ namespace JT809.Protocol return formatter.Deserialize(bytes, out int readSize); } - public static byte[] Serialize(T obj) + public static byte[] Serialize(T obj, int minBufferSize = 4096) { var formatter = JT809FormatterExtensions.GetFormatter(); var pool = MemoryPool.Shared; - IMemoryOwner buffer = pool.Rent(4096); + IMemoryOwner buffer = pool.Rent(minBufferSize); try { var len = formatter.Serialize(buffer, 0, obj);