Переглянути джерело

1.修改BCD的写入和读取方式

2.增加日期有针对性的写入和读取方式
tags/v2.4.5
SmallChi(Koike) 3 роки тому
джерело
коміт
88e84001cf
4 змінених файлів з 728 додано та 93 видалено
  1. +41
    -0
      src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs
  2. +134
    -0
      src/JT808.Protocol/JT808.Protocol.xml
  3. +240
    -46
      src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs
  4. +313
    -47
      src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs

+ 41
- 0
src/JT808.Protocol.Test/MessagePack/JT808MessagePackWriterTest.cs Переглянути файл

@@ -509,5 +509,46 @@ namespace JT808.Protocol.Test.MessagePack
var hex = msgpackWriter.FlushAndGetEncodingArray().ToHexString();
Assert.Equal("736D616C6C636869286B6F696B652900", hex);
}

[Fact]
public void IntToBcdTest()
{
var bytes1 = new byte[5];
Span<byte> buffer1 = new Span<byte>(bytes1);
IntToBcd(123456700, buffer1, buffer1.Length);
Assert.NotEqual(new byte[] { 0x12, 0x34, 0x56, 0x70,0x00 }, buffer1.ToArray());
Assert.Equal(new byte[] { 0x01, 0x23, 0x45, 0x67,0x00 }, buffer1.ToArray());

var bytes = new byte[6];
Span<byte> buffer = new Span<byte>(bytes);
IntToBcd(123456700, buffer, buffer.Length);
Assert.Equal(new byte[] { 0x00, 0x01, 0x23, 0x45, 0x67, 0x00 }, buffer.ToArray());
}

[Fact]
public void WriteBcdTest()
{
byte[] array = new byte[100];
var msgpackWriter = new JT808MessagePackWriter(array);
int val1 = 1234567890;
long val2 = 123456789011;
msgpackWriter.WriteBCD(val1, 5);
msgpackWriter.WriteBCD(val2, 10);
var result = msgpackWriter.FlushAndGetRealArray();
Assert.Equal(new byte[] { 0x12, 0x34, 0x56, 0x78, 0x90, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0x90, 0x11 }, result);
}

private void IntToBcd(int num, Span<byte> list, int count)
{
int level = count - 1;
var high = num / 100;
var low = num % 100;
if (high > 0)
{
IntToBcd(high, list, --count);
}
byte res = (byte)(((low / 10) << 4) + (low % 10));
list[level] = res;
}
}
}

+ 134
- 0
src/JT808.Protocol/JT808.Protocol.xml Переглянути файл

