2.修改对应序列化BufferSize的大小可根据实际组包调整; 3.增加业务类型创建包的扩展; 4.增加全局配置:头部及序列号配置. 5.修改文档tags/v1.3.0
@@ -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 |  |  | |||
Install-Package JT809 | |||
## 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) | |||
@@ -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(); | |||
} | |||
} | |||
} |
@@ -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, | |||
@@ -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" | |||
} | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT809.Protocol | |||
{ | |||
public interface IMsgSNDistributed | |||
{ | |||
uint Increment(); | |||
} | |||
} |
@@ -54,6 +54,7 @@ | |||
<ItemGroup> | |||
<Compile Include="JT809Configs\JT809EncryptOptions.cs" /> | |||
<Compile Include="JT809Configs\JT809HeaderOptions.cs" /> | |||
<Compile Include="JT809Enums\JT808_Alarm.cs" /> | |||
<Compile Include="JT809Enums\JT808_Status.cs" /> | |||
<Compile Include="JT809Enums\JT809CommandType.cs" /> | |||
@@ -0,0 +1,28 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT809.Protocol.JT809Configs | |||
{ | |||
public class JT809HeaderOptions | |||
{ | |||
/// <summary> | |||
/// 下级平台接入码,上级平台给下级平台分配唯一标识码。 | |||
/// </summary> | |||
public uint MsgGNSSCENTERID { get; set; } | |||
/// <summary> | |||
/// 协议版本号标识,上下级平台之间采用的标准协议版 | |||
/// 编号;长度为 3 个字节来表示,0x01 0x02 0x0F 标识 | |||
/// 的版本号是 v1.2.15,以此类推。 | |||
/// </summary> | |||
public JT809Header_Version Version { get; set; } = new JT809Header_Version(); | |||
/// <summary> | |||
/// 报文加密标识位 b: 0 表示报文不加密,1 表示报文加密。 | |||
/// </summary> | |||
public JT809Header_Encrypt EncryptFlag { get; set; } = JT809Header_Encrypt.None; | |||
/// <summary> | |||
/// 数据加密的密匙,长度为 4 个字节 | |||
/// </summary> | |||
public uint EncryptKey { get; set; } | |||
} | |||
} |
@@ -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); | |||
} | |||
@@ -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 | |||
{ | |||
/// <summary> | |||
/// 创建JT809Package对应的数据体: | |||
/// <list type="TJT809Bodies"> | |||
/// <item> | |||
/// <description>JT809_0x1001</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1002</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1003</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1004</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1005</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1006</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1007</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1008</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1200</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1300</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1400</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1500</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x1600</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9001</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9002</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9003</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9004</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9005</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9006</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9007</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9008</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9101</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9200</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9300</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9400</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9500</description> | |||
/// </item> | |||
/// <item> | |||
/// <description>JT809_0x9600</description> | |||
/// </item> | |||
/// </list> | |||
/// </summary> | |||
/// <typeparam name="TJT809Bodies"></typeparam> | |||
/// <param name="msgID"></param> | |||
/// <param name="jT809Bodies"></param> | |||
/// <returns></returns> | |||
public static JT809Package Create<TJT809Bodies>(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; | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
@@ -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<JT809GlobalConfig> instance = new Lazy<JT809GlobalConfig>(() => 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; | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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<JT809Package>(); | |||
var pool = MemoryPool<byte>.Shared; | |||
IMemoryOwner<byte> buffer = pool.Rent(4096); | |||
IMemoryOwner<byte> 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>(T obj) | |||
public static byte[] Serialize<T>(T obj, int minBufferSize = 4096) | |||
{ | |||
var formatter = JT809FormatterExtensions.GetFormatter<T>(); | |||
var pool = MemoryPool<byte>.Shared; | |||
IMemoryOwner<byte> buffer = pool.Rent(4096); | |||
IMemoryOwner<byte> buffer = pool.Rent(minBufferSize); | |||
try | |||
{ | |||
var len = formatter.Serialize(buffer, 0, obj); | |||