2.修改对应序列化BufferSize的大小可根据实际组包调整; 3.增加业务类型创建包的扩展; 4.增加全局配置:头部及序列号配置. 5.修改文档tags/v1.3.0
@@ -54,11 +54,12 @@ | |||||
反转义的原因:确认JT809协议的TCP消息边界。 | 反转义的原因:确认JT809协议的TCP消息边界。 | ||||
### 举个栗子 | |||||
### 举个栗子1 | |||||
#### 1.组包: | #### 1.组包: | ||||
> 业务数据类型 MsgID:从链路报警信息交互消息 | > 业务数据类型 MsgID:从链路报警信息交互消息 | ||||
> | |||||
> 子业务类型标识 SubBusinessType:报警督办请求消息 | > 子业务类型标识 SubBusinessType:报警督办请求消息 | ||||
``` code | ``` 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安装 | ## NuGet安装 | ||||
| Package Name | Version | Downloads | |||||
|--------------| ------- | ---- | |||||
| JT809 |  |  | |||||
Install-Package JT809 | Install-Package JT809 | ||||
## 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) | ## 使用BenchmarkDotNet性能测试报告(只是玩玩,不能当真) | ||||
@@ -4,6 +4,8 @@ using System.Text; | |||||
using Xunit; | using Xunit; | ||||
using JT809.Protocol; | using JT809.Protocol; | ||||
using JT809.Protocol.JT809Extensions; | using JT809.Protocol.JT809Extensions; | ||||
using System.Threading.Tasks; | |||||
using System.Diagnostics; | |||||
namespace JT809.Protocol.Test | namespace JT809.Protocol.Test | ||||
{ | { | ||||
@@ -37,5 +39,19 @@ namespace JT809.Protocol.Test | |||||
Assert.Equal(JT809Header_Encrypt.None, jT809Header.EncryptFlag); | Assert.Equal(JT809Header_Encrypt.None, jT809Header.EncryptFlag); | ||||
Assert.Equal((uint)0, jT809Header.EncryptKey); | 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() | public JT809_0x1001EncryptPackageTest() | ||||
{ | { | ||||
JT809GlobalConfig.Instance.SetJT809Encrypt(new JT809EncryptImpl(new JT809Configs.JT809EncryptOptions() | |||||
JT809GlobalConfig.Instance.SetEncrypt(new JT809EncryptImpl(new JT809Configs.JT809EncryptOptions() | |||||
{ | { | ||||
IA1 = 20000000, | IA1 = 20000000, | ||||
IC1 = 20000000, | IC1 = 20000000, | ||||
@@ -83,5 +83,36 @@ namespace JT809.Protocol.Test.JT809Packages | |||||
Assert.Equal("12345678901", jT809_0x9400_0x9401.SupervisorTel); | Assert.Equal("12345678901", jT809_0x9400_0x9401.SupervisorTel); | ||||
Assert.Equal("123456@qq.com", jT809_0x9400_0x9401.SupervisorEmail); | 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> | <ItemGroup> | ||||
<Compile Include="JT809Configs\JT809EncryptOptions.cs" /> | <Compile Include="JT809Configs\JT809EncryptOptions.cs" /> | ||||
<Compile Include="JT809Configs\JT809HeaderOptions.cs" /> | |||||
<Compile Include="JT809Enums\JT808_Alarm.cs" /> | <Compile Include="JT809Enums\JT808_Alarm.cs" /> | ||||
<Compile Include="JT809Enums\JT808_Status.cs" /> | <Compile Include="JT809Enums\JT808_Status.cs" /> | ||||
<Compile Include="JT809Enums\JT809CommandType.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) | public static string ToHexString(this byte[] source) | ||||
{ | { | ||||
//return string.Join(separator, source.Select(s => s.ToString("X2"))); | |||||
return ToHexString(source, false); | 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); | jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), buffer.Slice(offset, checkIndex - offset), out readSize); | ||||
break; | break; | ||||
case JT809Header_Encrypt.Common: | 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); | jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), bodiesData, out readSize); | ||||
break; | break; | ||||
} | } | ||||
@@ -101,7 +101,7 @@ namespace JT809.Protocol.JT809Formatters | |||||
case JT809Header_Encrypt.None: | case JT809Header_Encrypt.None: | ||||
break; | break; | ||||
case JT809Header_Encrypt.Common: | case JT809Header_Encrypt.Common: | ||||
messageBodyData = JT809GlobalConfig.Instance.JT809Encrypt.Encrypt(messageBodyData); | |||||
messageBodyData = JT809GlobalConfig.Instance.Encrypt.Encrypt(messageBodyData); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -1,4 +1,6 @@ | |||||
using System; | |||||
using JT809.Protocol.JT809Configs; | |||||
using JT809.Protocol.JT809Internal; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
@@ -8,7 +10,11 @@ namespace JT809.Protocol | |||||
{ | { | ||||
private static readonly Lazy<JT809GlobalConfig> instance = new Lazy<JT809GlobalConfig>(() => new JT809GlobalConfig()); | 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 | 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; | 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 class JT809Serializer | ||||
{ | { | ||||
public static byte[] Serialize(JT809Package jT809Package) | |||||
public static byte[] Serialize(JT809Package jT809Package, int minBufferSize = 4096) | |||||
{ | { | ||||
var formatter = JT809FormatterExtensions.GetFormatter<JT809Package>(); | var formatter = JT809FormatterExtensions.GetFormatter<JT809Package>(); | ||||
var pool = MemoryPool<byte>.Shared; | var pool = MemoryPool<byte>.Shared; | ||||
IMemoryOwner<byte> buffer = pool.Rent(4096); | |||||
IMemoryOwner<byte> buffer = pool.Rent(minBufferSize); | |||||
try | try | ||||
{ | { | ||||
var len = formatter.Serialize(buffer, 0, jT809Package); | var len = formatter.Serialize(buffer, 0, jT809Package); | ||||
@@ -35,11 +35,11 @@ namespace JT809.Protocol | |||||
return formatter.Deserialize(bytes, out int readSize); | 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 formatter = JT809FormatterExtensions.GetFormatter<T>(); | ||||
var pool = MemoryPool<byte>.Shared; | var pool = MemoryPool<byte>.Shared; | ||||
IMemoryOwner<byte> buffer = pool.Rent(4096); | |||||
IMemoryOwner<byte> buffer = pool.Rent(minBufferSize); | |||||
try | try | ||||
{ | { | ||||
var len = formatter.Serialize(buffer, 0, obj); | var len = formatter.Serialize(buffer, 0, obj); | ||||