@@ -18256,48 +18256,95 @@
</summary>
<param name="format">>D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime_yyMMddHHmmss">
<summary>
读取六字节日期,yyMMddHHmmss
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.BcdToInt(System.Byte)">
<summary>
16进制的BCD BYTE转成整型
</summary>
<param name="value">16进制的BCD BYTE转成整型</param>
<returns></returns>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull6(System.String)">
<summary>
读取可空类型的六字节日期,yyMMddHHmmss
</summary>
<param name="format">>D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull_yyMMddHHmmss">
<summary>
读取可空类型的六字节日期,yyMMddHHmmss
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime5(System.String)">
<summary>
读取五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime_HHmmssfff">
<summary>
读取五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull5(System.String)">
<summary>
读取可空类型的五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull_HHmmssfff">
<summary>
读取可空类型的五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime4(System.String)">
<summary>
读取四字节日期,YYYYMMDD
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime_YYYYMMDD">
<summary>
读取四字节日期,YYYYMMDD
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull4(System.String)">
<summary>
读取可空类型的四字节日期,YYYYMMDD
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull_YYYYMMDD">
<summary>
读取可空类型的四字节日期,YYYYMMDD
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime3(System.String)">
<summary>
读取三字节日期,YYMMDD
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTime_YYMMDD">
<summary>
读取三字节日期,YYMMDD
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull3(System.String)">
<summary>
读取可空类型的三字节日期,YYMMDD
</summary>
<param name="format">D2: 10 X2:16</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadDateTimeNull_YYMMDD">
<summary>
读取可空类型的三字节日期,YYMMDD
</summary>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackReader.ReadUTCDateTime">
<summary>
读取UTC时间类型
@@ -18567,6 +18614,45 @@
<param name="src"></param>
<param name="position"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.IntToBcd(System.Int32)">
<summary>
整型数据转为BCD BYTE
为了兼容int类型,不使用byte做参数
支持0xFF一个字节的转换
</summary>
<param name="value"></param>
<returns></returns>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.IntToBcd(System.Int32,System.Span{System.Byte},System.Int32)">
<summary>
整型数据转为BCD BYTE[]
</summary>
<param name="value">整数值</param>
<param name="list">bytes</param>
<param name="count">字节数>=整数值</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.IntToBcd(System.Int64,System.Span{System.Byte},System.Int32)">
<summary>
整型数据转为BCD BYTE[]
</summary>
<param name="value">整数值</param>
<param name="list">bytes</param>
<param name="byteCount">字节数>=整数值</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteBCD(System.Int64@,System.Int32@)">
<summary>
写入BCD编码数据
</summary>
<param name="value">整数值</param>
<param name="byteCount">字节数>=整数值</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteBCD(System.Int32@,System.Int32@)">
<summary>
写入BCD编码数据
</summary>
<param name="value">整数值</param>
<param name="count">字节数>=整数值</param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime6(System.DateTime@,System.Int32@)">
<summary>
写入六个字节的日期类型,yyMMddHHmmss
@@ -18574,6 +18660,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_yyMMddHHmmss(System.DateTime@)">
<summary>
写入六个字节的日期类型,yyMMddHHmmss
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime6(System.Nullable{System.DateTime}@,System.Int32@)">
<summary>
写入六个字节的可空日期类型,yyMMddHHmmss
@@ -18581,6 +18673,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_yyMMddHHmmss(System.Nullable{System.DateTime}@)">
<summary>
写入六个字节的可空日期类型,yyMMddHHmmss
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime5(System.DateTime@,System.Int32@)">
<summary>
写入五个字节的日期类型,HH-mm-ss-msms或HH-mm-ss-fff
@@ -18588,6 +18686,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_HHmmssfff(System.DateTime@)">
<summary>
写入五个字节的日期类型,HH-mm-ss-msms或HH-mm-ss-fff
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime5(System.Nullable{System.DateTime}@,System.Int32@)">
<summary>
写入五个字节的可空日期类型,HH-mm-ss-msms或HH-mm-ss-fff
@@ -18595,6 +18699,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_HHmmssfff(System.Nullable{System.DateTime}@)">
<summary>
写入五个字节的可空日期类型,HH-mm-ss-msms或HH-mm-ss-fff
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteUTCDateTime(System.DateTime@)">
<summary>
写入UTC日期类型
@@ -18608,6 +18718,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_YYYYMMDD(System.DateTime@)">
<summary>
写入四个字节的日期类型,YYYYMMDD BCD[4] 数据形如:20200101
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime4(System.Nullable{System.DateTime}@,System.Int32@)">
<summary>
写入四个字节的可空日期类型,YYYYMMDD BCD[4]数据形如:20200101
@@ -18615,6 +18731,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_YYYYMMDD(System.Nullable{System.DateTime}@)">
<summary>
写入四个字节的可空日期类型,YYYYMMDD BCD[4]数据形如:20200101
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime3(System.DateTime@,System.Int32@)">
<summary>
写入三个字节的日期类型,YYMMDD 数据形如:20200101
@@ -18622,6 +18744,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_YYMMDD(System.DateTime@)">
<summary>
写入三个字节的日期类型,YYMMDD 数据形如:20200101
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime3(System.Nullable{System.DateTime}@,System.Int32@)">
<summary>
写入三个字节的可空日期类型,YYMMDD 数据形如:20200101
@@ -18629,6 +18757,12 @@
<param name="value"></param>
<param name="fromBase"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteDateTime_YYMMDD(System.Nullable{System.DateTime}@)">
<summary>
写入三个字节的可空日期类型,YYMMDD 数据形如:20200101
</summary>
<param name="value"></param>
</member>
<member name="M:JT808.Protocol.MessagePack.JT808MessagePackWriter.WriteXor(System.Int32@,System.Int32@)">
<summary>
将指定内存块进行或运算并写入一个字节


+ 240
- 46
src/JT808.Protocol/MessagePack/JT808MessagePackReader.cs Переглянути файл

