Ver código fonte

1.完善终端控制命令参数的解析及对应的自定义命令参数

2.增加基于终端控制命令参数的demo13
3.修改文档
tags/v2.4.1
SmallChi(Koike) 4 anos atrás
pai
commit
0c07eccf17
7 arquivos alterados com 314 adições e 12 exclusões
  1. +7
    -0
      README.md
  2. +1
    -0
      src/JT808.Protocol.Test/MessageBody/JT808_0x8105Test.cs
  3. +275
    -0
      src/JT808.Protocol.Test/Simples/Demo13.cs
  4. +2
    -2
      src/JT808.Protocol/Extensions/JT808_0x8105_CommandParameterExtensions.cs
  5. +2
    -2
      src/JT808.Protocol/Internal/JT808_0x8105_Cusotm_Factory.cs
  6. +7
    -2
      src/JT808.Protocol/JT808.Protocol.xml
  7. +20
    -6
      src/JT808.Protocol/MessageBody/JT808_0x8105.cs

+ 7
- 0
README.md Ver arquivo

@@ -313,6 +313,13 @@ JT808Serializer DT2JT808Serializer = new JT808Serializer(DT2JT808Config);

>注意:只适用于已知的设备厂家协议才行

### 举个栗子13

场景:
由于粤标的设备把2019版本的0x8105终端控制消息命令参数做了扩展,所以需要兼容。

