@@ -240,6 +240,20 @@ namespace JT1078.Protocol.Test | |||
Assert.Equal("B7 6D FF EF 7D FB A9 9D FE A9 1F 37 77 F3 37 BE EF FB F7 FB FB BE 7D DF B7 FD FB 76 AF DE 77 65 C7 EF E3 FB BE FF DB 4E FF DB B7 63 FF EE EF D8 BE 1D 37 B7 7D E7 7D F3 C6 F7 FD F4 BE 1F F7 B7 55 FF 76 FC FE CE 7B FF B7 7D 3F F5 FF FE 76 6C DF FE 53 DB CF 6D FB BF FD DE B1 EF 3E 77 D3 3F 6E 9A BF BF FF DB F7 FD DB 7F 63 FF 6E EC F8 EE 1F FB FD 7F FB 7D 7C DB".ToHexBytes(), package.Bodies.ToArray()); | |||
} | |||
[Fact] | |||
public void Json1() | |||
{ | |||
var bytes = "30 31 63 64 81 88 11 35 01 12 34 56 78 10 01 30 00 00 01 6B B3 92 DA 05 00 78 B7 6D FF EF 7D FB A9 9D FE A9 1F 37 77 F3 37 BE EF FB F7 FB FB BE 7D DF B7 FD FB 76 AF DE 77 65 C7 EF E3 FB BE FF DB 4E FF DB B7 63 FF EE EF D8 BE 1D 37 B7 7D E7 7D F3 C6 F7 FD F4 BE 1F F7 B7 55 FF 76 FC FE CE 7B FF B7 7D 3F F5 FF FE 76 6C DF FE 53 DB CF 6D FB BF FD DE B1 EF 3E 77 D3 3F 6E 9A BF BF FF DB F7 FD DB 7F 63 FF 6E EC F8 EE 1F FB FD 7F FB 7D 7C DB".ToHexBytes(); | |||
string json = JT1078Serializer.Analyze(bytes); | |||
} | |||
[Fact] | |||
public void Json2() | |||
{ | |||
var bytes = "30 31 63 64 81 E2 10 88 01 12 34 56 78 10 01 10 00 00 01 6B B3 92 CA 7C 02 80 00 28 00 2E 00 00 00 01 61 E1 A2 BF 00 98 CF C0 EE 1E 17 28 34 07 78 8E 39 A4 03 FD DB D1 D5 46 BF B0 63 01 3F 59 AC 34 C9 7A 02 1A B9 6A 28 A4 2C 08".ToHexBytes(); | |||
string json = JT1078Serializer.Analyze(bytes); | |||
} | |||
[Fact] | |||
public void Label1Test1() | |||
{ | |||
@@ -71,11 +71,54 @@ namespace JT1078.Protocol.Extensions | |||
return hex; | |||
} | |||
/// <summary> | |||
/// Copyright (c) Microsoft. All rights reserved. | |||
/// Licensed under the MIT license. See LICENSE file in the project root for full license information. | |||
/// <see cref="DotNetty.Buffers.ByteBufferUtil"/> | |||
/// </summary> | |||
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(); | |||
} | |||
} | |||
@@ -14,7 +14,7 @@ | |||
<licenseUrl>https://github.com/SmallChi/JT1078/blob/master/LICENSE</licenseUrl> | |||
<license>https://github.com/SmallChi/JT1078/blob/master/LICENSE</license> | |||
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> | |||
<Version>1.0.2</Version> | |||
<Version>1.0.3</Version> | |||
<SignAssembly>false</SignAssembly> | |||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance> | |||
<PackageLicenseFile>LICENSE</PackageLicenseFile> | |||
@@ -22,7 +22,7 @@ | |||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' "> | |||
<PackageReference Include="System.Memory" Version="4.5.3" /> | |||
<PackageReference Include="System.Memory" Version="4.5.4" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
@@ -32,4 +32,7 @@ | |||
</None> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<PackageReference Include="System.Text.Json" Version="4.7.2" /> | |||
</ItemGroup> | |||
</Project> |
@@ -1,9 +1,13 @@ | |||
using JT1078.Protocol.Enums; | |||
using JT1078.Protocol.Extensions; | |||
using JT1078.Protocol.MessagePack; | |||
using System; | |||
using System.Collections.Concurrent; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Text.Json; | |||
namespace JT1078.Protocol | |||
{ | |||
@@ -111,5 +115,81 @@ namespace JT1078.Protocol | |||
return jT1078Package; | |||
} | |||
} | |||
public static byte[] AnalyzeJsonBuffer(ReadOnlySpan<byte> bytes, JsonWriterOptions options = default, int minBufferSize = 8096) | |||
{ | |||
byte[] buffer = JT1078ArrayPool.Rent(minBufferSize); | |||
try | |||
{ | |||
JT1078MessagePackReader jT1078MessagePackReader = new JT1078MessagePackReader(bytes); | |||
using (MemoryStream memoryStream = new MemoryStream()) | |||
using (Utf8JsonWriter writer = new Utf8JsonWriter(memoryStream, options)) | |||
{ | |||
writer.WriteStartObject(); | |||
var header = jT1078MessagePackReader.ReadUInt32(); | |||
writer.WriteString($"[{header}]头部", header.ReadNumber()); | |||
var val1 = jT1078MessagePackReader.ReadByte(); | |||
var label1 = new JT1078Label1(val1); | |||
var labelSpan = val1.ReadBinary(); | |||
writer.WriteStartObject($"[{labelSpan.ToString()}]object1[{val1.ReadNumber()}]"); | |||
writer.WriteNumber($"({labelSpan.Slice(0,2).ToString()})V[固定为2]", label1.V); | |||
writer.WriteNumber($"({labelSpan[2]})P[固定为0]", label1.P); | |||
writer.WriteNumber($"({labelSpan[3]})X[RTP头是否需要扩展位固定为0]", label1.X); | |||
writer.WriteNumber($"({labelSpan.Slice(4).ToString()})CC[固定为1]", label1.CC); | |||
writer.WriteEndObject(); | |||
var val2 = jT1078MessagePackReader.ReadByte(); | |||
var label2 = new JT1078Label2(val2); | |||
var label2Span = val2.ReadBinary(); | |||
writer.WriteStartObject($"[{label2Span.ToString()}]object2[{val2.ReadNumber()}]"); | |||
writer.WriteNumber($"({label2Span.Slice(0, 4).ToString()})M[确定是否是完整数据帧的边界]", label2.M); | |||
writer.WriteString($"({label2Span.Slice(4).ToString()})PT[负载类型]", label2.PT.ToString()); | |||
writer.WriteEndObject(); | |||
var sn = jT1078MessagePackReader.ReadUInt16(); | |||
writer.WriteNumber($"{sn.ReadNumber()}[序列号]", sn); | |||
var sim = jT1078MessagePackReader.ReadBCD(12); | |||
writer.WriteString($"[终端设备SIM卡号]", sim); | |||
var logicChannelNumber = jT1078MessagePackReader.ReadByte(); | |||
writer.WriteNumber($"{logicChannelNumber.ReadNumber()}[逻辑通道号]", logicChannelNumber); | |||
var val3 = jT1078MessagePackReader.ReadByte(); | |||
var label3 = new JT1078Label3(val3); | |||
var label3Span = val3.ReadBinary(); | |||
writer.WriteStartObject($"[{label3Span.ToString()}]object3[{val3.ReadNumber()}]"); | |||
writer.WriteString($"({label3Span.Slice(0, 4).ToString()})[数据类型]", label3.DataType.ToString()); | |||
writer.WriteString($"({label3Span.Slice(4).ToString()})[分包处理标记]", label3.SubpackageType.ToString()); | |||
writer.WriteEndObject(); | |||
if (label3.DataType != JT1078DataType.透传数据) | |||
{ | |||
var timestamp = jT1078MessagePackReader.ReadUInt64(); | |||
writer.WriteNumber($"{timestamp.ReadNumber()}[标识此RTP数据包当前帧的相对时间,单位毫秒(ms)]", timestamp); | |||
} | |||
if (label3.DataType != JT1078DataType.透传数据 && | |||
label3.DataType != JT1078DataType.音频帧) | |||
{ | |||
var lastIFrameInterval = jT1078MessagePackReader.ReadUInt16(); | |||
writer.WriteNumber($"{lastIFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastIFrameInterval); | |||
var lastFrameInterval = jT1078MessagePackReader.ReadUInt16(); | |||
writer.WriteNumber($"{lastFrameInterval.ReadNumber()}[该帧与上一个关键帧之间的时间间隔,单位毫秒(ms)]", lastFrameInterval); | |||
} | |||
var dataBodyLength = jT1078MessagePackReader.ReadUInt16(); | |||
writer.WriteNumber($"{dataBodyLength.ReadNumber()}[数据体长度]", dataBodyLength); | |||
var bodies = jT1078MessagePackReader.ReadRemainArray().ToArray(); | |||
writer.WriteString("[数据体]", string.Join(" ", (bodies).Select(p => p.ToString("X2")))); | |||
writer.WriteEndObject(); | |||
writer.Flush(); | |||
return memoryStream.ToArray(); | |||
} | |||
} | |||
finally | |||
{ | |||
JT1078ArrayPool.Return(buffer); | |||
} | |||
} | |||
public static string Analyze(ReadOnlySpan<byte> bytes,JsonWriterOptions options = default, int minBufferSize = 8096) | |||
{ | |||
string json = Encoding.UTF8.GetString(AnalyzeJsonBuffer(bytes, options, minBufferSize)); | |||
return json; | |||
} | |||
} | |||
} |