@@ -371,18 +371,19 @@ namespace JT808.Protocol.MessagePack
/// 读取六字节日期,yyMMddHHmmss
/// </summary>
/// <param name="format">>D2: 10 X2:16</param>
[Obsolete("use ReadDateTime_yyMMddHHmmss")]
public DateTime ReadDateTime6(string format = "X2")
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(6);
int year = Convert.ToInt32(readOnlySpan[0].ToString(format)) + JT808Constants.DateLimitYear;
int month = Convert.ToInt32(readOnlySpan[1].ToString(format));
int day = Convert.ToInt32(readOnlySpan[2].ToString(format));
int hour = Convert.ToInt32(readOnlySpan[3].ToString(format));
int minute = Convert.ToInt32(readOnlySpan[4].ToString(format));
int second = Convert.ToInt32(readOnlySpan[5].ToString(format));
int year = BcdToInt(readOnlySpan[0]) + JT808Constants.DateLimitYear;
int month = BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
int hour = BcdToInt(readOnlySpan[3]);
int minute = BcdToInt(readOnlySpan[4]);
int second = BcdToInt(readOnlySpan[5]);
d = new DateTime(year, month, day, hour, minute, second);
}
catch (Exception)
@@ -392,21 +393,81 @@ namespace JT808.Protocol.MessagePack
return d;
}
/// <summary>
/// 读取六字节日期,yyMMddHHmmss
/// </summary>
public DateTime ReadDateTime_yyMMddHHmmss()
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(6);
int year = BcdToInt(readOnlySpan[0]) + JT808Constants.DateLimitYear;
int month = BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
int hour = BcdToInt(readOnlySpan[3]);
int minute = BcdToInt(readOnlySpan[4]);
int second = BcdToInt(readOnlySpan[5]);
d = new DateTime(year, month, day, hour, minute, second);
}
catch (Exception)
{
d = JT808Constants.UTCBaseTime;
}
return d;
}
/// <summary>
/// 16进制的BCD BYTE转成整型
/// </summary>
/// <param name="value">16进制的BCD BYTE转成整型</param>
/// <returns></returns>
public int BcdToInt(byte value)
{
int high = value >> 4;
int low = value & 0xF;
int number = 10 * high + low;
return number;
}
/// <summary>
/// 读取可空类型的六字节日期,yyMMddHHmmss
/// </summary>
/// <param name="format">>D2: 10 X2:16</param>
[Obsolete("use ReadDateTimeNull_yyMMddHHmmss")]
public DateTime? ReadDateTimeNull6(string format = "X2")
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(6);
int year = Convert.ToInt32(readOnlySpan[0].ToString(format)) ;
int month = Convert.ToInt32(readOnlySpan[1].ToString(format));
int day = Convert.ToInt32(readOnlySpan[2].ToString(format));
int hour = Convert.ToInt32(readOnlySpan[3].ToString(format));
int minute = Convert.ToInt32(readOnlySpan[4].ToString(format));
int second = Convert.ToInt32(readOnlySpan[5].ToString(format));
int year = BcdToInt(readOnlySpan[0]);
int month = BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
int hour = BcdToInt(readOnlySpan[3]);
int minute = BcdToInt(readOnlySpan[4]);
int second = BcdToInt(readOnlySpan[5]);
if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) return null;
d = new DateTime(year + JT808Constants.DateLimitYear, month, day, hour, minute, second);
}
catch (Exception)
{
return null;
}
return d;
}
/// <summary>
/// 读取可空类型的六字节日期,yyMMddHHmmss
/// </summary>
public DateTime? ReadDateTimeNull_yyMMddHHmmss()
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(6);
int year = BcdToInt(readOnlySpan[0]);
int month = BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
int hour = BcdToInt(readOnlySpan[3]);
int minute = BcdToInt(readOnlySpan[4]);
int second = BcdToInt(readOnlySpan[5]);
if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) return null;
d = new DateTime(year + JT808Constants.DateLimitYear, month, day, hour, minute, second);
}
@@ -420,23 +481,45 @@ namespace JT808.Protocol.MessagePack
/// 读取五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTime_HHmmssfff")]
public DateTime ReadDateTime5(string format = "X2")
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(5);
StringBuilder sb = new StringBuilder(4);
sb.Append(readOnlySpan[3].ToString(format));
sb.Append(readOnlySpan[4].ToString(format));
var fff = BcdToInt(readOnlySpan[3]) * 100 + BcdToInt(readOnlySpan[4]);
d = new DateTime(
DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
BcdToInt(readOnlySpan[0]),
BcdToInt(readOnlySpan[1]),
BcdToInt(readOnlySpan[2]), fff);
}
catch
{
d = JT808Constants.UTCBaseTime;
}
return d;
}
/// <summary>
/// 读取五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
/// </summary>
public DateTime ReadDateTime_HHmmssfff()
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(5);
var fff = BcdToInt(readOnlySpan[3]) * 100 + BcdToInt(readOnlySpan[4]);
d = new DateTime(
DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
Convert.ToInt32(readOnlySpan[0].ToString(format)),
Convert.ToInt32(readOnlySpan[1].ToString(format)),
Convert.ToInt32(readOnlySpan[2].ToString(format)),
Convert.ToInt32(sb.ToString().TrimStart()));
BcdToInt(readOnlySpan[0]),
BcdToInt(readOnlySpan[1]),
BcdToInt(readOnlySpan[2]), fff);
}
catch
{
@@ -448,20 +531,47 @@ namespace JT808.Protocol.MessagePack
/// 读取可空类型的五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTimeNull_HHmmssfff")]
public DateTime? ReadDateTimeNull5(string format = "X2")
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(5);
StringBuilder sb = new StringBuilder(4);
sb.Append(readOnlySpan[3].ToString("X2"));
sb.Append(readOnlySpan[4].ToString("X2"));
int hour = Convert.ToInt32(readOnlySpan[0].ToString(format));
int minute = Convert.ToInt32(readOnlySpan[1].ToString(format));
int second = Convert.ToInt32(readOnlySpan[2].ToString(format));
int millisecond = Convert.ToInt32(sb.ToString().TrimStart());
if (hour == 0 && minute == 0 && second == 0 && millisecond == 0) return null;
int hour = BcdToInt(readOnlySpan[0]);
int minute = BcdToInt(readOnlySpan[1]);
int second = BcdToInt(readOnlySpan[2]);
var fff = BcdToInt(readOnlySpan[3]) * 100 + BcdToInt(readOnlySpan[4]);
if (hour == 0 && minute == 0 && second == 0 && fff == 0) return null;
d = new DateTime(
DateTime.Now.Year,
DateTime.Now.Month,
DateTime.Now.Day,
hour,
minute,
second,
fff);
}
catch
{
return null;
}
return d;
}
/// <summary>
/// 读取可空类型的五字节日期,HH-mm-ss-msms|HH-mm-ss-fff
/// </summary>
public DateTime? ReadDateTimeNull_HHmmssfff()
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(5);
int hour = BcdToInt(readOnlySpan[0]);
int minute = BcdToInt(readOnlySpan[1]);
int second = BcdToInt(readOnlySpan[2]);
var fff = BcdToInt(readOnlySpan[3]) * 100 + BcdToInt(readOnlySpan[4]);
if (hour == 0 && minute == 0 && second == 0 && fff == 0) return null;
d = new DateTime(
DateTime.Now.Year,
DateTime.Now.Month,
@@ -469,7 +579,7 @@ namespace JT808.Protocol.MessagePack
hour,
minute,
second,
millisecond);
fff);
}
catch
{
@@ -481,19 +591,18 @@ namespace JT808.Protocol.MessagePack
/// 读取四字节日期,YYYYMMDD
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTime_YYYYMMDD")]
public DateTime ReadDateTime4(string format = "X2")
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(4);
StringBuilder sb = new StringBuilder(4);
sb.Append(readOnlySpan[0].ToString(format));
sb.Append(readOnlySpan[1].ToString(format));
var year = BcdToInt(readOnlySpan[0]) * 100 + BcdToInt(readOnlySpan[1]);
d = new DateTime(
Convert.ToInt32(sb.ToString()),
Convert.ToInt32(readOnlySpan[2].ToString(format)),
Convert.ToInt32(readOnlySpan[3].ToString(format)));
year,
BcdToInt(readOnlySpan[2]),
BcdToInt(readOnlySpan[3]));
}
catch (Exception)
{
@@ -502,21 +611,61 @@ namespace JT808.Protocol.MessagePack
return d;
}
/// <summary>
/// 读取四字节日期,YYYYMMDD
/// </summary>
public DateTime ReadDateTime_YYYYMMDD()
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(4);
var year = BcdToInt(readOnlySpan[0]) * 100 + BcdToInt(readOnlySpan[1]);
d = new DateTime(
year,
BcdToInt(readOnlySpan[2]),
BcdToInt(readOnlySpan[3]));
}
catch (Exception)
{
d = JT808Constants.UTCBaseTime;
}
return d;
}
/// <summary>
/// 读取可空类型的四字节日期,YYYYMMDD
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTimeNull_YYYYMMDD")]
public DateTime? ReadDateTimeNull4(string format = "X2")
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(4);
StringBuilder sb = new StringBuilder(4);
sb.Append(readOnlySpan[0].ToString(format));
sb.Append(readOnlySpan[1].ToString(format));
int year = Convert.ToInt32(sb.ToString());
int month = Convert.ToInt32(readOnlySpan[2].ToString(format));
int day = Convert.ToInt32(readOnlySpan[3].ToString(format));
var year = BcdToInt(readOnlySpan[0]) * 100 + BcdToInt(readOnlySpan[1]);
int month = BcdToInt(readOnlySpan[2]);
int day = BcdToInt(readOnlySpan[3]);
if (year == 0 && month == 0 && day == 0) return null;
d = new DateTime(year, month, day);
}
catch (Exception)
{
return null;
}
return d;
}
/// <summary>
/// 读取可空类型的四字节日期,YYYYMMDD
/// </summary>
public DateTime? ReadDateTimeNull_YYYYMMDD()
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(4);
var year = BcdToInt(readOnlySpan[0]) * 100 + BcdToInt(readOnlySpan[1]);
int month = BcdToInt(readOnlySpan[2]);
int day = BcdToInt(readOnlySpan[3]);
if (year == 0 && month == 0 && day == 0) return null;
d = new DateTime(year, month, day);
}
@@ -530,6 +679,7 @@ namespace JT808.Protocol.MessagePack
/// 读取三字节日期,YYMMDD
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTime_YYMMDD")]
public DateTime ReadDateTime3(string format = "X2")
{
DateTime d;
@@ -537,9 +687,29 @@ namespace JT808.Protocol.MessagePack
{
var readOnlySpan = GetReadOnlySpan(3);
d = new DateTime(
Convert.ToInt32(readOnlySpan[0].ToString(format)) + JT808Constants.DateLimitYear,
Convert.ToInt32(readOnlySpan[1].ToString(format)),
Convert.ToInt32(readOnlySpan[2].ToString(format)));
BcdToInt(readOnlySpan[0]) + JT808Constants.DateLimitYear,
BcdToInt(readOnlySpan[1]),
BcdToInt(readOnlySpan[2]));
}
catch (Exception)
{
d = JT808Constants.UTCBaseTime;
}
return d;
}
/// <summary>
/// 读取三字节日期,YYMMDD
/// </summary>
public DateTime ReadDateTime_YYMMDD()
{
DateTime d;
try
{
var readOnlySpan = GetReadOnlySpan(3);
d = new DateTime(
BcdToInt(readOnlySpan[0]) + JT808Constants.DateLimitYear,
BcdToInt(readOnlySpan[1]),
BcdToInt(readOnlySpan[2]));
}
catch (Exception)
{
@@ -551,15 +721,16 @@ namespace JT808.Protocol.MessagePack
/// 读取可空类型的三字节日期,YYMMDD
/// </summary>
/// <param name="format">D2: 10 X2:16</param>
[Obsolete("use ReadDateTimeNull_YYMMDD")]
public DateTime? ReadDateTimeNull3(string format = "X2")
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(3);
int year =Convert.ToInt32(readOnlySpan[0].ToString(format));
int month=Convert.ToInt32(readOnlySpan[1].ToString(format));
int day = Convert.ToInt32(readOnlySpan[2].ToString(format));
int year = BcdToInt(readOnlySpan[0]);
int month= BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
if (year == 0 && month == 0 && day == 0) return null;
d = new DateTime(
year + JT808Constants.DateLimitYear, month,day
@@ -572,6 +743,29 @@ namespace JT808.Protocol.MessagePack
return d;
}
/// <summary>
/// 读取可空类型的三字节日期,YYMMDD
/// </summary>
public DateTime? ReadDateTimeNull_YYMMDD()
{
DateTime? d;
try
{
var readOnlySpan = GetReadOnlySpan(3);
int year = BcdToInt(readOnlySpan[0]);
int month = BcdToInt(readOnlySpan[1]);
int day = BcdToInt(readOnlySpan[2]);
if (year == 0 && month == 0 && day == 0) return null;
d = new DateTime(
year + JT808Constants.DateLimitYear, month, day
);
}
catch (Exception)
{
d = JT808Constants.UTCBaseTime;
}
return d;
}
/// <summary>
/// 读取UTC时间类型
/// </summary>
/// <returns></returns>


+ 313
- 47
src/JT808.Protocol/MessagePack/JT808MessagePackWriter.cs Переглянути файл

@@ -3,6 +3,7 @@ using JT808.Protocol.Enums;
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Text;

namespace JT808.Protocol.MessagePack
@@ -309,27 +310,133 @@ namespace JT808.Protocol.MessagePack
{
src.CopyTo(writer.Written.Slice(position));
}

/// <summary>
/// 整型数据转为BCD BYTE
/// 为了兼容int类型,不使用byte做参数
/// 支持0xFF一个字节的转换
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public byte IntToBcd(int value)
{
byte result = 0;
if (value <= 0xFF)
{
//19 00010011
//0001 1001
int high = value / 10;
int low = value % 10;
result = (byte)(high << 4 | low);
}
return result;
}

/// <summary>
/// 整型数据转为BCD BYTE[]
/// </summary>
/// <param name="value">整数值</param>
/// <param name="list">bytes</param>
/// <param name="count">字节数>=整数值</param>
public void IntToBcd(int value, Span<byte> list, int count)
{
int level = count - 1;
var high = value / 100;
var low = value % 100;
if (high > 0)
{
IntToBcd(high, list, --count);
}
byte res = (byte)(((low / 10) << 4) + (low % 10));
list[level] = res;
}

/// <summary>
/// 整型数据转为BCD BYTE[]
/// </summary>
/// <param name="value">整数值</param>
/// <param name="list">bytes</param>
/// <param name="byteCount">字节数>=整数值</param>
public void IntToBcd(long value, Span<byte> list, int byteCount)
{
int level = byteCount - 1;
if (level < 0) return;
var high = value / 100;
var low = value % 100;
if (high > 0)
{
IntToBcd(high, list, --byteCount);
}
byte res = (byte)(((low / 10) << 4) + (low % 10));
list[level] = res;
}

/// <summary>
/// 写入BCD编码数据
/// </summary>
/// <param name="value">整数值</param>
/// <param name="byteCount">字节数>=整数值</param>
public void WriteBCD(in long value, in int byteCount)
{
var span = writer.Free;
IntToBcd(value, writer.Free, byteCount);
writer.Advance(byteCount);
}

/// <summary>
/// 写入BCD编码数据
/// </summary>
/// <param name="value">整数值</param>
/// <param name="count">字节数>=整数值</param>
public void WriteBCD(in int value, in int count)
{
var span = writer.Free;
IntToBcd(value, writer.Free, count);
writer.Advance(count);
}

/// <summary>
/// 写入六个字节的日期类型,yyMMddHHmmss
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_yyMMddHHmmss")]
public void WriteDateTime6(in DateTime value, in int fromBase = 16)
{
var span = writer.Free;
span[0] = Convert.ToByte(value.ToString("yy"), fromBase);
span[1] = Convert.ToByte(value.ToString("MM"), fromBase);
span[2] = Convert.ToByte(value.ToString("dd"), fromBase);
span[3] = Convert.ToByte(value.ToString("HH"), fromBase);
span[4] = Convert.ToByte(value.ToString("mm"), fromBase);
span[5] = Convert.ToByte(value.ToString("ss"), fromBase);
int yy = value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Month);
span[2] = IntToBcd(value.Day);
span[3] = IntToBcd(value.Hour);
span[4] = IntToBcd(value.Minute);
span[5] = IntToBcd(value.Second);
writer.Advance(6);
}

/// <summary>
/// 写入六个字节的日期类型,yyMMddHHmmss
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_yyMMddHHmmss(in DateTime value)
{
var span = writer.Free;
int yy = value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Month);
span[2] = IntToBcd(value.Day);
span[3] = IntToBcd(value.Hour);
span[4] = IntToBcd(value.Minute);
span[5] = IntToBcd(value.Second);
writer.Advance(6);
}

