@@ -1,11 +1,13 @@ | |||
using JT808.Protocol.Enums; | |||
using JT808.Protocol.Extensions; | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.Internal; | |||
using JT808.Protocol.MessageBody; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text.Json; | |||
using Xunit; | |||
namespace JT808.Protocol.Test.MessageBody | |||
@@ -17,7 +19,10 @@ namespace JT808.Protocol.Test.MessageBody | |||
public JT808_0x8500Test() | |||
{ | |||
IJT808Config jT808Config = new DefaultGlobalConfig(); | |||
jT808Config.JT808_0x8500_2019_Factory.SetMap<JT808_0x8500_0xF001>(); | |||
jT808Config.JT808_0x8500_2019_Factory.SetMap<JT808_0x8500_0x0001>(); | |||
jT808Config.FormatterFactory.SetMap<JT808_0x8500_0xF001>(); | |||
jT808Config.FormatterFactory.SetMap<JT808_0x8500_0x0001>(); | |||
JT808Serializer = new JT808Serializer(jT808Config); | |||
} | |||
[Fact] | |||
@@ -71,12 +76,11 @@ namespace JT808.Protocol.Test.MessageBody | |||
Dictionary<ushort, int> keys = new Dictionary<ushort, int>(); | |||
keys.Add(0x0001, 1); | |||
keys.Add(0xF001, 1); | |||
var span = jT808_0X8500.ControlTypeBuffer.AsSpan(); | |||
JT808_0x8500_0x0001 jT808_0x8500_0x0001 = JT808Serializer.Deserialize<JT808_0x8500_0x0001>(span.Slice(0,3), JT808Version.JTT2019); | |||
JT808_0x8500_0x0001 jT808_0x8500_0x0001 = (JT808_0x8500_0x0001)jT808_0X8500.ControlTypes[0]; | |||
Assert.Equal(0x0001, jT808_0x8500_0x0001.ControlTypeId); | |||
Assert.Equal(0, jT808_0x8500_0x0001.ControlTypeParameter); | |||
JT808_0x8500_0xF001 jT808_0x8500_0xF001 = JT808Serializer.Deserialize<JT808_0x8500_0xF001>(span.Slice(3,3), JT808Version.JTT2019); | |||
JT808_0x8500_0xF001 jT808_0x8500_0xF001 = (JT808_0x8500_0xF001)jT808_0X8500.ControlTypes[1]; | |||
Assert.Equal(0xF001, jT808_0x8500_0xF001.ControlTypeId); | |||
Assert.Equal(1, jT808_0x8500_0xF001.ControlTypeParameter); | |||
} | |||
@@ -92,12 +96,21 @@ namespace JT808.Protocol.Test.MessageBody | |||
/// <summary> | |||
/// 自定义控制类型 | |||
/// </summary> | |||
public class JT808_0x8500_0xF001 : JT808_0x8500_ControlType, IJT808MessagePackFormatter<JT808_0x8500_0xF001> | |||
public class JT808_0x8500_0xF001 : JT808_0x8500_ControlType, IJT808MessagePackFormatter<JT808_0x8500_0xF001>, IJT808Analyze | |||
{ | |||
public override ushort ControlTypeId { get; set; } = 0xF001; | |||
public byte ControlTypeParameter { get; set; } | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
JT808_0x8500_0xF001 value = new JT808_0x8500_0xF001(); | |||
value.ControlTypeId = reader.ReadUInt16(); | |||
writer.WriteNumber($"[{ value.ControlTypeId.ReadNumber()}]控制类型Id", value.ControlTypeId); | |||
value.ControlTypeParameter = reader.ReadByte(); | |||
writer.WriteNumber($"[{ value.ControlTypeParameter.ReadNumber()}]控制类型参数", value.ControlTypeParameter); | |||
} | |||
public JT808_0x8500_0xF001 Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_0x8500_0xF001 value = new JT808_0x8500_0xF001(); | |||
@@ -25,6 +25,7 @@ namespace JT808.Protocol.Interfaces | |||
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(); | |||
JT808_0x8500_2019_Factory = new JT808_0x8500_2019_Factory(); | |||
TerminalPhoneNoLength = 12; | |||
Trim = true; | |||
} | |||
@@ -44,6 +45,7 @@ namespace JT808.Protocol.Interfaces | |||
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 IJT808_0x8500_2019_Factory JT808_0x8500_2019_Factory { get; set; } | |||
public virtual IJT808Config Register(params Assembly[] externalAssemblies) | |||
{ | |||
if (externalAssemblies != null) | |||
@@ -58,6 +60,7 @@ namespace JT808.Protocol.Interfaces | |||
JT808_0X8103_Custom_Factory.Register(easb); | |||
JT808_0x0900_Custom_Factory.Register(easb); | |||
JT808_0x8900_Custom_Factory.Register(easb); | |||
JT808_0x8500_2019_Factory.Register(easb); | |||
} | |||
} | |||
return this; | |||
@@ -57,6 +57,10 @@ namespace JT808.Protocol | |||
/// </summary> | |||
IJT808_0x8900_Custom_Factory JT808_0x8900_Custom_Factory { get; set; } | |||
/// <summary> | |||
/// 控制类型工厂 | |||
/// </summary> | |||
IJT808_0x8500_2019_Factory JT808_0x8500_2019_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_0x8500_2019_Factory : IJT808ExternalRegister | |||
{ | |||
IDictionary<ushort, object> Map { get; } | |||
IJT808_0x8500_2019_Factory SetMap<TJT808_0x8500_ControlType>() where TJT808_0x8500_ControlType : JT808_0x8500_ControlType; | |||
} | |||
} |
@@ -1,10 +1,4 @@ | |||
using JT808.Protocol.Enums; | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.Internal; | |||
using System; | |||
using System.Reflection; | |||
using System.Text; | |||
using JT808.Protocol.Interfaces; | |||
namespace JT808.Protocol.Internal | |||
{ | |||
@@ -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_0x8500_2019_Factory : IJT808_0x8500_2019_Factory | |||
{ | |||
public IDictionary<ushort, object> Map { get; } | |||
public JT808_0x8500_2019_Factory() | |||
{ | |||
Map = new Dictionary<ushort, object>(); | |||
} | |||
public void Register(Assembly externalAssembly) | |||
{ | |||
var types = externalAssembly.GetTypes().Where(w => w.BaseType == typeof(JT808_0x8500_ControlType)).ToList(); | |||
foreach(var type in types) | |||
{ | |||
var instance = Activator.CreateInstance(type); | |||
var controlTypeId = (ushort)type.GetProperty(nameof(JT808_0x8500_ControlType.ControlTypeId)).GetValue(instance); | |||
if (Map.ContainsKey(controlTypeId)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {controlTypeId} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(controlTypeId, instance); | |||
} | |||
} | |||
} | |||
public IJT808_0x8500_2019_Factory SetMap<TJT808_0x8500_ControlType>() where TJT808_0x8500_ControlType : JT808_0x8500_ControlType | |||
{ | |||
Type type = typeof(TJT808_0x8500_ControlType); | |||
var instance = Activator.CreateInstance(type); | |||
var controlTypeId = (ushort)type.GetProperty(nameof(JT808_0x8500_ControlType.ControlTypeId)).GetValue(instance); | |||
if (Map.ContainsKey(controlTypeId)) | |||
{ | |||
throw new ArgumentException($"{type.FullName} {controlTypeId} An element with the same key already exists."); | |||
} | |||
else | |||
{ | |||
Map.Add(controlTypeId, instance); | |||
} | |||
return this; | |||
} | |||
} | |||
} |
@@ -2664,6 +2664,11 @@ | |||
数据下行透传工厂 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.IJT808Config.JT808_0x8500_2019_Factory"> | |||
<summary> | |||
控制类型工厂 | |||
</summary> | |||
</member> | |||
<member name="P:JT808.Protocol.IJT808Config.Encoding"> | |||
<summary> | |||
统一编码 | |||
@@ -2,6 +2,7 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody | |||
@@ -45,6 +46,20 @@ namespace JT808.Protocol.MessageBody | |||
writer.WriteNumber($"[{ value.AlarmMsgNum.ReadNumber()}]报警消息流水号", value.AlarmMsgNum); | |||
value.ManualConfirmAlarmType = reader.ReadUInt32(); | |||
writer.WriteNumber($"[{ value.ManualConfirmAlarmType.ReadNumber()}]人工确认报警类型", value.ManualConfirmAlarmType); | |||
ReadOnlySpan<char> manualConfirmAlarmTypeBits = Convert.ToString(value.ManualConfirmAlarmType, 2).PadLeft(32, '0').AsSpan(); | |||
writer.WriteStartObject($"人工确认报警对象[{manualConfirmAlarmTypeBits.ToString()}]"); | |||
writer.WriteString("[bit29~bit31]保留", manualConfirmAlarmTypeBits.Slice(29,3).ToString()); | |||
writer.WriteString($"[bit28]{manualConfirmAlarmTypeBits[28]}","确认车辆非法位移报警"); | |||
writer.WriteString($"[bit27]{manualConfirmAlarmTypeBits[27]}", "确认车辆非法点火报警"); | |||
writer.WriteString($"[bit23~bit26]保留", manualConfirmAlarmTypeBits.Slice(23, 4).ToString()); | |||
writer.WriteString($"[bit22]{manualConfirmAlarmTypeBits[22]}", "确认路段行驶时间不足/过长报警"); | |||
writer.WriteString($"[bit21]{manualConfirmAlarmTypeBits[21]}", "确认进出路线报警"); | |||
writer.WriteString($"[bit20]{manualConfirmAlarmTypeBits[20]}", "确认进出区域报警"); | |||
writer.WriteString($"[bit4~bit19]保留", manualConfirmAlarmTypeBits.Slice(4, 16).ToString()); | |||
writer.WriteString($"[bit3]{manualConfirmAlarmTypeBits[3]}", "确认危险预警"); | |||
writer.WriteString($"[bit1~bit2]保留", manualConfirmAlarmTypeBits.Slice(1, 2).ToString()); | |||
writer.WriteString($"[bit0]{manualConfirmAlarmTypeBits[0]}", "确认紧急报警"); | |||
writer.WriteEndObject(); | |||
} | |||
} | |||
} |
@@ -4,6 +4,7 @@ using JT808.Protocol.Extensions; | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody | |||
@@ -55,17 +56,53 @@ namespace JT808.Protocol.MessageBody | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
JT808_0x8300 jT808_0X8300 = new JT808_0x8300(); | |||
jT808_0X8300.TextFlag = reader.ReadByte(); | |||
writer.WriteNumber($"[{ jT808_0X8300.TextFlag.ReadNumber()}]文本信息标志位", jT808_0X8300.TextFlag); | |||
JT808_0x8300 value = new JT808_0x8300(); | |||
value.TextFlag = reader.ReadByte(); | |||
writer.WriteNumber($"[{ value.TextFlag.ReadNumber()}]文本信息标志位", value.TextFlag); | |||
ReadOnlySpan<char> textFlagBits = Convert.ToString(value.TextFlag, 2).PadLeft(8, '0').AsSpan(); | |||
if (reader.Version == JT808Version.JTT2019) | |||
{ | |||
jT808_0X8300.TextType = reader.ReadByte(); | |||
writer.WriteNumber($"[{ jT808_0X8300.TextType.ReadNumber()}]文本类型-{(jT808_0X8300.TextType==1? "通知":"服务")}", jT808_0X8300.TextType); | |||
writer.WriteStartObject($"文本信息标志对象[{textFlagBits.ToString()}]"); | |||
writer.WriteString($"[bit6~-bit7]保留", textFlagBits.Slice(6, 2).ToString()); | |||
writer.WriteString($"[bit5]{textFlagBits[5]}", textFlagBits[5] == '0' ? "中心导航信息" : "CAN故障码信息"); | |||
writer.WriteString($"[bit4]{textFlagBits[4]}", "-"); | |||
writer.WriteString($"[bit3]{textFlagBits[3]}", "终端TTS播读"); | |||
writer.WriteString($"[bit2]{textFlagBits[2]}", "终端显示器显示"); | |||
var bit0And1= textFlagBits.Slice(0, 2).ToString(); | |||
switch (bit0And1) | |||
{ | |||
case "01": | |||
writer.WriteString($"[bit0]{textFlagBits[0]}", "服务"); | |||
break; | |||
case "10": | |||
writer.WriteString($"[bit0]{textFlagBits[0]}", "紧急"); | |||
break; | |||
case "11": | |||
writer.WriteString($"[bit0]{textFlagBits[0]}", "通知"); | |||
break; | |||
case "00": | |||
writer.WriteString($"[bit0]{textFlagBits[0]}", "保留"); | |||
break; | |||
} | |||
writer.WriteEndObject(); | |||
value.TextType = reader.ReadByte(); | |||
writer.WriteNumber($"[{ value.TextType.ReadNumber()}]文本类型-{(value.TextType==1? "通知":"服务")}", value.TextType); | |||
} | |||
else | |||
{ | |||
writer.WriteStartObject($"文本信息标志对象[{textFlagBits.ToString()}]"); | |||
writer.WriteString($"[bit6~-bit7]保留", textFlagBits.Slice(6, 2).ToString()); | |||
writer.WriteString($"[bit5]{textFlagBits[5]}", textFlagBits[5] == '0' ? "中心导航信息" : "CAN故障码信息"); | |||
writer.WriteString($"[bit4]{textFlagBits[4]}", "广告屏显示"); | |||
writer.WriteString($"[bit3]{textFlagBits[3]}", "终端TTS播读"); | |||
writer.WriteString($"[bit2]{textFlagBits[2]}", "终端显示器显示"); | |||
writer.WriteString($"[bit1]{textFlagBits[1]}", "保留"); | |||
writer.WriteString($"[bit0]{textFlagBits[0]}", "紧急"); | |||
writer.WriteEndObject(); | |||
} | |||
var txtBuffer = reader.ReadVirtualArray(reader.ReadCurrentRemainContentLength()).ToArray(); | |||
jT808_0X8300.TextInfo = reader.ReadRemainStringContent(); | |||
writer.WriteString($"[{txtBuffer.ToHexString()}]答案内容", jT808_0X8300.TextInfo); | |||
value.TextInfo = reader.ReadRemainStringContent(); | |||
writer.WriteString($"[{txtBuffer.ToHexString()}]答案内容", value.TextInfo); | |||
} | |||
} | |||
} |
@@ -3,6 +3,7 @@ using JT808.Protocol.Extensions; | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text.Json; | |||
@@ -40,16 +41,35 @@ namespace JT808.Protocol.MessageBody | |||
JT808_0x8500 value = new JT808_0x8500(); | |||
if (reader.Version == JT808Version.JTT2019) | |||
{ | |||
value.ControlTypeCount = reader.ReadUInt16(); | |||
value.ControlTypeCount = reader.ReadUInt16(); | |||
writer.WriteNumber($"[{ value.ControlTypeCount.ReadNumber()}]控制类型数量", value.ControlTypeCount); | |||
//todo:待完善 | |||
value.ControlTypeBuffer = reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray(); | |||
writer.WriteString($"控制类型", value.ControlTypeBuffer.ToHexString()); | |||
writer.WriteStartArray($"控制类型集合"); | |||
while (reader.ReadCurrentRemainContentLength() > 0) | |||
{ | |||
writer.WriteStartObject(); | |||
var controlTypeId = reader.ReadVirtualUInt16(); | |||
if (config.JT808_0x8500_2019_Factory.Map.TryGetValue(controlTypeId, out object instance)) | |||
{ | |||
instance.Analyze(ref reader, writer, config); | |||
} | |||
else | |||
{ | |||
value.ControlTypeBuffer = reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray(); | |||
writer.WriteString($"控制类型", value.ControlTypeBuffer.ToHexString()); | |||
} | |||
writer.WriteEndObject(); | |||
} | |||
writer.WriteEndArray(); | |||
} | |||
else | |||
{ | |||
value.ControlFlag = reader.ReadByte(); | |||
writer.WriteNumber($"[{ value.ControlFlag.ReadNumber()}]控制标志", value.ControlFlag); | |||
ReadOnlySpan<char> controlFlagBits = Convert.ToString(value.ControlFlag, 2).PadLeft(8, '0').AsSpan(); | |||
writer.WriteStartObject($"控制标志对象[{controlFlagBits.ToString()}]"); | |||
writer.WriteString("[bit1~bit7]保留", controlFlagBits.Slice(1, 7).ToString()); | |||
writer.WriteString("[bit0]", controlFlagBits[0]=='0'? "车门解锁" : "车门加锁"); | |||
writer.WriteEndObject(); | |||
} | |||
} | |||
@@ -59,7 +79,19 @@ namespace JT808.Protocol.MessageBody | |||
if(reader.Version== JT808Version.JTT2019) | |||
{ | |||
value.ControlTypeCount = reader.ReadUInt16(); | |||
value.ControlTypeBuffer = reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray(); | |||
value.ControlTypes = new List<JT808_0x8500_ControlType>(); | |||
while (reader.ReadCurrentRemainContentLength() > 0) | |||
{ | |||
var controlTypeId = reader.ReadVirtualUInt16(); | |||
if (config.JT808_0x8500_2019_Factory.Map.TryGetValue(controlTypeId, out object instance)) | |||
{ | |||
value.ControlTypes.Add(JT808MessagePackFormatterResolverExtensions.JT808DynamicDeserialize(instance, ref reader, config)); | |||
} | |||
else | |||
{ | |||
value.ControlTypeBuffer = reader.ReadArray(reader.ReadCurrentRemainContentLength()).ToArray(); | |||
} | |||
} | |||
} | |||
else | |||
{ | |||