[可以参考Simples的Demo13](https://github.com/SmallChi/JT808/blob/master/src/JT808.Protocol.Test/Simples/Demo13.cs)

## NuGet安装

| Package Name| Version| Preview Version |Downloads|Remark|


+ 1
- 0
src/JT808.Protocol.Test/MessageBody/JT808_0x8105Test.cs Ver arquivo

@@ -9,6 +9,7 @@ namespace JT808.Protocol.Test.MessageBody
public class JT808_0x8105Test
{
JT808Serializer JT808Serializer = new JT808Serializer();

[Fact]
public void Test1()
{


+ 275
- 0
src/JT808.Protocol.Test/Simples/Demo13.cs Ver arquivo

@@ -0,0 +1,275 @@
using JT808.Protocol.Enums;
using JT808.Protocol.Interfaces;
using JT808.Protocol.Internal;
using JT808.Protocol.Extensions;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;
using JT808.Protocol.MessageBody;
using JT808.Protocol.Formatters;
using JT808.Protocol.MessagePack;
using System.Text.Json;
using JT808.Protocol.MessageBody.CarDVR;
using System.Linq;
using JT808.Protocol.Test.JT808LocationAttach;
using static JT808.Protocol.MessageBody.JT808_0x8105;
using System.Buffers.Binary;
using Newtonsoft.Json;

namespace JT808.Protocol.Test.Simples
{
public class Demo13
{
JT808Serializer JT808Serializer;

public Demo13()
{
IJT808Config jT808Config = new DefaultGlobalConfig();
jT808Config.JT808_0x8105_Cusotm_Factory.SetMap<Koike1CommandParameter>();
jT808Config.JT808_0x8105_Cusotm_Factory.SetMap<Koike2CommandParameter>();
jT808Config.JT808_0x8105_Cusotm_Factory.SetMap<Koike3CommandParameter>();
JT808Serializer = new JT808Serializer(jT808Config);
}

[Fact]
public void Test1()
{
JT808Package jT808Package = new JT808Package
{
Header = new JT808Header
{
MsgId = Enums.JT808MsgId.终端控制.ToUInt16Value(),
ManualMsgNum = 1,
TerminalPhoneNo = "12345678900",
},
Bodies = new JT808_0x8105
{
CommandWord = 1,
CustomCommandParameters=new List<ICommandParameter>
{
new Koike1CommandParameter
{
Value=23
},
new Koike2CommandParameter
{
Value="SmallChi"
},
new Koike3CommandParameter
{
Value=new Koike3Object
{
Value1=0xff,
Value2="Happy"
}
}
}
}
};
var hex = JT808Serializer.Serialize(jT808Package).ToHexString();
Assert.Equal("7E8105002A0123456789000001013B3B3B3B3B3B3B3B3B3B3B3B3B000000173B536D616C6C43686900003BFF486170707900000000003B827E", hex);
}

[Fact]
public void Test2()
{
byte[] bytes = "7E8105002A0123456789000001013B3B3B3B3B3B3B3B3B3B3B3B3B000000173B536D616C6C43686900003BFF486170707900000000003B827E".ToHexBytes();
var jT808Package = JT808Serializer.Deserialize<JT808Package>(bytes);
Assert.Equal(Enums.JT808MsgId.终端控制.ToUInt16Value(), jT808Package.Header.MsgId);
Assert.Equal(1, jT808Package.Header.MsgNum);
Assert.Equal("12345678900", jT808Package.Header.TerminalPhoneNo);
var JT808_0x8105 = (JT808_0x8105)jT808Package.Bodies;
Assert.Equal(1, JT808_0x8105.CommandWord);
Assert.Equal(23u, JT808_0x8105.CustomCommandParameters.GetCommandParameter<Koike1CommandParameter>().Value.Value);
Assert.Equal("SmallChi", JT808_0x8105.CustomCommandParameters.GetCommandParameter<Koike2CommandParameter>().Value);
Assert.Equal(new Koike3Object()
{
Value1 = 0xff,
Value2 = "Happy"
}, JT808_0x8105.CustomCommandParameters.GetCommandParameter<Koike3CommandParameter>().Value);
}

[Fact]
public void Test3()
{
byte[] bytes = "7E8105002A0123456789000001013B3B3B3B3B3B3B3B3B3B3B3B3B000000173B536D616C6C43686900003BFF486170707900000000003B827E".ToHexBytes();
var json = JT808Serializer.Analyze(bytes);
}

[Fact]
public void Test4()
{
var ex= Assert.Throws<System.ArgumentException>(() =>
{
IJT808Config jT808Config = new DefaultGlobalConfig();
jT808Config.JT808_0x8105_Cusotm_Factory.SetMap<ErrorCommandParameter>();
});
Assert.Equal(ex.Message, $"{typeof(ErrorCommandParameter).FullName} Order is {3}. We're starting at 13 and we're incremying by 1.");
}

/// <summary>
/// ICusotmCommandParameter 自定义命令参数接口
/// ICommandParameterValue<> 对应的数据类型值
/// 注意:Order必须从13开始逐一递增
/// </summary>
public class Koike1CommandParameter : ICusotmCommandParameter, ICommandParameterValue<uint?>
{
public int Order => 13;

public string CommandName => "Koike1";

public uint? Value { get; set; }

/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
if (!Value.HasValue) return default;
var value = new byte[4];
BinaryPrimitives.WriteUInt32BigEndian(value, Value.Value);
return value;
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
public void ToValue(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
Value = BinaryPrimitives.ReadUInt32BigEndian(bytes);
}
}
}
/// <summary>
/// ICusotmCommandParameter 自定义命令参数接口
/// ICommandParameterValue<> 对应的数据类型值
/// 注意:Order必须从13开始逐一递增
/// </summary>
public class Koike2CommandParameter : ICusotmCommandParameter, ICommandParameterValue<string>
{
public int Order => 14;
public string CommandName => "Koike2";
public string Value { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
if (string.IsNullOrEmpty(Value)) return default;
return JT808Constants.Encoding.GetBytes(Value.PadRight(10, '\0'));
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
public void ToValue(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
Value = JT808Constants.Encoding.GetString(bytes).Trim('\0');
}
}
}
/// <summary>
/// ICusotmCommandParameter 自定义命令参数接口
/// ICommandParameterValue<> 对应的数据类型值
/// 注意:Order必须从13开始逐一递增
/// </summary>
public class Koike3CommandParameter : ICusotmCommandParameter, ICommandParameterValue<Koike3Object>
{
public int Order => 15;
public string CommandName => "Koike3";
public Koike3Object Value { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
if (Value==null) return default;
return Value.ToBytes();
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
public void ToValue(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
Value = new Koike3Object();
Value.ToValue(bytes);
}
}
}
/// <summary>
/// Koike3为对象
/// ICommandParameterConvert:命令参数转换
/// ToString:为对象类型用于分析器自定义显示
/// </summary>
public record Koike3Object : ICommandParameterConvert
{
public byte Value1 { get; set; }
public string Value2 { get; set; }
public byte[] ToBytes()
{
byte[] value = new byte[11];
value[0] = Value1;
var val2 = JT808Constants.Encoding.GetBytes(Value2.PadRight(10, '\0'));
Array.Copy(val2, 0, value, 1, val2.Length);
return value;
}
public void ToValue(byte[] bytes)
{
if (bytes != null && bytes.Length > 0)
{
var val = bytes.AsSpan();
Value1 = val[0];
Value2 = JT808Constants.Encoding.GetString(val.Slice(1)).Trim('\0');
}
}
/// <summary>
/// 用于分析器描述
/// </summary>
/// <returns></returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}

/// <summary>
/// ICusotmCommandParameter 自定义命令参数接口
/// ICommandParameterValue<> 对应的数据类型值
/// 注意:Order必须从13开始逐一递增
/// </summary>
public class ErrorCommandParameter : ICusotmCommandParameter, ICommandParameterValue<bool>
{
public int Order => 3;
public string CommandName => "Error";
public bool Value { get; set; }
/// <summary>
///
/// </summary>
/// <returns></returns>
public byte[] ToBytes()
{
return default;
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
public void ToValue(byte[] bytes)
{

}
}
}
}

+ 2
- 2
src/JT808.Protocol/Extensions/JT808_0x8105_CommandParameterExtensions.cs Ver arquivo

@@ -85,9 +85,9 @@ namespace JT808.Protocol.Extensions
{
var name = nameof(ICommandParameterValue<object>.Value);
var property = commandParameter.GetType().GetProperty(name);
if (property == null) return default;
if (property == null) return "空值";
var value= property.GetValue(commandParameter);
if (value == null) return default;
if (value == null) return "空值";
return value.ToString();
}
}


+ 2
- 2
src/JT808.Protocol/Internal/JT808_0x8105_Cusotm_Factory.cs Ver arquivo

@@ -47,11 +47,11 @@ namespace JT808.Protocol.Internal
var order = (int)type.GetProperty(nameof(ICusotmCommandParameter.Order)).GetValue(instance);
if(order < CommandParameterCount)
{
throw new ArgumentException($"{type.FullName} {order} We're starting at 13 and we're incremying by 1.");
throw new ArgumentException($"{type.FullName} Order is {order}. We're starting at 13 and we're incremying by 1.");
}
if (Map.ContainsKey(order))
{
throw new ArgumentException($"{type.FullName} {order} An element with the same Order already exists.");
throw new ArgumentException($"{type.FullName} Order is {order}. An element with the same Order already exists.");
}
else
{


+ 7
- 2
src/JT808.Protocol/JT808.Protocol.xml Ver arquivo

@@ -15340,13 +15340,18 @@
命令名称
</summary>
</member>
<member name="M:JT808.Protocol.MessageBody.JT808_0x8105.ICommandParameter.ToBytes">
<member name="T:JT808.Protocol.MessageBody.JT808_0x8105.ICommandParameterConvert">
<summary>
命令参数值的转换
</summary>
</member>
<member name="M:JT808.Protocol.MessageBody.JT808_0x8105.ICommandParameterConvert.ToBytes">
<summary>
转为byte数组
</summary>
<returns></returns>
</member>
<member name="M:JT808.Protocol.MessageBody.JT808_0x8105.ICommandParameter.ToValue(System.Byte[])">
<member name="M:JT808.Protocol.MessageBody.JT808_0x8105.ICommandParameterConvert.ToValue(System.Byte[])">
<summary>
将byte数组转为命令值
</summary>


+ 20
- 6
src/JT808.Protocol/MessageBody/JT808_0x8105.cs Ver arquivo

@@ -129,12 +129,12 @@ namespace JT808.Protocol.MessageBody
writer.WriteByte(value.CommandWord);
if (value.CommandWord == 1 || value.CommandWord == 2)
{
if (CommandParameters != null && CommandParameters.Count > 0)
if (value.CommandParameters != null && value.CommandParameters.Count > 0)
{
//由于标准的命令参数是有顺序的,所以先判断有几个标准的命令参数
for (int i = 0; i < CommandParameterCount; i++)
{
var cmd = CommandParameters.FirstOrDefault(f => f.Order == i);
var cmd = value.CommandParameters.FirstOrDefault(f => f.Order == i);
if (cmd != null)
{
writer.WriteArray(cmd.ToBytes());
@@ -146,10 +146,17 @@ namespace JT808.Protocol.MessageBody
}
}
}
if (CustomCommandParameters != null && CustomCommandParameters.Count > 0)
else
{
for (int i = 0; i < CommandParameterCount; i++)
{
writer.WriteChar(CommandParameterSeparator);
}
}
if (value.CustomCommandParameters != null && value.CustomCommandParameters.Count > 0)
{
//自定义命令参数扩展
foreach (var cmd in CustomCommandParameters.OrderBy(o => o.Order))
foreach (var cmd in value.CustomCommandParameters.OrderBy(o => o.Order))
{
var bytes = cmd.ToBytes();
if (bytes != null && bytes.Length > 0)
@@ -230,7 +237,7 @@ namespace JT808.Protocol.MessageBody
if (commandParameter != null)
{
commandParameter.ToValue(cmd);
writer.WriteString($"[{cmd.ToHexString()}]{commandParameter.CommandName}", commandParameter.ToValueString());
writer.WriteString($"[{cmd?.ToHexString()}]{commandParameter.CommandName}", commandParameter.ToValueString());
}
}
}
@@ -243,7 +250,7 @@ namespace JT808.Protocol.MessageBody
/// <summary>
/// 命令参数接口
/// </summary>
public interface ICommandParameter
public interface ICommandParameter:ICommandParameterConvert
{
/// <summary>
/// 排序
@@ -253,6 +260,13 @@ namespace JT808.Protocol.MessageBody
/// 命令名称
/// </summary>
string CommandName { get; }

}
/// <summary>
/// 命令参数值的转换
/// </summary>
public interface ICommandParameterConvert
{
/// <summary>
/// 转为byte数组
/// </summary>


Carregando…
Cancelar
Salvar