/// <summary>
/// 写入六个字节的可空日期类型,yyMMddHHmmss
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_yyMMddHHmmss")]
public void WriteDateTime6(in DateTime? value, in int fromBase = 16)
{
var span = writer.Free;
@@ -344,58 +451,136 @@ namespace JT808.Protocol.MessagePack
}
else
{
span[0] = Convert.ToByte(value.Value.ToString("yy"), fromBase);
span[1] = Convert.ToByte(value.Value.ToString("MM"), fromBase);
span[2] = Convert.ToByte(value.Value.ToString("dd"), fromBase);
span[3] = Convert.ToByte(value.Value.ToString("HH"), fromBase);
span[4] = Convert.ToByte(value.Value.ToString("mm"), fromBase);
span[5] = Convert.ToByte(value.Value.ToString("ss"), fromBase);
int yy = value.Value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Value.Month);
span[2] = IntToBcd(value.Value.Day);
span[3] = IntToBcd(value.Value.Hour);
span[4] = IntToBcd(value.Value.Minute);
span[5] = IntToBcd(value.Value.Second);
}
writer.Advance(6);
}

/// <summary>
/// 写入六个字节的可空日期类型,yyMMddHHmmss
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_yyMMddHHmmss(in DateTime? value)
{
var span = writer.Free;
if (value == null || value.HasValue)
{
span[0] = 0;
span[1] = 0;
span[2] = 0;
span[3] = 0;
span[4] = 0;
span[5] = 0;
}
else
{
int yy = value.Value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Value.Month);
span[2] = IntToBcd(value.Value.Day);
span[3] = IntToBcd(value.Value.Hour);
span[4] = IntToBcd(value.Value.Minute);
span[5] = IntToBcd(value.Value.Second);
}
writer.Advance(6);
}

