diff --git a/src/JT808.Protocol.Test/MessageBody/JT808_0x8500Test.cs b/src/JT808.Protocol.Test/MessageBody/JT808_0x8500Test.cs index 2e4d730..c9a8f46 100644 --- a/src/JT808.Protocol.Test/MessageBody/JT808_0x8500Test.cs +++ b/src/JT808.Protocol.Test/MessageBody/JT808_0x8500Test.cs @@ -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(); + jT808Config.JT808_0x8500_2019_Factory.SetMap(); jT808Config.FormatterFactory.SetMap(); + jT808Config.FormatterFactory.SetMap(); JT808Serializer = new JT808Serializer(jT808Config); } [Fact] @@ -71,12 +76,11 @@ namespace JT808.Protocol.Test.MessageBody Dictionary keys = new Dictionary(); keys.Add(0x0001, 1); keys.Add(0xF001, 1); - var span = jT808_0X8500.ControlTypeBuffer.AsSpan(); - JT808_0x8500_0x0001 jT808_0x8500_0x0001 = JT808Serializer.Deserialize(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(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 /// /// 自定义控制类型 /// - public class JT808_0x8500_0xF001 : JT808_0x8500_ControlType, IJT808MessagePackFormatter + public class JT808_0x8500_0xF001 : JT808_0x8500_ControlType, IJT808MessagePackFormatter, 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(); diff --git a/src/JT808.Protocol/Interfaces/GlobalConfigBase.cs b/src/JT808.Protocol/Interfaces/GlobalConfigBase.cs index defff86..76d9e48 100644 --- a/src/JT808.Protocol/Interfaces/GlobalConfigBase.cs +++ b/src/JT808.Protocol/Interfaces/GlobalConfigBase.cs @@ -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; diff --git a/src/JT808.Protocol/Interfaces/IJT808Config.cs b/src/JT808.Protocol/Interfaces/IJT808Config.cs index 6a83124..2d0b1ad 100644 --- a/src/JT808.Protocol/Interfaces/IJT808Config.cs +++ b/src/JT808.Protocol/Interfaces/IJT808Config.cs @@ -57,6 +57,10 @@ namespace JT808.Protocol /// IJT808_0x8900_Custom_Factory JT808_0x8900_Custom_Factory { get; set; } /// + /// 控制类型工厂 + /// + IJT808_0x8500_2019_Factory JT808_0x8500_2019_Factory { get; set; } + /// /// 统一编码 /// Encoding Encoding { get; set; } diff --git a/src/JT808.Protocol/Interfaces/IJT808_0x8500_2019_Factory.cs b/src/JT808.Protocol/Interfaces/IJT808_0x8500_2019_Factory.cs new file mode 100644 index 0000000..a14bd47 --- /dev/null +++ b/src/JT808.Protocol/Interfaces/IJT808_0x8500_2019_Factory.cs @@ -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 Map { get; } + IJT808_0x8500_2019_Factory SetMap() where TJT808_0x8500_ControlType : JT808_0x8500_ControlType; + } +} diff --git a/src/JT808.Protocol/Internal/DefaultGlobalConfig.cs b/src/JT808.Protocol/Internal/DefaultGlobalConfig.cs index 36c0215..565b380 100644 --- a/src/JT808.Protocol/Internal/DefaultGlobalConfig.cs +++ b/src/JT808.Protocol/Internal/DefaultGlobalConfig.cs @@ -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 { diff --git a/src/JT808.Protocol/Internal/JT808_0x8500_2019_Factory.cs b/src/JT808.Protocol/Internal/JT808_0x8500_2019_Factory.cs new file mode 100644 index 0000000..d7f2196 --- /dev/null +++ b/src/JT808.Protocol/Internal/JT808_0x8500_2019_Factory.cs @@ -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 Map { get; } + + public JT808_0x8500_2019_Factory() + { + Map = new Dictionary(); + } + + 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() 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; + } + } +} diff --git a/src/JT808.Protocol/JT808.Protocol.xml b/src/JT808.Protocol/JT808.Protocol.xml index a094b5a..25507c8 100644 --- a/src/JT808.Protocol/JT808.Protocol.xml +++ b/src/JT808.Protocol/JT808.Protocol.xml @@ -2664,6 +2664,11 @@ 数据下行透传工厂 + + + 控制类型工厂 + + 统一编码 diff --git a/src/JT808.Protocol/MessageBody/JT808_0x8203.cs b/src/JT808.Protocol/MessageBody/JT808_0x8203.cs index 7b48349..afe89fd 100644 --- a/src/JT808.Protocol/MessageBody/JT808_0x8203.cs +++ b/src/JT808.Protocol/MessageBody/JT808_0x8203.cs @@ -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 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(); } } } diff --git a/src/JT808.Protocol/MessageBody/JT808_0x8300.cs b/src/JT808.Protocol/MessageBody/JT808_0x8300.cs index 572a2b8..5dc16f1 100644 --- a/src/JT808.Protocol/MessageBody/JT808_0x8300.cs +++ b/src/JT808.Protocol/MessageBody/JT808_0x8300.cs @@ -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 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); } } } diff --git a/src/JT808.Protocol/MessageBody/JT808_0x8500.cs b/src/JT808.Protocol/MessageBody/JT808_0x8500.cs index a8e3300..96161e1 100644 --- a/src/JT808.Protocol/MessageBody/JT808_0x8500.cs +++ b/src/JT808.Protocol/MessageBody/JT808_0x8500.cs @@ -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 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(); + 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 {