From 3ece76ce1ec61af04a6303599745f8b36412dc9b Mon Sep 17 00:00:00 2001 From: SmallChi <564952747@qq.com> Date: Thu, 7 Jun 2018 19:24:59 +0800 Subject: [PATCH] =?UTF-8?q?1.=E8=BD=A6=E8=BE=86=E7=99=BB=E5=85=A5=E5=B0=81?= =?UTF-8?q?=E5=8C=85=E6=8B=86=E5=8C=85=EF=BC=88=E5=BE=85=E5=AE=8C=E5=96=84?= =?UTF-8?q?=EF=BC=89=202.=E4=BF=AE=E6=94=B9=E6=89=A9=E5=B1=95=E6=96=B9?= =?UTF-8?q?=E6=B3=95=203.=E5=A2=9E=E5=8A=A0=E8=BD=A6=E8=BE=86=E7=99=BB?= =?UTF-8?q?=E5=85=A5=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GBNewEnergy.Protocol.Test.csproj | 8 ++ .../NEPackageTest.cs | 71 ++++++++++ .../DownStream/NELoginDownStream.cs | 10 ++ src/GBNewEnergy.Protocol/Enums/ErrorCode.cs | 3 +- .../Extensions/BinaryExtensions.cs | 103 -------------- .../Extensions/NEExtensions.cs | 134 ++++++++++++++++++ src/GBNewEnergy.Protocol/IBuffered.cs | 2 +- src/GBNewEnergy.Protocol/NEBodies.cs | 33 +---- src/GBNewEnergy.Protocol/NEBodiesFactory.cs | 28 ++++ src/GBNewEnergy.Protocol/NEPackage.cs | 66 +++++++-- .../UpStream/NELoginUpStream.cs | 70 ++++++++- .../UpStream/NELogoutUpStream.cs | 27 ++++ 12 files changed, 402 insertions(+), 153 deletions(-) delete mode 100644 src/GBNewEnergy.Protocol/Extensions/BinaryExtensions.cs create mode 100644 src/GBNewEnergy.Protocol/Extensions/NEExtensions.cs create mode 100644 src/GBNewEnergy.Protocol/NEBodiesFactory.cs create mode 100644 src/GBNewEnergy.Protocol/UpStream/NELogoutUpStream.cs diff --git a/src/GBNewEnergy.Protocol.Test/GBNewEnergy.Protocol.Test.csproj b/src/GBNewEnergy.Protocol.Test/GBNewEnergy.Protocol.Test.csproj index 5a3f1d0..e53e54e 100644 --- a/src/GBNewEnergy.Protocol.Test/GBNewEnergy.Protocol.Test.csproj +++ b/src/GBNewEnergy.Protocol.Test/GBNewEnergy.Protocol.Test.csproj @@ -6,6 +6,14 @@ false + + 7.2 + + + + 7.2 + + diff --git a/src/GBNewEnergy.Protocol.Test/NEPackageTest.cs b/src/GBNewEnergy.Protocol.Test/NEPackageTest.cs index 750926d..4b2a93c 100644 --- a/src/GBNewEnergy.Protocol.Test/NEPackageTest.cs +++ b/src/GBNewEnergy.Protocol.Test/NEPackageTest.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Text; using Xunit; using GBNewEnergy.Protocol.Extensions; +using GBNewEnergy.Protocol.UpStream; +using GBNewEnergy.Protocol.Enums; 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(); 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(); + } } } diff --git a/src/GBNewEnergy.Protocol/DownStream/NELoginDownStream.cs b/src/GBNewEnergy.Protocol/DownStream/NELoginDownStream.cs index db43a0d..f38071d 100644 --- a/src/GBNewEnergy.Protocol/DownStream/NELoginDownStream.cs +++ b/src/GBNewEnergy.Protocol/DownStream/NELoginDownStream.cs @@ -9,5 +9,15 @@ namespace GBNewEnergy.Protocol.Response protected NELoginDownStream(byte[] buffer) : base(buffer) { } + + protected NELoginDownStream(string vin) : base(vin) + { + + } + + public override void ToBuffer() + { + throw new NotImplementedException(); + } } } diff --git a/src/GBNewEnergy.Protocol/Enums/ErrorCode.cs b/src/GBNewEnergy.Protocol/Enums/ErrorCode.cs index 98272fe..bbeca9a 100644 --- a/src/GBNewEnergy.Protocol/Enums/ErrorCode.cs +++ b/src/GBNewEnergy.Protocol/Enums/ErrorCode.cs @@ -6,6 +6,7 @@ namespace GBNewEnergy.Protocol.Enums { public enum ErrorCode { - BeginFlagError = 1001 + BeginFlagError = 1001, + BCCCodeError = 1001 } } diff --git a/src/GBNewEnergy.Protocol/Extensions/BinaryExtensions.cs b/src/GBNewEnergy.Protocol/Extensions/BinaryExtensions.cs deleted file mode 100644 index 4d32bb0..0000000 --- a/src/GBNewEnergy.Protocol/Extensions/BinaryExtensions.cs +++ /dev/null @@ -1,103 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; - -namespace GBNewEnergy.Protocol.Extensions -{ - public static class BinaryExtensions - { - - /// - /// 从高位到低位转成int - /// - /// - /// - /// - /// - 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; - } - - /// - /// 字符串到字节数组 - /// - /// - /// - public static byte[] ToBytes(this string data, Encoding coding) - { - return coding.GetBytes(data); - } - - /// - /// 字符串到字节数组 - /// - /// - public static byte[] ToBytes(this string data) - { - return Encoding.ASCII.GetBytes(data); - } - - /// - /// 整型到字节数组 - /// - /// int数据 - /// int填入长度 - 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; - } - - /// - /// 异或 - /// - /// - /// - /// - /// - 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; - } - - /// - /// 字节数组转16进制字符串 - /// - /// - /// 默认 " " - /// - public static string ToHexString(this byte[] bytes,string separator=" ") - { - return string.Join(separator, bytes.Select(s => s.ToString("X2"))); - } - - /// - /// 16进制字符串转16进制数组 - /// - /// - /// - /// - public static byte[] ToHexBytes(this string hexString, string separator = " ") - { - return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); - } - } -} diff --git a/src/GBNewEnergy.Protocol/Extensions/NEExtensions.cs b/src/GBNewEnergy.Protocol/Extensions/NEExtensions.cs new file mode 100644 index 0000000..b9687c4 --- /dev/null +++ b/src/GBNewEnergy.Protocol/Extensions/NEExtensions.cs @@ -0,0 +1,134 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; + +namespace GBNewEnergy.Protocol.Extensions +{ + public static class NEExtensions + { + /// + /// 日期限制于2000年 + /// + 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; + } + + /// + /// 异或 + /// + /// + /// + /// + /// + 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; + } + + /// + /// 字节数组转16进制字符串 + /// + /// + /// 默认 " " + /// + public static string ToHexString(this byte[] bytes,string separator=" ") + { + return string.Join(separator, bytes.Select(s => s.ToString("X2"))); + } + + /// + /// 16进制字符串转16进制数组 + /// + /// + /// + /// + public static byte[] ToHexBytes(this string hexString, string separator = " ") + { + return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); + } + } +} diff --git a/src/GBNewEnergy.Protocol/IBuffered.cs b/src/GBNewEnergy.Protocol/IBuffered.cs index 8ea9cd8..02034a0 100644 --- a/src/GBNewEnergy.Protocol/IBuffered.cs +++ b/src/GBNewEnergy.Protocol/IBuffered.cs @@ -2,6 +2,6 @@ { public interface IBuffered { - byte[] ToBuffer(); + void ToBuffer(); } } diff --git a/src/GBNewEnergy.Protocol/NEBodies.cs b/src/GBNewEnergy.Protocol/NEBodies.cs index 08d1018..9a47245 100644 --- a/src/GBNewEnergy.Protocol/NEBodies.cs +++ b/src/GBNewEnergy.Protocol/NEBodies.cs @@ -11,7 +11,7 @@ namespace GBNewEnergy.Protocol /// VIN - 登录流水号,过期时间(每天置1) /// 车载终端登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天 /// - private static readonly ConcurrentDictionary LoginNumDict; + protected static readonly ConcurrentDictionary LoginNumDict; static NEBodies() { @@ -26,6 +26,7 @@ namespace GBNewEnergy.Protocol /// /// 数据采集时间 + /// 采用北京时间 /// public DateTime CurrentDateTime { get; protected set; } @@ -36,37 +37,11 @@ namespace GBNewEnergy.Protocol 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; } - public byte[] ToBuffer() - { - throw new NotImplementedException(); - } + public abstract void ToBuffer(); } } diff --git a/src/GBNewEnergy.Protocol/NEBodiesFactory.cs b/src/GBNewEnergy.Protocol/NEBodiesFactory.cs new file mode 100644 index 0000000..96434b0 --- /dev/null +++ b/src/GBNewEnergy.Protocol/NEBodiesFactory.cs @@ -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 + { + /// + /// 通过命令id获取数据体 + /// + /// + /// + /// + public static NEBodies GetNEBodiesByMsgId(MsgId msgId,byte[] buf) + { + switch (msgId) + { + case MsgId.login: + return new NELoginUpStream(buf); + default: + return null; + } + } + } +} diff --git a/src/GBNewEnergy.Protocol/NEPackage.cs b/src/GBNewEnergy.Protocol/NEPackage.cs index 86df19a..f9f4b53 100644 --- a/src/GBNewEnergy.Protocol/NEPackage.cs +++ b/src/GBNewEnergy.Protocol/NEPackage.cs @@ -2,8 +2,6 @@ using GBNewEnergy.Protocol.Exceptions; using GBNewEnergy.Protocol.Extensions; using System; -using System.Collections.Generic; -using System.Text; namespace GBNewEnergy.Protocol @@ -15,15 +13,53 @@ namespace GBNewEnergy.Protocol { public NEPackage(byte[] header,byte[] body) { + // 判断头部异常 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]; AskId = (AskId)header[3]; - VIN = Encoding.ASCII.GetString(header, 4, 17).Trim('\0'); + VIN = header.ReadStringLittle(4, 17); EncryptMethod = (EncryptMethod)header[21]; - DataUnitLength = header.ToIntH2L(22, 2); + // 通过命令id获取数据体 + Bodies = NEBodiesFactory.GetNEBodiesByMsgId(MsgId, body); + Buffer = packageBuffer; 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) { MsgId = msgId; @@ -43,6 +79,10 @@ namespace GBNewEnergy.Protocol /// public const byte BeginFlag = 0x23; /// + /// 校验位1字节 + /// + private const int CheckBit = 1; + /// /// 命令标识 /// public MsgId MsgId { get; private set; } @@ -79,27 +119,23 @@ namespace GBNewEnergy.Protocol public byte[] Buffer { get; private set; } - public override string ToString() - { - return this.Header.ToHexString()+" " +this.Buffer.ToHexString(); - } - private void ToBuffer() { // 固定单元长度 DataUnitLength = Bodies.Buffer.Length; - Buffer = new byte[HeaderFixedByteLength + 1 + DataUnitLength]; + Buffer = new byte[HeaderFixedByteLength + DataUnitLength + CheckBit]; Buffer[0] = BeginFlag; Buffer[1] = BeginFlag; Buffer[2] = (byte)MsgId; Buffer[3] = (byte)AskId; - Array.Copy(VIN.ToBytes(), 0, Buffer, 4, 20); + Buffer.WriteLittle(VIN, 4); 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; - Array.Copy(Buffer,0, Header, 0, 22); + Header = new byte[HeaderFixedByteLength]; + Array.Copy(Buffer, 0, Header, 0, HeaderFixedByteLength); } } } diff --git a/src/GBNewEnergy.Protocol/UpStream/NELoginUpStream.cs b/src/GBNewEnergy.Protocol/UpStream/NELoginUpStream.cs index 775fcd5..987fb82 100644 --- a/src/GBNewEnergy.Protocol/UpStream/NELoginUpStream.cs +++ b/src/GBNewEnergy.Protocol/UpStream/NELoginUpStream.cs @@ -1,14 +1,57 @@ -using System; +using GBNewEnergy.Protocol.Extensions; +using System; using System.Collections.Generic; 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 batteryNos = new List(); + 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 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(); } /// @@ -17,15 +60,34 @@ namespace GBNewEnergy.Protocol.Request public string SIM { get; set; } /// /// 电池总成数 + /// 可充电储能子系统数 /// public byte BatteryCount { get; set; } /// /// 电池编码长度 + /// 可充电储能系统编码长度 /// public byte BatteryLength { get; set; } /// /// 电池编码 + /// 可充电储能系统编码 /// public IEnumerable 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); + } + } } } diff --git a/src/GBNewEnergy.Protocol/UpStream/NELogoutUpStream.cs b/src/GBNewEnergy.Protocol/UpStream/NELogoutUpStream.cs new file mode 100644 index 0000000..d9ffe5f --- /dev/null +++ b/src/GBNewEnergy.Protocol/UpStream/NELogoutUpStream.cs @@ -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(); + } + } +}