/// <summary>
/// 写入五个字节的日期类型,HH-mm-ss-msms或HH-mm-ss-fff
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_HHmmssfff")]
public void WriteDateTime5(in DateTime value, in int fromBase = 16)
{
var span = writer.Free;
span[0] = Convert.ToByte(value.ToString("HH"), fromBase);
span[1] = Convert.ToByte(value.ToString("mm"), fromBase);
span[2] = Convert.ToByte(value.ToString("ss"), fromBase);
var msSpan = value.Millisecond.ToString().PadLeft(4,'0').AsSpan();
span[3] = Convert.ToByte(msSpan.Slice(0, 2).ToString(), fromBase);
span[4] = Convert.ToByte(msSpan.Slice(2, 2).ToString(), fromBase);
writer.Advance(5);
span[0] = IntToBcd(value.Hour);
span[1] = IntToBcd(value.Minute);
span[2] = IntToBcd(value.Second);
writer.Advance(3);
IntToBcd(value.Millisecond, writer.Free, 2);
writer.Advance(2);
}

/// <summary>
/// 写入五个字节的日期类型,HH-mm-ss-msms或HH-mm-ss-fff
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_HHmmssfff(in DateTime value)
{
var span = writer.Free;
span[0] = IntToBcd(value.Hour);
span[1] = IntToBcd(value.Minute);
span[2] = IntToBcd(value.Second);
writer.Advance(3);
IntToBcd(value.Millisecond, writer.Free, 2);
writer.Advance(2);
}

