@@ -6,6 +6,14 @@ | |||||
<IsPackable>false</IsPackable> | <IsPackable>false</IsPackable> | ||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'"> | |||||
<LangVersion>7.2</LangVersion> | |||||
</PropertyGroup> | |||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | |||||
<LangVersion>7.2</LangVersion> | |||||
</PropertyGroup> | |||||
<ItemGroup> | <ItemGroup> | ||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" /> | ||||
<PackageReference Include="xunit" Version="2.3.1" /> | <PackageReference Include="xunit" Version="2.3.1" /> | ||||
@@ -3,6 +3,8 @@ using System.Collections.Generic; | |||||
using System.Text; | using System.Text; | ||||
using Xunit; | using Xunit; | ||||
using GBNewEnergy.Protocol.Extensions; | using GBNewEnergy.Protocol.Extensions; | ||||
using GBNewEnergy.Protocol.UpStream; | |||||
using GBNewEnergy.Protocol.Enums; | |||||
namespace GBNewEnergy.Protocol.Test | namespace GBNewEnergy.Protocol.Test | ||||
{ | { | ||||
@@ -15,5 +17,74 @@ namespace GBNewEnergy.Protocol.Test | |||||
byte[] body = "12 05 0F 0F 29 15 01 02 01 01 00 00 00 00 33 54 19 B1 23 06 58 01 00 06 9F 00 00 02 01 01 03 47 00 00 4E 20 47 10 D6 27 24 05 01 06 CA 3C 03 01 57 8E C3 06 01 38 0D 5C 01 01 0D 48 01 01 43 01 0B 42 07 00 00 00 00 00 00 00 00 00 08 01 01 19 B1 23 06 00 C0 00 01 C0 0D 48 0D 48 0D 48 0D 48 0D 52 0D 48 0D 48 0D 52 0D 52 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 48 0D 52 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 48 0D 52 0D 48 0D 48 0D 48 0D 5C 0D 52 0D 52 0D 52 0D 5C 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 48 0D 52 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 09 01 01 00 48 43 43 43 43 43 43 43 43 43 43 42 43 42 42 42 42 42 43 42 42 42 42 42 42 42 43 42 42 42 43 42 42 42 42 42 42 42 42 42 42 42 42 42 42 43 42 42 43 42 42 42 42 42 42 42 42 43 42 42 43 43 43 42 43 43 43 43 43 43 43 43 43 48".ToHexBytes(); | byte[] body = "12 05 0F 0F 29 15 01 02 01 01 00 00 00 00 33 54 19 B1 23 06 58 01 00 06 9F 00 00 02 01 01 03 47 00 00 4E 20 47 10 D6 27 24 05 01 06 CA 3C 03 01 57 8E C3 06 01 38 0D 5C 01 01 0D 48 01 01 43 01 0B 42 07 00 00 00 00 00 00 00 00 00 08 01 01 19 B1 23 06 00 C0 00 01 C0 0D 48 0D 48 0D 48 0D 48 0D 52 0D 48 0D 48 0D 52 0D 52 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 48 0D 52 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 48 0D 52 0D 48 0D 48 0D 48 0D 5C 0D 52 0D 52 0D 52 0D 5C 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 48 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 52 0D 48 0D 48 0D 48 0D 48 0D 52 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 48 0D 48 0D 52 0D 48 0D 52 0D 52 09 01 01 00 48 43 43 43 43 43 43 43 43 43 43 42 43 42 42 42 42 42 43 42 42 42 42 42 42 42 43 42 42 42 43 42 42 42 42 42 42 42 42 42 42 42 42 42 42 43 42 42 43 42 42 42 42 42 42 42 42 43 42 42 43 43 43 42 43 43 43 43 43 43 43 43 43 48".ToHexBytes(); | ||||
NEPackage nEPackage = new NEPackage(header, body); | NEPackage nEPackage = new NEPackage(header, body); | ||||
} | } | ||||
[Fact] | |||||
public void NELoginUpStreamConstructor1_1() | |||||
{ | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F" | |||||
// "12 06 07 11 04 1B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31" | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F 12 06 07 11 04 1B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 D7" | |||||
NELoginUpStream nELoginUpStream = new NELoginUpStream("LGHC4V1D3HE202652", "64743066405", 1,1,new string[] { "1"}); | |||||
NEPackage nEPackage = new NEPackage("LGHC4V1D3HE202652", Enums.MsgId.login,Enums.AskId.cmd, nELoginUpStream, EncryptMethod.None); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NELoginUpStreamConstructor1_2() | |||||
{ | |||||
byte[] header = "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F".ToHexBytes(); | |||||
byte[] body = "12 06 07 11 04 1B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 D7".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(header, body); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NELoginUpStreamConstructor2_1() | |||||
{ | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F" | |||||
// "12 06 07 12 23 3B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31" | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F 12 06 07 12 23 3B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 D3" | |||||
NELoginUpStream nELoginUpStream = new NELoginUpStream("LGHC4V1D3HE202652", "64743066405", 1, 1, new string[] { "1" }); | |||||
NEPackage nEPackage = new NEPackage("LGHC4V1D3HE202652", Enums.MsgId.login, Enums.AskId.cmd, nELoginUpStream, EncryptMethod.None); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NELoginUpStreamConstructor2_2() | |||||
{ | |||||
byte[] header = "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F".ToHexBytes(); | |||||
byte[] body = "12 06 07 12 23 3B 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 D3".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(header, body); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NELoginUpStreamConstructor3_1() | |||||
{ | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F" | |||||
// "06 07 12 37 02 00 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31" | |||||
// "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F 06 07 12 37 02 00 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 EC" | |||||
NELoginUpStream nELoginUpStream = new NELoginUpStream("LGHC4V1D3HE202652", "64743066405", 1, 1, new string[] { "1" }); | |||||
NEPackage nEPackage = new NEPackage("LGHC4V1D3HE202652", Enums.MsgId.login, Enums.AskId.cmd, nELoginUpStream, EncryptMethod.None); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NELoginUpStreamConstructor3_2() | |||||
{ | |||||
byte[] header = "23 23 01 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 1F".ToHexBytes(); | |||||
byte[] body = "06 07 12 37 02 00 00 01 36 34 37 34 33 30 36 36 34 30 35 00 00 00 00 00 00 00 00 00 01 01 31 EC".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(header, body); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -9,5 +9,15 @@ namespace GBNewEnergy.Protocol.Response | |||||
protected NELoginDownStream(byte[] buffer) : base(buffer) | protected NELoginDownStream(byte[] buffer) : base(buffer) | ||||
{ | { | ||||
} | } | ||||
protected NELoginDownStream(string vin) : base(vin) | |||||
{ | |||||
} | |||||
public override void ToBuffer() | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -6,6 +6,7 @@ namespace GBNewEnergy.Protocol.Enums | |||||
{ | { | ||||
public enum ErrorCode | public enum ErrorCode | ||||
{ | { | ||||
BeginFlagError = 1001 | |||||
BeginFlagError = 1001, | |||||
BCCCodeError = 1001 | |||||
} | } | ||||
} | } |
@@ -1,103 +0,0 @@ | |||||
using System; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.Extensions | |||||
{ | |||||
public static class BinaryExtensions | |||||
{ | |||||
/// <summary> | |||||
/// 从高位到低位转成int | |||||
/// </summary> | |||||
/// <param name="buf"></param> | |||||
/// <param name="offset"></param> | |||||
/// <param name="len"></param> | |||||
/// <returns></returns> | |||||
public static int ToIntH2L(this byte[] bytes, int offset, int len) | |||||
{ | |||||
int result = 0; | |||||
for (int i = offset; i < offset + len; i++) | |||||
{ | |||||
result += bytes[i] * (int)Math.Pow(256, len + offset - i - 1); | |||||
} | |||||
return result; | |||||
} | |||||
/// <summary> | |||||
/// 字符串到字节数组 | |||||
/// </summary> | |||||
/// <param name="data"></param> | |||||
/// <param name="coding"></param> | |||||
public static byte[] ToBytes(this string data, Encoding coding) | |||||
{ | |||||
return coding.GetBytes(data); | |||||
} | |||||
/// <summary> | |||||
/// 字符串到字节数组 | |||||
/// </summary> | |||||
/// <param name="data"></param> | |||||
public static byte[] ToBytes(this string data) | |||||
{ | |||||
return Encoding.ASCII.GetBytes(data); | |||||
} | |||||
/// <summary> | |||||
/// 整型到字节数组 | |||||
/// </summary> | |||||
/// <param name="data">int数据</param> | |||||
/// <param name="len">int填入长度</param> | |||||
public static byte[] ToBytes(this int data, int len) | |||||
{ | |||||
byte[] bytes = new byte[len]; | |||||
int n = 1; | |||||
for (int i = 0; i < len; i++) | |||||
{ | |||||
bytes[i] = (byte)(data >> 8 * (len - n)); | |||||
n++; | |||||
} | |||||
return bytes; | |||||
} | |||||
/// <summary> | |||||
/// 异或 | |||||
/// </summary> | |||||
/// <param name="buf"></param> | |||||
/// <param name="offset"></param> | |||||
/// <param name="len"></param> | |||||
/// <returns></returns> | |||||
public static byte ToXor(this byte[] buf, int offset, int len) | |||||
{ | |||||
byte result = buf[offset]; | |||||
for (int i = offset + 1; i < offset + len; i++) | |||||
{ | |||||
result = (byte)(result ^ buf[i]); | |||||
} | |||||
return result; | |||||
} | |||||
/// <summary> | |||||
/// 字节数组转16进制字符串 | |||||
/// </summary> | |||||
/// <param name="bytes"></param> | |||||
/// <param name="separator">默认 " "</param> | |||||
/// <returns></returns> | |||||
public static string ToHexString(this byte[] bytes,string separator=" ") | |||||
{ | |||||
return string.Join(separator, bytes.Select(s => s.ToString("X2"))); | |||||
} | |||||
/// <summary> | |||||
/// 16进制字符串转16进制数组 | |||||
/// </summary> | |||||
/// <param name="hexString"></param> | |||||
/// <param name="separator"></param> | |||||
/// <returns></returns> | |||||
public static byte[] ToHexBytes(this string hexString, string separator = " ") | |||||
{ | |||||
return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,134 @@ | |||||
using System; | |||||
using System.IO; | |||||
using System.Linq; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.Extensions | |||||
{ | |||||
public static class NEExtensions | |||||
{ | |||||
/// <summary> | |||||
/// 日期限制于2000年 | |||||
/// </summary> | |||||
private const int DateLimitYear = 2000; | |||||
public static DateTime ReadDateTimeLittle(this byte[] read,int offset, int len) | |||||
{ | |||||
return new DateTime( | |||||
read[offset] + DateLimitYear, | |||||
read[offset++], | |||||
read[offset++], | |||||
read[offset++], | |||||
read[offset++], | |||||
read[offset++]); | |||||
} | |||||
public static ushort ReadUShortH2LLittle(this byte[] read, int offset, int len) | |||||
{ | |||||
int result = 0; | |||||
for (int i = offset; i < offset + len; i++) | |||||
{ | |||||
result += read[i] * (int)Math.Pow(256, len + offset - i - 1); | |||||
} | |||||
return (ushort)result; | |||||
} | |||||
public static string ReadStringLittle(this byte[] read, int offset, int len,Encoding coding) | |||||
{ | |||||
return coding.GetString(read, offset, len).Trim('\0'); | |||||
} | |||||
public static string ReadStringLittle(this byte[] read, int offset, int len) | |||||
{ | |||||
return Encoding.ASCII.GetString(read, offset, len).Trim('\0'); | |||||
} | |||||
public static void WriteLittle(this byte[] write,string str, int offset, Encoding coding) | |||||
{ | |||||
byte[] strByte = coding.GetBytes(str); | |||||
Array.Copy(strByte, 0, write, offset, strByte.Length); | |||||
} | |||||
public static void WriteLittle(this byte[] write, string str, int offset) | |||||
{ | |||||
byte[] strByte = Encoding.ASCII.GetBytes(str); | |||||
Array.Copy(strByte, 0, write, offset, strByte.Length); | |||||
} | |||||
public static void WriteLittle(this byte[] write,int data ,int offset,int len) | |||||
{ | |||||
int n = 1; | |||||
for (int i = 0; i < len; i++) | |||||
{ | |||||
write[offset] = (byte)(data >> 8 * (len - n)); | |||||
n++; | |||||
offset++; | |||||
} | |||||
} | |||||
public static void WriteLittle(this byte[] write, ushort data, int offset, int len) | |||||
{ | |||||
int n = 1; | |||||
for (int i = 0; i < len; i++) | |||||
{ | |||||
write[offset] = (byte)(data >> 8 * (len - n)); | |||||
n++; | |||||
offset++; | |||||
} | |||||
} | |||||
public static void WriteLittle(this byte[] write, byte[] bytes, int offset, int len) | |||||
{ | |||||
Array.Copy(bytes, 0, write, offset, len); | |||||
} | |||||
public static void WriteLittle(this byte[] write, DateTime date, int offset,int len) | |||||
{ | |||||
write[offset] = (byte)(date.Year - DateLimitYear); | |||||
write[offset++] = (byte)date.Month; | |||||
write[offset++] = (byte)date.Day; | |||||
write[offset++] = (byte)date.Hour; | |||||
write[offset++] = (byte)date.Minute; | |||||
write[offset++] = (byte)date.Second; | |||||
} | |||||
/// <summary> | |||||
/// 异或 | |||||
/// </summary> | |||||
/// <param name="buf"></param> | |||||
/// <param name="offset"></param> | |||||
/// <param name="len"></param> | |||||
/// <returns></returns> | |||||
public static byte ToXor(this byte[] buf, int offset, int len) | |||||
{ | |||||
byte result = buf[offset]; | |||||
for (int i = offset + 1; i < offset + len; i++) | |||||
{ | |||||
result = (byte)(result ^ buf[i]); | |||||
} | |||||
return result; | |||||
} | |||||
/// <summary> | |||||
/// 字节数组转16进制字符串 | |||||
/// </summary> | |||||
/// <param name="bytes"></param> | |||||
/// <param name="separator">默认 " "</param> | |||||
/// <returns></returns> | |||||
public static string ToHexString(this byte[] bytes,string separator=" ") | |||||
{ | |||||
return string.Join(separator, bytes.Select(s => s.ToString("X2"))); | |||||
} | |||||
/// <summary> | |||||
/// 16进制字符串转16进制数组 | |||||
/// </summary> | |||||
/// <param name="hexString"></param> | |||||
/// <param name="separator"></param> | |||||
/// <returns></returns> | |||||
public static byte[] ToHexBytes(this string hexString, string separator = " ") | |||||
{ | |||||
return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); | |||||
} | |||||
} | |||||
} |
@@ -2,6 +2,6 @@ | |||||
{ | { | ||||
public interface IBuffered | public interface IBuffered | ||||
{ | { | ||||
byte[] ToBuffer(); | |||||
void ToBuffer(); | |||||
} | } | ||||
} | } |
@@ -11,7 +11,7 @@ namespace GBNewEnergy.Protocol | |||||
/// VIN - 登录流水号,过期时间(每天置1) | /// VIN - 登录流水号,过期时间(每天置1) | ||||
/// 车载终端登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天 | /// 车载终端登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天 | ||||
/// </summary> | /// </summary> | ||||
private static readonly ConcurrentDictionary<string, (ushort LoginNum, DateTime ExpirationTime)> LoginNumDict; | |||||
protected static readonly ConcurrentDictionary<string, (ushort LoginNum, DateTime ExpirationTime)> LoginNumDict; | |||||
static NEBodies() | static NEBodies() | ||||
{ | { | ||||
@@ -26,6 +26,7 @@ namespace GBNewEnergy.Protocol | |||||
/// <summary> | /// <summary> | ||||
/// 数据采集时间 | /// 数据采集时间 | ||||
/// 采用北京时间 | |||||
/// </summary> | /// </summary> | ||||
public DateTime CurrentDateTime { get; protected set; } | public DateTime CurrentDateTime { get; protected set; } | ||||
@@ -36,37 +37,11 @@ namespace GBNewEnergy.Protocol | |||||
Buffer = buffer; | Buffer = buffer; | ||||
} | } | ||||
protected NEBodies(string vin,object[] parameter) | |||||
protected NEBodies(string vin) | |||||
{ | { | ||||
if (LoginNumDict.ContainsKey(vin)) | |||||
{ | |||||
(ushort LoginNum, DateTime ExpirationTime) temp; | |||||
if(LoginNumDict.TryGetValue(vin,out temp)) | |||||
{ | |||||
// 不等于当天 | |||||
if(temp.ExpirationTime != DateTime.Now.Date) | |||||
{ | |||||
LoginNum = 1; | |||||
LoginNumDict.TryUpdate(vin, (LoginNum, DateTime.Now.Date), temp); | |||||
} | |||||
else | |||||
{// 自增1 更新字典 | |||||
LoginNum = temp.LoginNum++; | |||||
LoginNumDict.TryUpdate(vin, (LoginNum, DateTime.Now.Date), temp); | |||||
} | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
LoginNum = 1; | |||||
LoginNumDict.TryAdd(vin,(LoginNum, DateTime.Now.Date)); | |||||
} | |||||
CurrentDateTime = DateTime.Now; | CurrentDateTime = DateTime.Now; | ||||
} | } | ||||
public byte[] ToBuffer() | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
public abstract void ToBuffer(); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,28 @@ | |||||
using GBNewEnergy.Protocol.Enums; | |||||
using GBNewEnergy.Protocol.UpStream; | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol | |||||
{ | |||||
public class NEBodiesFactory | |||||
{ | |||||
/// <summary> | |||||
/// 通过命令id获取数据体 | |||||
/// </summary> | |||||
/// <param name="msgId"></param> | |||||
/// <param name="buf"></param> | |||||
/// <returns></returns> | |||||
public static NEBodies GetNEBodiesByMsgId(MsgId msgId,byte[] buf) | |||||
{ | |||||
switch (msgId) | |||||
{ | |||||
case MsgId.login: | |||||
return new NELoginUpStream(buf); | |||||
default: | |||||
return null; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -2,8 +2,6 @@ | |||||
using GBNewEnergy.Protocol.Exceptions; | using GBNewEnergy.Protocol.Exceptions; | ||||
using GBNewEnergy.Protocol.Extensions; | using GBNewEnergy.Protocol.Extensions; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol | namespace GBNewEnergy.Protocol | ||||
@@ -15,15 +13,53 @@ namespace GBNewEnergy.Protocol | |||||
{ | { | ||||
public NEPackage(byte[] header,byte[] body) | public NEPackage(byte[] header,byte[] body) | ||||
{ | { | ||||
// 判断头部异常 | |||||
if (header[0] != BeginFlag && header[1] == BeginFlag) throw new NEException(ErrorCode.BeginFlagError, $"{header[0]},{header[1]}"); | if (header[0] != BeginFlag && header[1] == BeginFlag) throw new NEException(ErrorCode.BeginFlagError, $"{header[0]},{header[1]}"); | ||||
// 组包 | |||||
byte[] packageBuffer = new byte[header.Length + body.Length]; | |||||
Array.Copy(header, 0, packageBuffer, 0, header.Length); | |||||
Array.Copy(body, 0, packageBuffer, header.Length, body.Length); | |||||
// 获取数据单元长度 | |||||
DataUnitLength = header.ReadUShortH2LLittle(22, 2); | |||||
// 进行BCC校验码 | |||||
// 校验位=报文长度 - 最后一位(校验位) - 偏移量(2) | |||||
int checkBit = packageBuffer.Length - 1 - 2; | |||||
byte bCCCode = packageBuffer.ToXor(2, checkBit); | |||||
byte bCCCode2 = body[body.Length - 1]; | |||||
if (bCCCode != bCCCode2) throw new NEException(ErrorCode.BCCCodeError, $"request:{bCCCode2}!=calculate:{bCCCode}"); | |||||
MsgId = (MsgId)header[2]; | MsgId = (MsgId)header[2]; | ||||
AskId = (AskId)header[3]; | AskId = (AskId)header[3]; | ||||
VIN = Encoding.ASCII.GetString(header, 4, 17).Trim('\0'); | |||||
VIN = header.ReadStringLittle(4, 17); | |||||
EncryptMethod = (EncryptMethod)header[21]; | EncryptMethod = (EncryptMethod)header[21]; | ||||
DataUnitLength = header.ToIntH2L(22, 2); | |||||
// 通过命令id获取数据体 | |||||
Bodies = NEBodiesFactory.GetNEBodiesByMsgId(MsgId, body); | |||||
Buffer = packageBuffer; | |||||
Header = header; | Header = header; | ||||
} | } | ||||
public NEPackage(byte[] buf) | |||||
{ | |||||
if (buf[0] != BeginFlag && buf[1] == BeginFlag) throw new NEException(ErrorCode.BeginFlagError, $"{buf[0]},{buf[1]}"); | |||||
MsgId = (MsgId)buf[2]; | |||||
AskId = (AskId)buf[3]; | |||||
VIN = buf.ReadStringLittle(4, 17); | |||||
EncryptMethod = (EncryptMethod)buf[21]; | |||||
DataUnitLength = buf.ReadUShortH2LLittle(22, 2); | |||||
// 进行BCC校验码 | |||||
// 校验位 = 报文长度 - 最后一位(校验位) - 偏移量(2) | |||||
int checkBit = buf.Length - CheckBit - 2; | |||||
byte bCCCode = buf.ToXor(2, checkBit); | |||||
byte bCCCode2 = buf[buf.Length - CheckBit]; | |||||
if (bCCCode != bCCCode2) | |||||
{ | |||||
throw new NEException(ErrorCode.BCCCodeError, $"request:{bCCCode2}!=calculate:{bCCCode}"); | |||||
} | |||||
Bodies = NEBodiesFactory.GetNEBodiesByMsgId(MsgId, buf); | |||||
Buffer = new byte[buf.Length + Bodies.Buffer.Length]; | |||||
Array.Copy(buf, 0, Buffer, 0, buf.Length); | |||||
Array.Copy(Bodies.Buffer, 0, Buffer, buf.Length, Bodies.Buffer.Length); | |||||
} | |||||
public NEPackage(string vin, MsgId msgId, AskId askId, NEBodies bodies,EncryptMethod encryptMethod) | public NEPackage(string vin, MsgId msgId, AskId askId, NEBodies bodies,EncryptMethod encryptMethod) | ||||
{ | { | ||||
MsgId = msgId; | MsgId = msgId; | ||||
@@ -43,6 +79,10 @@ namespace GBNewEnergy.Protocol | |||||
/// </summary> | /// </summary> | ||||
public const byte BeginFlag = 0x23; | public const byte BeginFlag = 0x23; | ||||
/// <summary> | /// <summary> | ||||
/// 校验位1字节 | |||||
/// </summary> | |||||
private const int CheckBit = 1; | |||||
/// <summary> | |||||
/// 命令标识 | /// 命令标识 | ||||
/// </summary> | /// </summary> | ||||
public MsgId MsgId { get; private set; } | public MsgId MsgId { get; private set; } | ||||
@@ -79,27 +119,23 @@ namespace GBNewEnergy.Protocol | |||||
public byte[] Buffer { get; private set; } | public byte[] Buffer { get; private set; } | ||||
public override string ToString() | |||||
{ | |||||
return this.Header.ToHexString()+" " +this.Buffer.ToHexString(); | |||||
} | |||||
private void ToBuffer() | private void ToBuffer() | ||||
{ | { | ||||
// 固定单元长度 | // 固定单元长度 | ||||
DataUnitLength = Bodies.Buffer.Length; | DataUnitLength = Bodies.Buffer.Length; | ||||
Buffer = new byte[HeaderFixedByteLength + 1 + DataUnitLength]; | |||||
Buffer = new byte[HeaderFixedByteLength + DataUnitLength + CheckBit]; | |||||
Buffer[0] = BeginFlag; | Buffer[0] = BeginFlag; | ||||
Buffer[1] = BeginFlag; | Buffer[1] = BeginFlag; | ||||
Buffer[2] = (byte)MsgId; | Buffer[2] = (byte)MsgId; | ||||
Buffer[3] = (byte)AskId; | Buffer[3] = (byte)AskId; | ||||
Array.Copy(VIN.ToBytes(), 0, Buffer, 4, 20); | |||||
Buffer.WriteLittle(VIN, 4); | |||||
Buffer[21] = (byte)EncryptMethod; | Buffer[21] = (byte)EncryptMethod; | ||||
Array.Copy(DataUnitLength.ToBytes(2), 0, Buffer, 22, 23); | |||||
Array.Copy(Bodies.Buffer, 0, Buffer, 24, DataUnitLength); | |||||
BCCCode = Buffer.ToXor(2, 23 + DataUnitLength); | |||||
Buffer.WriteLittle(DataUnitLength, 22, 2); | |||||
Buffer.WriteLittle(Bodies.Buffer, 24, DataUnitLength); | |||||
BCCCode = Buffer.ToXor(2, (HeaderFixedByteLength + DataUnitLength - 1)); | |||||
Buffer[HeaderFixedByteLength + DataUnitLength] = BCCCode; | Buffer[HeaderFixedByteLength + DataUnitLength] = BCCCode; | ||||
Array.Copy(Buffer,0, Header, 0, 22); | |||||
Header = new byte[HeaderFixedByteLength]; | |||||
Array.Copy(Buffer, 0, Header, 0, HeaderFixedByteLength); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -1,14 +1,57 @@ | |||||
using System; | |||||
using GBNewEnergy.Protocol.Extensions; | |||||
using System; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Text; | using System.Text; | ||||
namespace GBNewEnergy.Protocol.Request | |||||
namespace GBNewEnergy.Protocol.UpStream | |||||
{ | { | ||||
public class NELoginUpStream: NEBodies | |||||
public class NELoginUpStream : NEBodies | |||||
{ | { | ||||
protected NELoginUpStream(byte[] buffer) : base(buffer) | |||||
public NELoginUpStream(byte[] buffer) : base(buffer) | |||||
{ | { | ||||
CurrentDateTime = buffer.ReadDateTimeLittle(0, 6); | |||||
LoginNum = buffer.ReadUShortH2LLittle(6, 2); | |||||
SIM = buffer.ReadStringLittle(8, 20); | |||||
BatteryCount = buffer[28]; | |||||
BatteryLength = buffer[29]; | |||||
List<string> batteryNos = new List<string>(); | |||||
for (int i = 0; i < BatteryCount; i++) | |||||
{ | |||||
batteryNos.Add(buffer.ReadStringLittle(i * BatteryLength + 30, BatteryLength)); | |||||
} | |||||
BatteryNos = batteryNos; | |||||
} | |||||
public NELoginUpStream(string vin, string sim, byte batteryCount, byte batteryLength, IEnumerable<string> batteryNos) : base(vin) | |||||
{ | |||||
if (LoginNumDict.ContainsKey(vin)) | |||||
{ | |||||
(ushort LoginNum, DateTime ExpirationTime) temp; | |||||
if (LoginNumDict.TryGetValue(vin, out temp)) | |||||
{ | |||||
// 不等于当天 | |||||
if (temp.ExpirationTime != DateTime.Now.Date) | |||||
{ | |||||
LoginNum = 1; | |||||
LoginNumDict.TryUpdate(vin, (LoginNum, DateTime.Now.Date), temp); | |||||
} | |||||
else | |||||
{// 自增1 更新字典 | |||||
LoginNum = temp.LoginNum++; | |||||
LoginNumDict.TryUpdate(vin, (LoginNum, DateTime.Now.Date), temp); | |||||
} | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
LoginNum = 1; | |||||
LoginNumDict.TryAdd(vin, (LoginNum, DateTime.Now.Date)); | |||||
} | |||||
SIM = sim; | |||||
BatteryCount = batteryCount; | |||||
BatteryLength = batteryLength; | |||||
BatteryNos = batteryNos; | |||||
ToBuffer(); | |||||
} | } | ||||
/// <summary> | /// <summary> | ||||
@@ -17,15 +60,34 @@ namespace GBNewEnergy.Protocol.Request | |||||
public string SIM { get; set; } | public string SIM { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 电池总成数 | /// 电池总成数 | ||||
/// 可充电储能子系统数 | |||||
/// </summary> | /// </summary> | ||||
public byte BatteryCount { get; set; } | public byte BatteryCount { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 电池编码长度 | /// 电池编码长度 | ||||
/// 可充电储能系统编码长度 | |||||
/// </summary> | /// </summary> | ||||
public byte BatteryLength { get; set; } | public byte BatteryLength { get; set; } | ||||
/// <summary> | /// <summary> | ||||
/// 电池编码 | /// 电池编码 | ||||
/// 可充电储能系统编码 | |||||
/// </summary> | /// </summary> | ||||
public IEnumerable<string> BatteryNos { get; set; } | public IEnumerable<string> BatteryNos { get; set; } | ||||
public override void ToBuffer() | |||||
{ | |||||
// 根据协议说明书 | |||||
Buffer = new byte[6 + 2 + 20 + 1 + 1 + (BatteryCount * BatteryLength)]; | |||||
Buffer.WriteLittle(CurrentDateTime, 0, 6); | |||||
Buffer.WriteLittle(LoginNum, 6, 2); | |||||
Buffer.WriteLittle(SIM, 8); | |||||
Buffer[28] = BatteryCount; | |||||
Buffer[29] = BatteryLength; | |||||
if ((BatteryCount * BatteryLength) != 0) | |||||
{ | |||||
string str = string.Join("", BatteryNos); | |||||
Buffer.WriteLittle(str, 30); | |||||
} | |||||
} | |||||
} | } | ||||
} | } |
@@ -0,0 +1,27 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.UpStream | |||||
{ | |||||
public class NELogoutUpStream : NEBodies | |||||
{ | |||||
protected NELogoutUpStream(byte[] buffer) : base(buffer) | |||||
{ | |||||
} | |||||
protected NELogoutUpStream(string vin) : base(vin) | |||||
{ | |||||
(ushort LoginNum, DateTime ExpirationTime) temp; | |||||
if (LoginNumDict.TryGetValue(vin, out temp)) | |||||
{ | |||||
LoginNum = temp.LoginNum; | |||||
} | |||||
} | |||||
public override void ToBuffer() | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | |||||
} |