@@ -46,6 +46,8 @@ namespace JT808.Protocol.Interfaces | |||||
public virtual IJT808_0x0900_Custom_Factory JT808_0x0900_Custom_Factory { 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_0x8900_Custom_Factory JT808_0x8900_Custom_Factory { get; set; } | ||||
public virtual IJT808_0x8500_2019_Factory JT808_0x8500_2019_Factory { get; set; } | public virtual IJT808_0x8500_2019_Factory JT808_0x8500_2019_Factory { get; set; } | ||||
public IJT808_Recorder_Factory JT808_Recorder_Factory { get; set; } | |||||
public virtual IJT808Config Register(params Assembly[] externalAssemblies) | public virtual IJT808Config Register(params Assembly[] externalAssemblies) | ||||
{ | { | ||||
if (externalAssemblies != null) | if (externalAssemblies != null) | ||||
@@ -63,7 +63,7 @@ namespace JT808.Protocol | |||||
/// <summary> | /// <summary> | ||||
/// 记录仪工厂 | /// 记录仪工厂 | ||||
/// </summary> | /// </summary> | ||||
IJT808_Recorder_Factory IJT808_Recorder_Factory { get; set; } | |||||
IJT808_Recorder_Factory JT808_Recorder_Factory { get; set; } | |||||
/// <summary> | /// <summary> | ||||
/// 统一编码 | /// 统一编码 | ||||
/// </summary> | /// </summary> | ||||
@@ -2613,6 +2613,11 @@ | |||||
只用来标识2019版本增删改情况 | 只用来标识2019版本增删改情况 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.Interfaces.IJT808_Recorder_Factory"> | |||||
<summary> | |||||
记录仪工厂 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.IJT808Config.MsgSNDistributed"> | <member name="P:JT808.Protocol.IJT808Config.MsgSNDistributed"> | ||||
<summary> | <summary> | ||||
消息流水号 | 消息流水号 | ||||
@@ -2674,6 +2679,11 @@ | |||||
控制类型工厂 | 控制类型工厂 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="P:JT808.Protocol.IJT808Config.JT808_Recorder_Factory"> | |||||
<summary> | |||||
记录仪工厂 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.IJT808Config.Encoding"> | <member name="P:JT808.Protocol.IJT808Config.Encoding"> | ||||
<summary> | <summary> | ||||
统一编码 | 统一编码 | ||||
@@ -2712,6 +2722,105 @@ | |||||
当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | 当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.JT808CarDVRDownBodies"> | |||||
<summary> | |||||
记录仪上行数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownBodies.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownBodies.SkipSerialization"> | |||||
<summary> | |||||
跳过数据体序列化 | |||||
默认不跳过 | |||||
当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.Begin"> | |||||
<summary> | |||||
起始字头 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.KeepFields"> | |||||
<summary> | |||||
保留字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.DataLength"> | |||||
<summary> | |||||
数据块长度 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.Bodies"> | |||||
<summary> | |||||
记录仪体下行数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRDownPackage.CheckCode"> | |||||
<summary> | |||||
校验字 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.JT808CarDVRUpBodies"> | |||||
<summary> | |||||
记录仪上行数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpBodies.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpBodies.SkipSerialization"> | |||||
<summary> | |||||
跳过数据体序列化 | |||||
默认不跳过 | |||||
当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.JT808CarDVRUpPackage"> | |||||
<summary> | |||||
行车记录仪上行数据包 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.Begin"> | |||||
<summary> | |||||
起始字头 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.DataLength"> | |||||
<summary> | |||||
数据块长度 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.KeepFields"> | |||||
<summary> | |||||
保留字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.Bodies"> | |||||
<summary> | |||||
记录仪体上行数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.JT808CarDVRUpPackage.CheckCode"> | |||||
<summary> | |||||
校验字 | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT808.Protocol.JT808Constants.DateLimitYear"> | <member name="F:JT808.Protocol.JT808Constants.DateLimitYear"> | ||||
<summary> | <summary> | ||||
日期限制于2000年 | 日期限制于2000年 | ||||
@@ -6722,6 +6831,113 @@ | |||||
RSA 公钥{e,n}中的 n | RSA 公钥{e,n}中的 n | ||||
</summary> | </summary> | ||||
</member> | </member> | ||||
<member name="T:JT808.Protocol.MessageBody.Recorder.JT808_RecorderBody"> | |||||
<summary> | |||||
记录仪数据体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderBody.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderBody.SkipSerialization"> | |||||
<summary> | |||||
跳过数据体序列化 | |||||
默认不跳过 | |||||
当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderHeader.CommandId"> | |||||
<summary> | |||||
命令字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderHeader.DataLength"> | |||||
<summary> | |||||
数据块长度 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage"> | |||||
<summary> | |||||
记录仪 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.Begin"> | |||||
<summary> | |||||
起始字头 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.JT808_RecorderHeader"> | |||||
<summary> | |||||
记录仪头部 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.KeepFields"> | |||||
<summary> | |||||
保留字段 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.JT808_RecorderBody"> | |||||
<summary> | |||||
记录仪体 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.CheckCode"> | |||||
<summary> | |||||
校验字 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.CalculateCheckXorCode"> | |||||
<summary> | |||||
计算的异或校验码 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.SkipSerialization"> | |||||
<summary> | |||||
跳过数据体序列化 | |||||
默认不跳过 | |||||
当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
</summary> | |||||
</member> | |||||
<member name="M:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.CalculateXorCheckCode(JT808.Protocol.MessagePack.JT808MessagePackReader)"> | |||||
<summary> | |||||
计算校验码 | |||||
</summary> | |||||
<param name="readOnlySpan"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="M:JT808.Protocol.MessageBody.Recorder.JT808_RecorderPackage.CalculateXorCheckCode(System.ReadOnlySpan{System.Byte})"> | |||||
<summary> | |||||
计算校验码 | |||||
</summary> | |||||
<param name="xorReadOnlySpan"></param> | |||||
<returns></returns> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.Recorder.JT808_Recorder_Down_0x00"> | |||||
<summary> | |||||
采集记录仪执行标准版本 | |||||
返回:记录仪执行标准的年号及修改单号 | |||||
</summary> | |||||
</member> | |||||
<member name="T:JT808.Protocol.MessageBody.Recorder.JT808_Recorder_Up_0x00"> | |||||
<summary> | |||||
采集记录仪执行标准版本 | |||||
返回:记录仪执行标准的年号及修改单号 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_Recorder_Up_0x00.StandardYear"> | |||||
<summary> | |||||
记录仪执行标准年号后 2 位 BCD 码 | |||||
无应答则默认为 03 | |||||
</summary> | |||||
</member> | |||||
<member name="P:JT808.Protocol.MessageBody.Recorder.JT808_Recorder_Up_0x00.ModifyNumber"> | |||||
<summary> | |||||
修改单号 | |||||
无修改单或无应答则默认为 00H | |||||
</summary> | |||||
</member> | |||||
<member name="F:JT808.Protocol.MessagePack.JT808MessagePackReader._decoded"> | <member name="F:JT808.Protocol.MessagePack.JT808MessagePackReader._decoded"> | ||||
<summary> | <summary> | ||||
是否进行解码操作 | 是否进行解码操作 | ||||
@@ -0,0 +1,25 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace JT808.Protocol | |||||
{ | |||||
/// <summary> | |||||
/// 记录仪上行数据体 | |||||
/// </summary> | |||||
public abstract class JT808CarDVRDownBodies | |||||
{ | |||||
/// <summary> | |||||
/// 命令字 | |||||
/// </summary> | |||||
public abstract byte CommandId { get; } | |||||
/// <summary> | |||||
/// 跳过数据体序列化 | |||||
/// 默认不跳过 | |||||
/// 当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
/// </summary> | |||||
public virtual bool SkipSerialization { get; set; } = false; | |||||
public abstract string Description { get; } | |||||
} | |||||
} |
@@ -0,0 +1,35 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace JT808.Protocol | |||||
{ | |||||
public class JT808CarDVRDownPackage | |||||
{ | |||||
public const ushort BeginFlag = 0x557A; | |||||
/// <summary> | |||||
/// 起始字头 | |||||
/// </summary> | |||||
public ushort Begin { get; set; } = BeginFlag; | |||||
/// <summary> | |||||
/// 命令字 | |||||
/// </summary> | |||||
public byte CommandId { get; set; } | |||||
/// <summary> | |||||
/// 保留字段 | |||||
/// </summary> | |||||
public byte KeepFields { get; set; } = 0x00; | |||||
/// <summary> | |||||
/// 数据块长度 | |||||
/// </summary> | |||||
public ushort DataLength { get; set; } | |||||
/// <summary> | |||||
/// 记录仪体下行数据体 | |||||
/// </summary> | |||||
public JT808CarDVRDownBodies Bodies { get; set; } | |||||
/// <summary> | |||||
/// 校验字 | |||||
/// </summary> | |||||
public byte CheckCode { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,25 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace JT808.Protocol | |||||
{ | |||||
/// <summary> | |||||
/// 记录仪上行数据体 | |||||
/// </summary> | |||||
public abstract class JT808CarDVRUpBodies | |||||
{ | |||||
/// <summary> | |||||
/// 命令字 | |||||
/// </summary> | |||||
public abstract byte CommandId { get; } | |||||
/// <summary> | |||||
/// 跳过数据体序列化 | |||||
/// 默认不跳过 | |||||
/// 当数据体为空的时候,使用null作为空包感觉不适合,所以就算使用空包也需要new一下来表达意思。 | |||||
/// </summary> | |||||
public virtual bool SkipSerialization { get; set; } = false; | |||||
public abstract string Description { get; } | |||||
} | |||||
} |
@@ -0,0 +1,69 @@ | |||||
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 | |||||
{ | |||||
/// <summary> | |||||
/// 行车记录仪上行数据包 | |||||
/// </summary> | |||||
public class JT808CarDVRUpPackage : IJT808MessagePackFormatter<JT808CarDVRUpPackage>, IJT808Analyze | |||||
{ | |||||
public const ushort BeginFlag = 0x557A; | |||||
/// <summary> | |||||
/// 起始字头 | |||||
/// </summary> | |||||
public ushort Begin { get; set; } = BeginFlag; | |||||
/// <summary> | |||||
/// 命令字 | |||||
/// </summary> | |||||
public byte CommandId { get; set; } | |||||
/// <summary> | |||||
/// 数据块长度 | |||||
/// </summary> | |||||
public ushort DataLength { get; set; } | |||||
/// <summary> | |||||
/// 保留字段 | |||||
/// </summary> | |||||
public byte KeepFields { get; set; } = 0x00; | |||||
/// <summary> | |||||
/// 记录仪体上行数据体 | |||||
/// </summary> | |||||
public JT808CarDVRUpBodies Bodies { get; set; } | |||||
/// <summary> | |||||
/// 校验字 | |||||
/// </summary> | |||||
public byte CheckCode { get; set; } | |||||
public void Analyze(ref JT808MessagePackReader reader, Utf8JsonWriter writer, IJT808Config config) | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
public JT808CarDVRUpPackage Deserialize(ref JT808MessagePackReader reader, IJT808Config config) | |||||
{ | |||||
JT808CarDVRUpPackage value = new JT808CarDVRUpPackage(); | |||||
int currentPosition = reader.ReaderCount; | |||||
value.Begin = reader.ReadUInt16(); | |||||
value.CommandId = reader.ReadByte(); | |||||
value.DataLength = reader.ReadUInt16(); | |||||
var carDVRCheckCode = reader.ReadCarDVRCheckCode(currentPosition, value.DataLength); | |||||
//todo:定义一个行车记录仪的异常和跳过校验的配置属性 | |||||
//比如:config.SkipCRCCode | |||||
//if (carDVRCheckCode.RealXorCheckCode != carDVRCheckCode.CalculateXorCheckCode) | |||||
value.KeepFields = reader.ReadByte(); | |||||
//todo:数据体 | |||||
value.CheckCode = reader.ReadByte(); | |||||
return value; | |||||
} | |||||
public void Serialize(ref JT808MessagePackWriter writer, JT808CarDVRUpPackage value, IJT808Config config) | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | |||||
} |
@@ -61,7 +61,7 @@ namespace JT808.Protocol.MessageBody.Recorder | |||||
value.KeepFields = reader.ReadByte(); | value.KeepFields = reader.ReadByte(); | ||||
if (value.JT808_RecorderHeader.DataLength > 0) | if (value.JT808_RecorderHeader.DataLength > 0) | ||||
{ | { | ||||
if (config.IJT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||||
if (config.JT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||||
{ | { | ||||
//4.2.处理消息体 | //4.2.处理消息体 | ||||
value.JT808_RecorderBody = instance.Deserialize(ref reader, config); | value.JT808_RecorderBody = instance.Deserialize(ref reader, config); | ||||
@@ -78,7 +78,7 @@ namespace JT808.Protocol.MessageBody.Recorder | |||||
value.JT808_RecorderHeader.Serialize(ref writer, value.JT808_RecorderHeader, config); | value.JT808_RecorderHeader.Serialize(ref writer, value.JT808_RecorderHeader, config); | ||||
writer.WriteByte(value.KeepFields); | writer.WriteByte(value.KeepFields); | ||||
if (value.JT808_RecorderHeader.DataLength > 0) { | if (value.JT808_RecorderHeader.DataLength > 0) { | ||||
if (config.IJT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||||
if (config.JT808_Recorder_Factory.Map.TryGetValue(value.JT808_RecorderHeader.CommandId, out var instance)) | |||||
{ | { | ||||
if (!instance.SkipSerialization) | if (!instance.SkipSerialization) | ||||
{ | { | ||||
@@ -235,6 +235,20 @@ namespace JT808.Protocol.MessagePack | |||||
return hex; | return hex; | ||||
} | } | ||||
public (byte CalculateXorCheckCode, byte RealXorCheckCode) ReadCarDVRCheckCode(int currentPosition, int bodyLength) | |||||
{ | |||||
//头+ 命令字 + 数据块长度+保留字 | |||||
//2 + 1 + 2 + 1 | |||||
var reader =Reader.Slice(currentPosition, currentPosition+ (2 + 1 + 2 + 1) +bodyLength); | |||||
byte calculateXorCheckCode = 0; | |||||
foreach (var item in reader) | |||||
{ | |||||
calculateXorCheckCode = (byte)(calculateXorCheckCode ^ item); | |||||
} | |||||
var realXorCheckCode = Reader.Slice(currentPosition, currentPosition + (2 + 1 + 2 + 1) + bodyLength + 1)[0]; | |||||
return (calculateXorCheckCode, realXorCheckCode); | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// yyMMddHHmmss | /// yyMMddHHmmss | ||||
/// </summary> | /// </summary> | ||||