/// <summary>
/// 写入五个字节的可空日期类型,HH-mm-ss-msms或HH-mm-ss-fff
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_HHmmssfff")]
public void WriteDateTime5(in DateTime? value, in int fromBase = 16)
{
var span = writer.Free;
if (value == null || value.HasValue)
{
var span = writer.Free;
span[0] = 0;
span[1] = 0;
span[2] = 0;
span[3] = 0;
span[4] = 0;
writer.Advance(5);
}
else
{
span[0] = Convert.ToByte(value.Value.ToString("HH"), fromBase);
span[1] = Convert.ToByte(value.Value.ToString("mm"), fromBase);
span[2] = Convert.ToByte(value.Value.ToString("ss"), fromBase);
var msSpan = value.Value.Millisecond.ToString().PadLeft(4, '0').AsSpan();
span[3] = Convert.ToByte(msSpan.Slice(0, 2).ToString(), fromBase);
span[4] = Convert.ToByte(msSpan.Slice(2, 2).ToString(), fromBase);
var span = writer.Free;
span[0] = IntToBcd(value.Value.Hour);
span[1] = IntToBcd(value.Value.Minute);
span[2] = IntToBcd(value.Value.Second);
writer.Advance(3);
IntToBcd(value.Value.Millisecond, writer.Free, 2);
writer.Advance(2);
}
writer.Advance(5);
}

