@@ -61,6 +61,10 @@ namespace JT808.Protocol | |||
/// </summary> | |||
IJT808_0x8500_2019_Factory JT808_0x8500_2019_Factory { get; set; } | |||
/// <summary> | |||
/// 记录仪工厂 | |||
/// </summary> | |||
IJT808_Recorder_Factory IJT808_Recorder_Factory { get; set; } | |||
/// <summary> | |||
/// 统一编码 | |||
/// </summary> | |||
Encoding Encoding { get; set; } | |||
@@ -0,0 +1,16 @@ | |||
using JT808.Protocol.MessageBody.Recorder; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Protocol.Interfaces | |||
{ | |||
/// <summary> | |||
/// 记录仪工厂 | |||
/// </summary> | |||
public interface IJT808_Recorder_Factory : IJT808ExternalRegister | |||
{ | |||
IDictionary<byte, JT808_RecorderBody> Map { get; } | |||
IJT808_Recorder_Factory SetMap<TJT808_RecorderBody>() ; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
namespace JT808.Protocol.MessageBody.Recorder | |||
{ | |||
/// <summary> | |||
/// 记录仪数据体 | |||
/// </summary> | |||
public abstract class JT808_RecorderBody : IJT808Description | |||
{ | |||
/// <summary> | |||
/// 命令字 | |||
/// </summary> | |||
public abstract byte CommandId { get; } | |||
public abstract JT808_RecorderBody Deserialize(ref JT808MessagePackReader reader, IJT808Config config); | |||
public abstract void Serialize(ref JT808MessagePackWriter writer, JT808_RecorderBody value, IJT808Config config); | |||
/// <summary> | |||
/// 跳过数据体序列化 | |||
/// 默认不跳过 | |||
/// 当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||
/// </summary> | |||
public virtual bool SkipSerialization { get; set; } = false; | |||
public abstract string Description { get; } | |||
} | |||
} |
@@ -0,0 +1,41 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody.Recorder | |||
{ | |||
public class JT808_RecorderHeader: IJT808MessagePackFormatter<JT808_RecorderHeader>, IJT808Analyze | |||
{ | |||
/// <summary> | |||
/// 命令字 | |||
/// </summary> | |||
public byte CommandId { get; set; } | |||
/// <summary> | |||
/// 数据块长度 | |||
/// </summary> | |||
public ushort DataLength { get; set; } | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
public JT808_RecorderHeader Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_RecorderHeader value = new JT808_RecorderHeader(); | |||
value.CommandId = reader.ReadByte(); | |||
value.DataLength = reader.ReadUInt16(); | |||
return value; | |||
} | |||
public void Serialize(ref JT808MessagePackWriter writer, JT808_RecorderHeader value, IJT808Config config) | |||
{ | |||
writer.WriteByte(value.CommandId); | |||
writer.WriteUInt16(value.DataLength); | |||
} | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody.Recorder | |||
{ | |||
/// <summary> | |||
/// 采集记录仪执行标准版本 | |||
/// 返回:记录仪执行标准的年号及修改单号 | |||
/// </summary> | |||
public class JT808_Recorder_Down_0x00 : JT808_RecorderBody | |||
{ | |||
public override byte CommandId =>0x00; | |||
public override string Description => "采集记录仪执行标准版本"; | |||
public override bool SkipSerialization { get; set; } = true; | |||
public override JT808_RecorderBody Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
public override void Serialize(ref JT808MessagePackWriter writer, JT808_RecorderBody value, IJT808Config config) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
} | |||
} |
@@ -0,0 +1,52 @@ | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Buffers.Binary; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody.Recorder | |||
{ | |||
/// <summary> | |||
/// 采集记录仪执行标准版本 | |||
/// 返回:记录仪执行标准的年号及修改单号 | |||
/// </summary> | |||
public class JT808_Recorder_Up_0x00 : JT808_RecorderBody, IJT808Analyze | |||
{ | |||
public override byte CommandId => 0x00; | |||
/// <summary> | |||
/// 记录仪执行标准年号后 2 位 BCD 码 | |||
/// 无应答则默认为 03 | |||
/// </summary> | |||
public string StandardYear { get; set; } | |||
/// <summary> | |||
/// 修改单号 | |||
/// 无修改单或无应答则默认为 00H | |||
/// </summary> | |||
public byte ModifyNumber { get; set; } | |||
public override string Description => "采集记录仪执行标准版本应答"; | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
} | |||
public override JT808_RecorderBody Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_Recorder_Up_0x00 value = new JT808_Recorder_Up_0x00(); | |||
value.StandardYear = reader.ReadBCD(2); | |||
value.ModifyNumber = reader.ReadByte(); | |||
return value; | |||
} | |||
public override void Serialize(ref JT808MessagePackWriter writer, JT808_RecorderBody jT808_RecorderBody, IJT808Config config) | |||
{ | |||
JT808_Recorder_Up_0x00 value = jT808_RecorderBody as JT808_Recorder_Up_0x00; | |||
writer.WriteBCD(value.StandardYear, 2); | |||
writer.WriteByte(value.ModifyNumber); | |||
} | |||
} | |||
} |
@@ -0,0 +1,117 @@ | |||
using JT808.Protocol.Extensions; | |||
using JT808.Protocol.Formatters; | |||
using JT808.Protocol.Interfaces; | |||
using JT808.Protocol.MessagePack; | |||
using System; | |||
using System.Buffers.Binary; | |||
using System.Collections.Generic; | |||
using System.Text; | |||
using System.Text.Json; | |||
namespace JT808.Protocol.MessageBody.Recorder | |||
{ | |||
/// <summary> | |||
/// 记录仪 | |||
/// </summary> | |||
public class JT808_RecorderPackage : IJT808MessagePackFormatter<JT808_RecorderPackage>, IJT808Analyze | |||
{ | |||
public const ushort BeginFlag = 0x557A; | |||
/// <summary> | |||
/// 起始字头 | |||
/// </summary> | |||
public ushort Begin { get; set; } = BeginFlag; | |||
/// <summary> | |||
/// 记录仪头部 | |||
/// </summary> | |||
public JT808_RecorderHeader JT808_RecorderHeader { get; set; } | |||
/// <summary> | |||
/// 保留字段 | |||
/// </summary> | |||
public byte KeepFields { get; set; } = 0x00; | |||
/// <summary> | |||
/// 记录仪体 | |||
/// </summary> | |||
public JT808_RecorderBody JT808_RecorderBody { get; set; } | |||
/// <summary> | |||
/// 校验字 | |||
/// </summary> | |||
public byte CheckCode { get; set; } | |||
/// <summary> | |||
/// 计算的异或校验码 | |||
/// </summary> | |||
public byte CalculateCheckXorCode { get; set; } = 0; | |||
/// <summary> | |||
/// 跳过数据体序列化 | |||
/// 默认不跳过 | |||
/// 当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||
/// </summary> | |||
public virtual bool SkipSerialization { get; set; } = false; | |||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||
{ | |||
throw new NotImplementedException(); | |||
} | |||
public JT808_RecorderPackage Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||
{ | |||
JT808_RecorderPackage value = new JT808_RecorderPackage(); | |||
value.CalculateCheckXorCode = CalculateXorCheckCode(reader); | |||
value.Begin = reader.ReadUInt16(); | |||
value.JT808_RecorderHeader = new JT808_RecorderHeader().Deserialize(ref reader, config); | |||
value.KeepFields = reader.ReadByte(); | |||
if (value.JT808_RecorderHeader.DataLength > 0) | |||
{ | |||
if (config.IJT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||
{ | |||
//4.2.处理消息体 | |||
value.JT808_RecorderBody = instance.Deserialize(ref reader, config); | |||
} | |||
} | |||
value.CheckCode = reader.ReadByte(); | |||
return value; | |||
} | |||
public void Serialize(ref JT808MessagePackWriter writer, JT808_RecorderPackage value, IJT808Config config) | |||
{ | |||
var currentPosition = writer.GetCurrentPosition(); | |||
writer.WriteUInt16(value.Begin); | |||
value.JT808_RecorderHeader.Serialize(ref writer, value.JT808_RecorderHeader, config); | |||
writer.WriteByte(value.KeepFields); | |||
if (value.JT808_RecorderHeader.DataLength > 0) { | |||
if (config.IJT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||
{ | |||
if (!instance.SkipSerialization) | |||
{ | |||
//4.2.处理消息体 | |||
instance.Serialize(ref writer, value.JT808_RecorderBody, config); | |||
} | |||
} | |||
} | |||
writer.WriteByte(CalculateXorCheckCode(writer.FlushAndGetRealReadOnlySpan().Slice(currentPosition, writer.GetCurrentPosition() - currentPosition + 1))); | |||
} | |||
/// <summary> | |||
/// 计算校验码 | |||
/// </summary> | |||
/// <param name="readOnlySpan"></param> | |||
/// <returns></returns> | |||
private byte CalculateXorCheckCode(JT808MessagePackReader reader) { | |||
var header = reader.GetVirtualReadOnlySpan(5); | |||
int xorByteLength = 5+1 + BinaryPrimitives.ReadInt16BigEndian(header.Slice(3)); | |||
var xorReadOnlySpan = reader.GetVirtualReadOnlySpan(xorByteLength); | |||
return CalculateXorCheckCode(xorReadOnlySpan); | |||
} | |||
/// <summary> | |||
/// 计算校验码 | |||
/// </summary> | |||
/// <param name="xorReadOnlySpan"></param> | |||
/// <returns></returns> | |||
private byte CalculateXorCheckCode(ReadOnlySpan<byte> xorReadOnlySpan) { | |||
byte calculateXorCheckCode = 0; | |||
foreach (var item in xorReadOnlySpan) | |||
{ | |||
calculateXorCheckCode = (byte)(calculateXorCheckCode ^ item); | |||
} | |||
return calculateXorCheckCode; | |||
} | |||
} | |||
} |