From 4208e223a0019d893995808c9eac060ed855138c Mon Sep 17 00:00:00 2001 From: "SmallChi(Koike)" <564952747@qq.com> Date: Sat, 10 Oct 2020 23:06:33 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=8D=87=E7=BA=A7=E5=BA=93=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E5=AF=B9=E5=BA=94=E7=9A=84dotnetcore=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=202.=E5=AE=8C=E5=96=84=E4=B8=80=E4=B8=8B?= =?UTF-8?q?=E9=99=84=E4=BB=B6=E7=9A=84=E5=88=86=E6=9E=90=E5=99=A8=203.?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dotnetcore.yml | 2 +- README.md | 11 +- ...ocol.Extensions.JTActiveSafety.Test.csproj | 6 +- ....Protocol.Extensions.JTActiveSafety.csproj | 4 +- .../JTActiveSafety.Protocol.Test.csproj | 4 +- .../Extensions/HexExtensions.cs | 172 ++++++++++++++++++ .../JTActiveSafety.Protocol.csproj | 5 +- .../JTActiveSafetySerializer.cs | 36 +++- 8 files changed, 223 insertions(+), 17 deletions(-) create mode 100644 src/JTActiveSafety.Protocol/Extensions/HexExtensions.cs diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index f23939b..ae99996 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -12,7 +12,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@master with: - dotnet-version: 3.1.101 + dotnet-version: 3.1.401 - name: dotnet info run: dotnet --info - name: dotnet restore diff --git a/README.md b/README.md index 033d44f..52a9ffd 100644 --- a/README.md +++ b/README.md @@ -7,14 +7,13 @@ JTActiveSafety协议、道路运输车辆主动安全智能防控系统-主动 [](https://github.com/SmallChi/JTActiveSafety/blob/master/LICENSE) -## 基于JT808扩展的JTActiveSafety消息协议 - ## NuGet安装 -| Package Name | Version | Downloads | -| --------------------- | -------------------------------------------------- | --------------------------------------------------- | -| Install-Package JT808 |  |  | -| Install-Package JT808.Protocol.Extensions.JTActiveSafety|  |  | +| Package Name | Version | Downloads| Remark | +| --------------------- | -------------------------------------------------- | --------------------------------------------------- |--------------------------------------------------- | +| Install-Package JTActiveSafety|  |  |主动安全的附件协议| +| Install-Package JT808 |  |  |基础JT808协议| +| Install-Package JT808.Protocol.Extensions.JTActiveSafety|  |  |基于JT808扩展的JTActiveSafety消息协议| ### JT808扩展协议消息对照表 diff --git a/src/JT808.Protocol.Extensions.JTActiveSafety.Test/JT808.Protocol.Extensions.JTActiveSafety.Test.csproj b/src/JT808.Protocol.Extensions.JTActiveSafety.Test/JT808.Protocol.Extensions.JTActiveSafety.Test.csproj index 5e58ae8..c0d3bbe 100644 --- a/src/JT808.Protocol.Extensions.JTActiveSafety.Test/JT808.Protocol.Extensions.JTActiveSafety.Test.csproj +++ b/src/JT808.Protocol.Extensions.JTActiveSafety.Test/JT808.Protocol.Extensions.JTActiveSafety.Test.csproj @@ -7,10 +7,10 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.3" /> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> <PackageReference Include="xunit" Version="2.4.1" /> - <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/src/JT808.Protocol.Extensions.JTActiveSafety/JT808.Protocol.Extensions.JTActiveSafety.csproj b/src/JT808.Protocol.Extensions.JTActiveSafety/JT808.Protocol.Extensions.JTActiveSafety.csproj index 28be818..9c94bbb 100644 --- a/src/JT808.Protocol.Extensions.JTActiveSafety/JT808.Protocol.Extensions.JTActiveSafety.csproj +++ b/src/JT808.Protocol.Extensions.JTActiveSafety/JT808.Protocol.Extensions.JTActiveSafety.csproj @@ -15,7 +15,7 @@ <licenseUrl>https://github.com/SmallChi/JTActiveSafety/blob/master/LICENSE</licenseUrl> <license>https://github.com/SmallChi/JTActiveSafety/blob/master/LICENSE</license> <GeneratePackageOnBuild>false</GeneratePackageOnBuild> - <Version>1.0.4</Version> + <Version>1.0.5</Version> <PackageLicenseFile>LICENSE</PackageLicenseFile> </PropertyGroup> @@ -35,7 +35,7 @@ </ItemGroup> <ItemGroup> - <PackageReference Include="JT808" Version="2.2.10" /> + <PackageReference Include="JT808" Version="2.2.12" /> </ItemGroup> diff --git a/src/JTActiveSafety.Protocol.Test/JTActiveSafety.Protocol.Test.csproj b/src/JTActiveSafety.Protocol.Test/JTActiveSafety.Protocol.Test.csproj index 7e6211a..39267b4 100644 --- a/src/JTActiveSafety.Protocol.Test/JTActiveSafety.Protocol.Test.csproj +++ b/src/JTActiveSafety.Protocol.Test/JTActiveSafety.Protocol.Test.csproj @@ -7,9 +7,9 @@ </PropertyGroup> <ItemGroup> - <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> + <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" /> <PackageReference Include="xunit" Version="2.4.1" /> - <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1"> + <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> </PackageReference> diff --git a/src/JTActiveSafety.Protocol/Extensions/HexExtensions.cs b/src/JTActiveSafety.Protocol/Extensions/HexExtensions.cs new file mode 100644 index 0000000..ff3420b --- /dev/null +++ b/src/JTActiveSafety.Protocol/Extensions/HexExtensions.cs @@ -0,0 +1,172 @@ +using System; + +namespace JTActiveSafety.Protocol.Extensions +{ + /// <summary> + /// + /// ref:"www.codeproject.com/tips/447938/high-performance-csharp-byte-array-to-hex-string-t" + /// </summary> + public static partial class HexExtensions + { + public static string ToHexString(this byte[] source) + { + return HexUtil.DoHexDump(source, 0, source.Length).ToUpper(); + } + + public static int WriteHexStringLittle(byte[] bytes, int offset, string data, int len) + { + if (data == null) data = ""; + data = data.Replace(" ", ""); + int startIndex = 0; + if (data.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + { + startIndex = 2; + } + int length = len; + if (length == -1) + { + length = (data.Length - startIndex) / 2; + } + int noOfZero = length * 2 + startIndex - data.Length; + if (noOfZero > 0) + { + data = data.Insert(startIndex, new string('0', noOfZero)); + } + int byteIndex = 0; + while (startIndex < data.Length && byteIndex < length) + { + bytes[offset + byteIndex] = Convert.ToByte(data.Substring(startIndex, 2), 16); + startIndex += 2; + byteIndex++; + } + return length; + } + + /// <summary> + /// 16进制字符串转16进制数组 + /// </summary> + /// <param name="hexString"></param> + /// <param name="separator"></param> + /// <returns></returns> + public static byte[] ToHexBytes(this string hexString) + { + hexString = hexString.Replace(" ", ""); + byte[] buf = new byte[hexString.Length / 2]; + ReadOnlySpan<char> readOnlySpan = hexString.AsSpan(); + for (int i = 0; i < hexString.Length; i++) + { + if (i % 2 == 0) + { + buf[i / 2] = Convert.ToByte(readOnlySpan.Slice(i, 2).ToString(), 16); + } + } + return buf; + } + + public static string ReadHexStringLittle(ReadOnlySpan<byte> read, ref int offset, int len) + { + ReadOnlySpan<byte> source = read.Slice(offset, len); + string hex = HexUtil.DoHexDump(read, offset, len); + offset += len; + return hex; + } + + public static string ReadNumber(this byte value, string format = "X2") + { + return value.ToString(format); + } + public static string ReadNumber(this int value, string format = "X8") + { + return value.ToString(format); + } + public static string ReadNumber(this uint value, string format = "X8") + { + return value.ToString(format); + } + public static string ReadNumber(this long value, string format = "X16") + { + return value.ToString(format); + } + public static string ReadNumber(this ulong value, string format = "X16") + { + return value.ToString(format); + } + public static string ReadNumber(this short value, string format = "X4") + { + return value.ToString(format); + } + public static string ReadNumber(this ushort value, string format = "X4") + { + return value.ToString(format); + } + public static ReadOnlySpan<char> ReadBinary(this ushort value) + { + return System.Convert.ToString(value, 2).PadLeft(16, '0').AsSpan(); + } + public static ReadOnlySpan<char> ReadBinary(this short value) + { + return System.Convert.ToString(value, 2).PadLeft(16, '0').AsSpan(); + } + public static ReadOnlySpan<char> ReadBinary(this uint value) + { + return System.Convert.ToString(value, 2).PadLeft(32, '0').AsSpan(); + } + public static ReadOnlySpan<char> ReadBinary(this int value) + { + return System.Convert.ToString(value, 2).PadLeft(32, '0').AsSpan(); + } + public static ReadOnlySpan<char> ReadBinary(this byte value) + { + return System.Convert.ToString(value, 2).PadLeft(8, '0').AsSpan(); + } + + } + + public static class HexUtil + { + static readonly char[] HexdumpTable = new char[256 * 4]; + static HexUtil() + { + char[] digits = "0123456789ABCDEF".ToCharArray(); + for (int i = 0; i < 256; i++) + { + HexdumpTable[i << 1] = digits[(int)((uint)i >> 4 & 0x0F)]; + HexdumpTable[(i << 1) + 1] = digits[i & 0x0F]; + } + } + + public static string DoHexDump(ReadOnlySpan<byte> buffer, int fromIndex, int length) + { + if (length == 0) + { + return ""; + } + int endIndex = fromIndex + length; + var buf = new char[length << 1]; + int srcIdx = fromIndex; + int dstIdx = 0; + for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) + { + Array.Copy(HexdumpTable, buffer[srcIdx] << 1, buf, dstIdx, 2); + } + return new string(buf); + } + + public static string DoHexDump(byte[] array, int fromIndex, int length) + { + if (length == 0) + { + return ""; + } + int endIndex = fromIndex + length; + var buf = new char[length << 1]; + int srcIdx = fromIndex; + int dstIdx = 0; + for (; srcIdx < endIndex; srcIdx++, dstIdx += 2) + { + Array.Copy(HexdumpTable, (array[srcIdx] & 0xFF) << 1, buf, dstIdx, 2); + } + return new string(buf); + } + } +} diff --git a/src/JTActiveSafety.Protocol/JTActiveSafety.Protocol.csproj b/src/JTActiveSafety.Protocol/JTActiveSafety.Protocol.csproj index 57c943e..4cb48a3 100644 --- a/src/JTActiveSafety.Protocol/JTActiveSafety.Protocol.csproj +++ b/src/JTActiveSafety.Protocol/JTActiveSafety.Protocol.csproj @@ -19,7 +19,10 @@ <PackageLicenseFile>LICENSE</PackageLicenseFile> </PropertyGroup> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> - <PackageReference Include="System.Memory" Version="4.5.3" /> + <PackageReference Include="System.Memory" Version="4.5.4" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="System.Text.Json" Version="4.7.2" /> </ItemGroup> <ItemGroup> <None Include="..\..\LICENSE"> diff --git a/src/JTActiveSafety.Protocol/JTActiveSafetySerializer.cs b/src/JTActiveSafety.Protocol/JTActiveSafetySerializer.cs index 023c64c..4751de2 100644 --- a/src/JTActiveSafety.Protocol/JTActiveSafetySerializer.cs +++ b/src/JTActiveSafety.Protocol/JTActiveSafetySerializer.cs @@ -1,14 +1,18 @@ using JTActiveSafety.Protocol.Buffers; +using JTActiveSafety.Protocol.Extensions; using JTActiveSafety.Protocol.MessagePack; using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Text; +using System.Text.Json; namespace JTActiveSafety.Protocol { public static class JTActiveSafetySerializer { - public static byte[] Serialize(JTActiveSafetyPackage package, int minBufferSize = 4096) + public static byte[] Serialize(JTActiveSafetyPackage package, int minBufferSize = 65 * 1024) { byte[] buffer = JTActiveSafetyArrayPool.Rent(minBufferSize); try @@ -17,7 +21,7 @@ namespace JTActiveSafety.Protocol writer.WriteUInt32(package.FH_Flag); writer.WriteString(package.FileName); writer.WriteUInt32(package.Offset); - writer.WriteUInt32(package.Length); + writer.WriteUInt32((uint)package.Bodies.Length); writer.WriteArray(package.Bodies); return writer.FlushAndGetArray(); } @@ -38,5 +42,33 @@ namespace JTActiveSafety.Protocol jTActiveSafetyPackage.Bodies = reader.ReadRemainArray().ToArray(); return jTActiveSafetyPackage; } + + public static byte[] AnalyzeJsonBuffer(ReadOnlySpan<byte> bytes, JsonWriterOptions options = default) + { + JTActiveSafetyMessagePackReader reader = new JTActiveSafetyMessagePackReader(bytes); + using (MemoryStream memoryStream = new MemoryStream()) + using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStream, options)) + { + writer.WriteStartObject(); + var header = reader.ReadUInt32(); + writer.WriteString($"[{header}]头部", header.ReadNumber()); + var FileName = reader.ReadString(50); + writer.WriteString($"[文件名称]", FileName); + var offset = reader.ReadUInt32(); + writer.WriteNumber($"{offset}[数据偏移量]", offset); + var length = reader.ReadUInt32(); + writer.WriteNumber($"{length}[数据长度]", length); + var bodies = reader.ReadRemainArray().ToArray(); + writer.WriteString("[数据体]", string.Join(" ", (bodies).Select(p => p.ToString("X2")))); + writer.WriteEndObject(); + writer.Flush(); + return memoryStream.ToArray(); + } + } + public static string Analyze(ReadOnlySpan<byte> bytes, JsonWriterOptions options = default) + { + string json = Encoding.UTF8.GetString(AnalyzeJsonBuffer(bytes, options)); + return json; + } } }