/// <summary>
/// 写入五个字节的可空日期类型,HH-mm-ss-msms或HH-mm-ss-fff
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_HHmmssfff(in DateTime? value)
{
if (value == null || value.HasValue)
{
var span = writer.Free;
span[0] = 0;
span[1] = 0;
span[2] = 0;
span[3] = 0;
span[4] = 0;
writer.Advance(5);
}
else
{
var span = writer.Free;
span[0] = IntToBcd(value.Value.Hour);
span[1] = IntToBcd(value.Value.Minute);
span[2] = IntToBcd(value.Value.Second);
writer.Advance(3);
IntToBcd(value.Value.Millisecond, writer.Free, 2);
writer.Advance(2);
}
}

/// <summary>
/// 写入UTC日期类型
/// </summary>
@@ -412,20 +597,35 @@ namespace JT808.Protocol.MessagePack
}
writer.Advance(8);
}

/// <summary>
/// 写入四个字节的日期类型,YYYYMMDD BCD[4] 数据形如:20200101
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_YYYYMMDD")]
public void WriteDateTime4(in DateTime value, in int fromBase = 16)
{
IntToBcd(value.Year, writer.Free, 2);
writer.Advance(2);
var span = writer.Free;
var yearSpan=value.ToString("yyyy").AsSpan();
span[0] = Convert.ToByte(yearSpan.Slice(0, 2).ToString(), fromBase);
span[1] = Convert.ToByte(yearSpan.Slice(2, 2).ToString(), fromBase);
span[2] = Convert.ToByte(value.ToString("MM"), fromBase);
span[3] = Convert.ToByte(value.ToString("dd"), fromBase);
writer.Advance(4);
span[0] = IntToBcd(value.Month);
span[1] = IntToBcd(value.Day);
writer.Advance(2);
}

