@@ -1,6 +1,6 @@ | |||
# JT808协议 | |||
[](https://github.com/SmallChi/JT808/blob/master/LICENSE)[](https://app.fossa.io/projects/git%2Bgithub.com%2FSmallChi%2FJT808?ref=badge_shield)[](https://travis-ci.org/SmallChi/JT808)[]() | |||
[](https://github.com/SmallChi/JT808/blob/master/LICENSE)[]() | |||
## 前提条件 | |||
@@ -1,20 +1,34 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessageBody; | |||
using JT808.Protocol.MessagePack; | |||
using JT808.Protocol.Extensions; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.Test.MessageBody.JT808_0X8900_BodiesImpl | |||
{ | |||
public class JT808_0X8900_Test_BodiesImpl: JT808_0x8900_BodyBase, IJT808MessagePackFormatter<JT808_0X8900_Test_BodiesImpl> | |||
public class JT808_0X8900_Test_BodiesImpl: JT808_0x8900_BodyBase, IJT808MessagePackFormatter<JT808_0X8900_Test_BodiesImpl>, IJT808Analyze | |||
{ | |||
public uint Id { get; set; } | |||
public byte Sex { get; set; } | |||
public override byte PassthroughType { get; set; } = 0x0B; | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
JT808_0X8900_Test_BodiesImpl value = new JT808_0X8900_Test_BodiesImpl(); | |||
value.Id = reader.ReadUInt32(); | |||
writer.WriteNumber($"[{value.Id.ReadNumber()}]编号Id", value.Id); | |||
value.Sex = reader.ReadByte(); | |||
writer.WriteNumber($"[{value.Sex.ReadNumber()}]性别", value.Sex); | |||
} | |||
public JT808_0X8900_Test_BodiesImpl Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_0X8900_Test_BodiesImpl jT808_0X8900_Test_BodiesImpl = new JT808_0X8900_Test_BodiesImpl(); | |||
jT808_0X8900_Test_BodiesImpl.Id = reader.ReadUInt32(); | |||
jT808_0X8900_Test_BodiesImpl.Sex = reader.ReadByte(); | |||
return jT808_0X8900_Test_BodiesImpl; | |||
JT808_0X8900_Test_BodiesImpl value = new JT808_0X8900_Test_BodiesImpl(); | |||
value.Id = reader.ReadUInt32(); | |||
value.Sex = reader.ReadByte(); | |||
return value; | |||
} | |||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0X8900_Test_BodiesImpl value, IJT808Config config) | |||
@@ -16,6 +16,7 @@ namespace JT808.Protocol.Test.MessageBody | |||
{ | |||
IJT808Config jT808Config = new DefaultGlobalConfig(); | |||
jT808Config.FormatterFactory.SetMap<JT808_0x0900_0x83>(); | |||
jT808Config.JT808_0x0900_Custom_Factory.SetMap<JT808_0x0900_0x83>(); | |||
JT808Serializer = new JT808Serializer(jT808Config); | |||
} | |||
[Fact] | |||
@@ -43,21 +44,21 @@ namespace JT808.Protocol.Test.MessageBody | |||
public void Test1_1() | |||
{ | |||
byte[] bytes = "7E 09 00 00 09 00 01 23 45 67 89 00 0A 83 73 6D 61 6C 6C 63 68 69 1D 7E".ToHexBytes(); | |||
JT808Package jT808_0X0900 = JT808Serializer.Deserialize<JT808Package>(bytes); | |||
JT808Package jT808_0X0900 = JT808Serializer.Deserialize(bytes); | |||
Assert.Equal(Enums.JT808MsgId.数据上行透传.ToUInt16Value(), jT808_0X0900.Header.MsgId); | |||
Assert.Equal(10, jT808_0X0900.Header.MsgNum); | |||
Assert.Equal("123456789", jT808_0X0900.Header.TerminalPhoneNo); | |||
JT808_0x0900 JT808Bodies = (JT808_0x0900)jT808_0X0900.Bodies; | |||
JT808_0x0900_0x83 jT808_0x0900_0x83 = JT808Serializer.Deserialize<JT808_0x0900_0x83>(JT808Bodies.PassthroughData); | |||
JT808_0x0900_0x83 jT808_0x0900_0x83 = (JT808_0x0900_0x83)JT808Bodies.JT808_0x0900_BodyBase; | |||
Assert.Equal("smallchi", jT808_0x0900_0x83.PassthroughContent); | |||
Assert.Equal(0x83, JT808Bodies.PassthroughType); | |||
} | |||
[Fact] | |||
public void Test1_2() | |||
public void Test1_3() | |||
{ | |||
byte[] bytes = "7E 09 00 00 09 00 01 23 45 67 89 00 0A 83 73 6D 61 6C 6C 63 68 69 1D 7E".ToHexBytes(); | |||
string json = JT808Serializer.Analyze<JT808Package>(bytes); | |||
string json = JT808Serializer.Analyze(bytes); | |||
} | |||
} | |||
} |
@@ -1,21 +1,31 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessageBody; | |||
using JT808.Protocol.MessagePack; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.Test.JT808_0x0900_BodiesImpl | |||
{ | |||
public class JT808_0x0900_0x83 : JT808_0x0900_BodyBase,IJT808MessagePackFormatter<JT808_0x0900_0x83> | |||
public class JT808_0x0900_0x83 : JT808_0x0900_BodyBase,IJT808MessagePackFormatter<JT808_0x0900_0x83>, IJT808Analyze | |||
{ | |||
/// <summary> | |||
/// 透传内容 | |||
/// </summary> | |||
public string PassthroughContent { get; set; } | |||
public override byte PassthroughType { get; set; } = 0x83; | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
JT808_0x0900_0x83 value = new JT808_0x0900_0x83(); | |||
value.PassthroughContent = reader.ReadRemainStringContent(); | |||
writer.WriteString("透传内容", value.PassthroughContent); | |||
} | |||
public JT808_0x0900_0x83 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_0x0900_0x83 jT808PassthroughType0x83 = new JT808_0x0900_0x83(); | |||
jT808PassthroughType0x83.PassthroughContent = reader.ReadRemainStringContent(); | |||
return jT808PassthroughType0x83; | |||
JT808_0x0900_0x83 value = new JT808_0x0900_0x83(); | |||
value.PassthroughContent = reader.ReadRemainStringContent(); | |||
return value; | |||
} | |||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0x0900_0x83 value, IJT808Config config) | |||
@@ -16,6 +16,7 @@ namespace JT808.Protocol.Test.MessageBody | |||
{ | |||
IJT808Config jT808Config = new DefaultGlobalConfig(); | |||
jT808Config.FormatterFactory.SetMap<JT808_0X8900_Test_BodiesImpl>(); | |||
jT808Config.JT808_0x8900_Custom_Factory.SetMap<JT808_0X8900_Test_BodiesImpl>(); | |||
JT808Serializer = new JT808Serializer(jT808Config); | |||
} | |||
[Fact] | |||
@@ -39,7 +40,7 @@ namespace JT808.Protocol.Test.MessageBody | |||
{ | |||
byte[] bytes = "0B0000303901".ToHexBytes(); | |||
JT808_0x8900 jT808_0X8900 = JT808Serializer.Deserialize<JT808_0x8900>(bytes); | |||
JT808_0X8900_Test_BodiesImpl jT808_0X8900_Test_BodiesImpl = JT808Serializer.Deserialize<JT808_0X8900_Test_BodiesImpl>(jT808_0X8900.PassthroughData); | |||
JT808_0X8900_Test_BodiesImpl jT808_0X8900_Test_BodiesImpl = (JT808_0X8900_Test_BodiesImpl)jT808_0X8900.JT808_0X8900_BodyBase; | |||
Assert.Equal(0x0B, jT808_0X8900.PassthroughType); | |||
Assert.Equal((uint)12345, jT808_0X8900_Test_BodiesImpl.Id); | |||
Assert.Equal(0x01, jT808_0X8900_Test_BodiesImpl.Sex); | |||
@@ -17,7 +17,7 @@ namespace JT808.Protocol.Extensions | |||
} | |||
else | |||
{ | |||
throw new NotImplementedException($"{instance.GetType().FullName} {nameof(IJT808Analyze)}"); | |||
throw new NotImplementedException($"Not Implemented {instance.GetType().FullName} {nameof(IJT808Analyze)}"); | |||
} | |||
} | |||
} | |||
@@ -23,6 +23,8 @@ namespace JT808.Protocol.Interfaces | |||
JT808_0X0200_Factory = new JT808_0x0200_Factory(); | |||
JT808_0X8103_Custom_Factory = new JT808_0x8103_Custom_Factory(); | |||
JT808_0X8103_Factory = new JT808_0x8103_Factory(); | |||
JT808_0x0900_Custom_Factory = new JT808_0x0900_Custom_Factory(); | |||
JT808_0x8900_Custom_Factory = new JT808_0x8900_Custom_Factory(); | |||
TerminalPhoneNoLength = 12; | |||
Trim = true; | |||
} | |||
@@ -40,6 +42,8 @@ namespace JT808.Protocol.Interfaces | |||
public virtual IJT808_0x8103_Factory JT808_0X8103_Factory { get; set; } | |||
public virtual int TerminalPhoneNoLength { get; set; } | |||
public virtual bool Trim { get; set; } | |||
public virtual IJT808_0x0900_Custom_Factory JT808_0x0900_Custom_Factory { get; set; } | |||
public virtual IJT808_0x8900_Custom_Factory JT808_0x8900_Custom_Factory { get; set; } | |||
public virtual IJT808Config Register(params Assembly[] externalAssemblies) | |||
{ | |||
if (externalAssemblies != null) | |||
@@ -52,6 +56,8 @@ namespace JT808.Protocol.Interfaces | |||
JT808_0X0200_Custom_Factory.Register(easb); | |||
JT808_0X8103_Factory.Register(easb); | |||
JT808_0X8103_Custom_Factory.Register(easb); | |||
JT808_0x0900_Custom_Factory.Register(easb); | |||
JT808_0x8900_Custom_Factory.Register(easb); | |||
} | |||
} | |||
return this; | |||
@@ -49,6 +49,14 @@ namespace JT808.Protocol | |||
/// </summary> | |||
IJT808_0x8103_Factory JT808_0X8103_Factory { get; set; } | |||
/// <summary> | |||
///数据上行透传工厂 | |||
/// </summary> | |||
IJT808_0x0900_Custom_Factory JT808_0x0900_Custom_Factory { get; set; } | |||
/// <summary> | |||
///数据下行透传工厂 | |||
/// </summary> | |||
IJT808_0x8900_Custom_Factory JT808_0x8900_Custom_Factory { get; set; } | |||
/// <summary> | |||
/// 统一编码 | |||
/// </summary> | |||
Encoding Encoding { get; set; } | |||
@@ -0,0 +1,13 @@ | |||
using JT808.Protocol.MessageBody; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Protocol.Interfaces | |||
{ | |||
public interface IJT808_0x0900_Custom_Factory : IJT808ExternalRegister | |||
{ | |||
IDictionary<byte, object> Map { get; } | |||
IJT808_0x0900_Custom_Factory SetMap<TJT808_0x0900_BodyBase>() where TJT808_0x0900_BodyBase : JT808_0x0900_BodyBase; | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
using JT808.Protocol.MessageBody; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Protocol.Interfaces | |||
{ | |||
public interface IJT808_0x8900_Custom_Factory : IJT808ExternalRegister | |||
{ | |||
IDictionary<byte, object> Map { get; } | |||
IJT808_0x8900_Custom_Factory SetMap<TJT808_0x8900_BodyBase>() where TJT808_0x8900_BodyBase : JT808_0x8900_BodyBase; | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessageBody; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Text; | |||
namespace JT808.Protocol.Internal | |||
{ | |||
class JT808_0x0900_Custom_Factory : IJT808_0x0900_Custom_Factory | |||
{ | |||
public IDictionary<byte, object> Map { get; } | |||
public JT808_0x0900_Custom_Factory() | |||
{ | |||
Map = new Dictionary<byte, object>(); | |||
} | |||
public void Register(Assembly externalAssembly) | |||
{ | |||
var types = externalAssembly.GetTypes().Where(w => w.BaseType == typeof(JT808_0x0200_CustomBodyBase)).ToList(); | |||
foreach(var type in types) | |||
{ | |||
var instance = Activator.CreateInstance(type); | |||
var attachid = (byte)type.GetProperty(nameof(JT808_0x0200_CustomBodyBase.AttachInfoId)).GetValue(instance); | |||
if (Map.ContainsKey(attachid)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {attachid} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(attachid, instance); | |||
} | |||
} | |||
} | |||
public IJT808_0x0900_Custom_Factory SetMap<TJT808_0x0900_Custom_Factory>() where TJT808_0x0900_Custom_Factory : JT808_0x0900_BodyBase | |||
{ | |||
Type type = typeof(TJT808_0x0900_Custom_Factory); | |||
var instance = Activator.CreateInstance(type); | |||
var passthroughType = (byte)type.GetProperty(nameof(JT808_0x0900_BodyBase.PassthroughType)).GetValue(instance); | |||
if (Map.ContainsKey(passthroughType)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {passthroughType} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(passthroughType, instance); | |||
} | |||
return this; | |||
} | |||
} | |||
} |
@@ -0,0 +1,54 @@ | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessageBody; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Text; | |||
namespace JT808.Protocol.Internal | |||
{ | |||
class JT808_0x8900_Custom_Factory : IJT808_0x8900_Custom_Factory | |||
{ | |||
public IDictionary<byte, object> Map { get; } | |||
public JT808_0x8900_Custom_Factory() | |||
{ | |||
Map = new Dictionary<byte, object>(); | |||
} | |||
public void Register(Assembly externalAssembly) | |||
{ | |||
var types = externalAssembly.GetTypes().Where(w => w.BaseType == typeof(JT808_0x0200_CustomBodyBase)).ToList(); | |||
foreach(var type in types) | |||
{ | |||
var instance = Activator.CreateInstance(type); | |||
var attachid = (byte)type.GetProperty(nameof(JT808_0x0200_CustomBodyBase.AttachInfoId)).GetValue(instance); | |||
if (Map.ContainsKey(attachid)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {attachid} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(attachid, instance); | |||
} | |||
} | |||
} | |||
public IJT808_0x8900_Custom_Factory SetMap<TJT808_0x8900_Custom_Factory>() where TJT808_0x8900_Custom_Factory : JT808_0x8900_BodyBase | |||
{ | |||
Type type = typeof(TJT808_0x8900_Custom_Factory); | |||
var instance = Activator.CreateInstance(type); | |||
var passthroughType = (byte)type.GetProperty(nameof(JT808_0x8900_BodyBase.PassthroughType)).GetValue(instance); | |||
if (Map.ContainsKey(passthroughType)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {passthroughType} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(passthroughType, instance); | |||
} | |||
return this; | |||
} | |||
} | |||
} |
@@ -14,7 +14,7 @@ | |||
<licenseUrl>https://github.com/SmallChi/JT808/blob/master/LICENSE</licenseUrl> | |||
<license>https://github.com/SmallChi/JT808/blob/master/LICENSE</license> | |||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||
<Version>2.2.6</Version> | |||
<Version>2.2.7</Version> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
</PropertyGroup> | |||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||
@@ -2654,6 +2654,16 @@ | |||
设置终端参数工厂 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.IJT808Config.JT808_0x0900_Custom_Factory"> | |||
<summary> | |||
数据上行透传工厂 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.IJT808Config.JT808_0x8900_Custom_Factory"> | |||
<summary> | |||
数据下行透传工厂 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.IJT808Config.Encoding"> | |||
<summary> | |||
统一编码 | |||
@@ -4243,6 +4253,11 @@ | |||
数据上行透传 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.MessageBody.JT808_0x0900_BodyBase.PassthroughType"> | |||
<summary> | |||
透传消息类型 | |||
</summary> | |||
</member> | |||
<member name="T:JT808.Protocol.MessageBody.JT808_0x0901"> | |||
<summary> | |||
数据压缩上报 | |||
@@ -6678,6 +6693,12 @@ | |||
数据下行透传 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.MessageBody.JT808_0x8900_BodyBase.PassthroughType"> | |||
<summary> | |||
透传消息类型 | |||
透传消息类型定义见 表 93 | |||
</summary> | |||
</member> | |||
<member name="T:JT808.Protocol.MessageBody.JT808_0x8A00"> | |||
<summary> | |||
平台RSA公钥 | |||
@@ -31,19 +31,41 @@ namespace JT808.Protocol.MessageBody | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
//todo:待扩展完善 | |||
JT808_0x0900 value = new JT808_0x0900(); | |||
value.PassthroughType = reader.ReadByte(); | |||
writer.WriteNumber($"[{value.PassthroughType.ReadNumber()}]透传消息类型", value.PassthroughType); | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
writer.WriteString("透传消息内容", value.PassthroughData.ToHexString()); | |||
if (config.JT808_0x0900_Custom_Factory.Map.TryGetValue(value.PassthroughType, out var instance)) | |||
{ | |||
writer.WriteStartObject("数据上行对象"); | |||
try | |||
{ | |||
instance.Analyze(ref reader, writer, config); | |||
} | |||
catch (System.Exception ex) | |||
{ | |||
writer.WriteString("错误信息", $"{ex.Message}-{ex.StackTrace}"); | |||
} | |||
writer.WriteEndObject(); | |||
} | |||
else | |||
{ | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
writer.WriteString("透传消息内容", value.PassthroughData.ToHexString()); | |||
} | |||
} | |||
public JT808_0x0900 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_0x0900 value = new JT808_0x0900(); | |||
value.PassthroughType = reader.ReadByte(); | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
if(config.JT808_0x0900_Custom_Factory.Map.TryGetValue(value.PassthroughType,out var instance)) | |||
{ | |||
value.JT808_0x0900_BodyBase = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(instance, ref reader, config); | |||
} | |||
else | |||
{ | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
} | |||
return value; | |||
} | |||
@@ -5,6 +5,9 @@ | |||
/// </summary> | |||
public abstract class JT808_0x0900_BodyBase | |||
{ | |||
/// <summary> | |||
/// 透传消息类型 | |||
/// </summary> | |||
public abstract byte PassthroughType { get; set; } | |||
} | |||
} |
@@ -31,10 +31,17 @@ namespace JT808.Protocol.MessageBody | |||
public JT808_0x8900 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_0x8900 jT808_0X8900 = new JT808_0x8900(); | |||
jT808_0X8900.PassthroughType = reader.ReadByte(); | |||
jT808_0X8900.PassthroughData = reader.ReadContent().ToArray(); | |||
return jT808_0X8900; | |||
JT808_0x8900 value = new JT808_0x8900(); | |||
value.PassthroughType = reader.ReadByte(); | |||
if (config.JT808_0x8900_Custom_Factory.Map.TryGetValue(value.PassthroughType, out var instance)) | |||
{ | |||
value.JT808_0X8900_BodyBase = JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(instance, ref reader, config); | |||
} | |||
else | |||
{ | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
} | |||
return value; | |||
} | |||
public void Serialize(ref JT808MessagePackWriter writer, JT808_0x8900 value, IJT808Config config) | |||
@@ -45,11 +52,26 @@ namespace JT808.Protocol.MessageBody | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
JT808_0x8900 jT808_0X8900 = new JT808_0x8900(); | |||
jT808_0X8900.PassthroughType = reader.ReadByte(); | |||
jT808_0X8900.PassthroughData = reader.ReadContent().ToArray(); | |||
writer.WriteNumber($"[{jT808_0X8900.PassthroughType.ReadNumber()}]透传消息类型", jT808_0X8900.PassthroughType); | |||
writer.WriteString($"透传消息内容", jT808_0X8900.PassthroughData.ToHexString()); | |||
JT808_0x8900 value = new JT808_0x8900(); | |||
value.PassthroughType = reader.ReadByte(); | |||
if (config.JT808_0x8900_Custom_Factory.Map.TryGetValue(value.PassthroughType, out var instance)) | |||
{ | |||
writer.WriteStartObject("数据下行对象"); | |||
try | |||
{ | |||
instance.Analyze(ref reader, writer, config); | |||
} | |||
catch (System.Exception ex) | |||
{ | |||
writer.WriteString("错误信息", $"{ex.Message}-{ex.StackTrace}"); | |||
} | |||
writer.WriteEndObject(); | |||
} | |||
else | |||
{ | |||
value.PassthroughData = reader.ReadContent().ToArray(); | |||
writer.WriteString("透传消息内容", value.PassthroughData.ToHexString()); | |||
} | |||
} | |||
} | |||
} |
@@ -5,6 +5,10 @@ | |||
/// </summary> | |||
public abstract class JT808_0x8900_BodyBase | |||
{ | |||
/// <summary> | |||
/// 透传消息类型 | |||
/// 透传消息类型定义见 表 93 | |||
/// </summary> | |||
public abstract byte PassthroughType { get; set; } | |||
} | |||
} |