/// <summary>
/// 写入四个字节的日期类型,YYYYMMDD BCD[4] 数据形如:20200101
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_YYYYMMDD(in DateTime value)
{
IntToBcd(value.Year, writer.Free, 2);
writer.Advance(2);
var span = writer.Free;
span[0] = IntToBcd(value.Month);
span[1] = IntToBcd(value.Day);
writer.Advance(2);
}

/// <summary>
@@ -433,25 +633,53 @@ namespace JT808.Protocol.MessagePack
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_YYYYMMDD")]
public void WriteDateTime4(in DateTime? value, in int fromBase = 16)
{
var span = writer.Free;
if (value==null || value.HasValue)
{
var span = writer.Free;
span[0] = 0;
span[1] = 0;
span[2] = 0;
span[3] = 0;
writer.Advance(4);
}
else
{
var yearSpan = value.Value.ToString("yyyy").AsSpan();
span[0] = Convert.ToByte(yearSpan.Slice(0, 2).ToString(), fromBase);
span[1] = Convert.ToByte(yearSpan.Slice(2, 2).ToString(), fromBase);
span[2] = Convert.ToByte(value.Value.ToString("MM"), fromBase);
span[3] = Convert.ToByte(value.Value.ToString("dd"), fromBase);
IntToBcd(value.Value.Year, writer.Free, 2);
writer.Advance(2);
var span = writer.Free;
span[0] = IntToBcd(value.Value.Month);
span[1] = IntToBcd(value.Value.Day);
writer.Advance(2);
}
}

/// <summary>
/// 写入四个字节的可空日期类型,YYYYMMDD BCD[4]数据形如:20200101
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_YYYYMMDD(in DateTime? value)
{
if (value == null || value.HasValue)
{
var span = writer.Free;
span[0] = 0;
span[1] = 0;
span[2] = 0;
span[3] = 0;
writer.Advance(4);
}
else
{
IntToBcd(value.Value.Year, writer.Free, 2);
writer.Advance(2);
var span = writer.Free;
span[0] = IntToBcd(value.Value.Month);
span[1] = IntToBcd(value.Value.Day);
writer.Advance(2);
}
writer.Advance(4);
}

/// <summary>
@@ -459,20 +687,35 @@ namespace JT808.Protocol.MessagePack
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_YYMMDD")]
public void WriteDateTime3(in DateTime value, in int fromBase = 16)
{
var span = writer.Free;
span[0] = Convert.ToByte(value.ToString("yy"), fromBase);
span[1] = Convert.ToByte(value.ToString("MM"), fromBase);
span[2] = Convert.ToByte(value.ToString("dd"), fromBase);
int yy = value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Month);
span[2] = IntToBcd(value.Day);
writer.Advance(3);
}
/// <summary>
/// 写入三个字节的日期类型,YYMMDD 数据形如:20200101
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_YYMMDD(in DateTime value)
{
var span = writer.Free;
int yy = value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Month);
span[2] = IntToBcd(value.Day);
writer.Advance(3);
}

/// <summary>
/// 写入三个字节的可空日期类型,YYMMDD 数据形如:20200101
/// </summary>
/// <param name="value"></param>
/// <param name="fromBase"></param>
[Obsolete("use WriteDateTime_YYMMDD")]
public void WriteDateTime3(in DateTime? value, in int fromBase = 16)
{
var span = writer.Free;
@@ -484,9 +727,32 @@ namespace JT808.Protocol.MessagePack
}
else
{
span[0] = Convert.ToByte(value.Value.ToString("yy"), fromBase);
span[1] = Convert.ToByte(value.Value.ToString("MM"), fromBase);
span[2] = Convert.ToByte(value.Value.ToString("dd"), fromBase);
int yy = value.Value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Value.Month);
span[2] = IntToBcd(value.Value.Day);
}
writer.Advance(3);
}
/// <summary>
/// 写入三个字节的可空日期类型,YYMMDD 数据形如:20200101
/// </summary>
/// <param name="value"></param>
public void WriteDateTime_YYMMDD(in DateTime? value)
{
var span = writer.Free;
if (value == null || value.HasValue)
{
span[0] = 0;
span[1] = 0;
span[2] = 0;
}
else
{
int yy = value.Value.Year - JT808Constants.DateLimitYear;
span[0] = IntToBcd(yy);
span[1] = IntToBcd(value.Value.Month);
span[2] = IntToBcd(value.Value.Day);
}
writer.Advance(3);
}


Завантаження…
Відмінити
Зберегти