@@ -3,7 +3,7 @@ using System.IO; | |||||
namespace GBNewEnergy.Protocol | namespace GBNewEnergy.Protocol | ||||
{ | { | ||||
public abstract class BufferedEntityBase : IBuffer | |||||
public abstract class BufferedEntityBase : IBuffer, IBuffered | |||||
{ | { | ||||
public byte[] Buffer { get; protected set; } | public byte[] Buffer { get; protected set; } | ||||
@@ -11,5 +11,15 @@ namespace GBNewEnergy.Protocol | |||||
{ | { | ||||
Buffer = buffer; | Buffer = buffer; | ||||
} | } | ||||
protected BufferedEntityBase(params object[] parameter) | |||||
{ | |||||
} | |||||
public byte[] ToBuffer() | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -4,8 +4,10 @@ using System.Text; | |||||
namespace GBNewEnergy.Protocol.Response | namespace GBNewEnergy.Protocol.Response | ||||
{ | { | ||||
public class NELoginDownStream : NEDownStreamBase | |||||
public class NELoginDownStream : NEBodies | |||||
{ | { | ||||
protected NELoginDownStream(byte[] buffer) : base(buffer) | |||||
{ | |||||
} | |||||
} | } | ||||
} | } |
@@ -1,6 +1,7 @@ | |||||
using System; | using System; | ||||
using System.IO; | using System.IO; | ||||
using System.Linq; | using System.Linq; | ||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.Extensions | namespace GBNewEnergy.Protocol.Extensions | ||||
{ | { | ||||
@@ -24,6 +25,59 @@ namespace GBNewEnergy.Protocol.Extensions | |||||
return result; | 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> | /// <summary> | ||||
/// 字节数组转16进制字符串 | /// 字节数组转16进制字符串 | ||||
/// </summary> | /// </summary> | ||||
@@ -5,7 +5,10 @@ | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<ItemGroup> | <ItemGroup> | ||||
<Compile Remove="BufferedEntityBase.cs" /> | |||||
<Compile Remove="NEDownStreamBase.cs" /> | |||||
<Compile Remove="NEHeader.cs" /> | <Compile Remove="NEHeader.cs" /> | ||||
<Compile Remove="NEUpStreamBase.cs" /> | |||||
</ItemGroup> | </ItemGroup> | ||||
</Project> | </Project> |
@@ -2,6 +2,6 @@ | |||||
{ | { | ||||
public interface IBuffered | public interface IBuffered | ||||
{ | { | ||||
void ToBuffer(); | |||||
byte[] ToBuffer(); | |||||
} | } | ||||
} | } |
@@ -0,0 +1,72 @@ | |||||
using System; | |||||
using System.Collections.Concurrent; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol | |||||
{ | |||||
public abstract class NEBodies : IBuffer, IBuffered | |||||
{ | |||||
/// <summary> | |||||
/// VIN - 登录流水号,过期时间(每天置1) | |||||
/// 车载终端登入一次,登入流水号自动加1,从1开始循环累加,最大值为65531,循环周期为天 | |||||
/// </summary> | |||||
private static readonly ConcurrentDictionary<string, (ushort LoginNum, DateTime ExpirationTime)> LoginNumDict; | |||||
static NEBodies() | |||||
{ | |||||
LoginNumDict = new ConcurrentDictionary<string, (ushort LoginNum, DateTime ExpirationTime)>(); | |||||
} | |||||
/// <summary> | |||||
/// 登入流水号 | |||||
/// 作用:看数据是否是连续请求 | |||||
/// </summary> | |||||
public ushort LoginNum { get; protected set; } | |||||
/// <summary> | |||||
/// 数据采集时间 | |||||
/// </summary> | |||||
public DateTime CurrentDateTime { get; protected set; } | |||||
public byte[] Buffer { get; protected set; } | |||||
protected NEBodies(byte[] buffer) | |||||
{ | |||||
Buffer = buffer; | |||||
} | |||||
protected NEBodies(string vin,object[] parameter) | |||||
{ | |||||
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(); | |||||
} | |||||
} | |||||
} |
@@ -11,9 +11,9 @@ namespace GBNewEnergy.Protocol | |||||
/// <summary> | /// <summary> | ||||
/// 新能源包 | /// 新能源包 | ||||
/// </summary> | /// </summary> | ||||
public class NEPackage: BufferedEntityBase | |||||
public class NEPackage:IBuffer | |||||
{ | { | ||||
public NEPackage(byte[] header,byte[] body):base(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]}"); | ||||
MsgId = (MsgId)header[2]; | MsgId = (MsgId)header[2]; | ||||
@@ -23,6 +23,17 @@ namespace GBNewEnergy.Protocol | |||||
DataUnitLength = header.ToIntH2L(22, 2); | DataUnitLength = header.ToIntH2L(22, 2); | ||||
Header = header; | Header = header; | ||||
} | } | ||||
public NEPackage(string vin, MsgId msgId, AskId askId, NEBodies bodies,EncryptMethod encryptMethod) | |||||
{ | |||||
MsgId = msgId; | |||||
AskId = askId; | |||||
VIN = vin; | |||||
EncryptMethod = encryptMethod; | |||||
Bodies = bodies; | |||||
ToBuffer(); | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 固定为24个字节长度 | /// 固定为24个字节长度 | ||||
/// </summary> | /// </summary> | ||||
@@ -53,19 +64,42 @@ namespace GBNewEnergy.Protocol | |||||
/// </summary> | /// </summary> | ||||
public int DataUnitLength { get; private set; } | public int DataUnitLength { get; private set; } | ||||
/// <summary> | /// <summary> | ||||
/// BCC校验码 | |||||
/// 采用BCC(异或检验)法,校验范围从命令单元的第一个字节开始,同后一个字节异或,直到校验码前一个字节为止, | |||||
/// 校验码占用一个字节,当数据单元存在加密时,应先加密后检验,先校验后解密 | |||||
/// </summary> | /// </summary> | ||||
public byte BCCCode { get; private set; } | public byte BCCCode { get; private set; } | ||||
/// <summary> | /// <summary> | ||||
/// 头数据 | /// 头数据 | ||||
/// </summary> | /// </summary> | ||||
public byte[] Header { get; private set; } | public byte[] Header { get; private set; } | ||||
/// <summary> | |||||
/// 数据体 | |||||
/// </summary> | |||||
public NEBodies Bodies { get;protected set; } | |||||
public NEUpStreamBase NEUpStreamBase { get;protected set; } | |||||
public byte[] Buffer { get; private set; } | |||||
public override string ToString() | public override string ToString() | ||||
{ | { | ||||
return Header.ToHexString()+" "+this.Buffer.ToHexString(); | |||||
return this.Header.ToHexString()+" " +this.Buffer.ToHexString(); | |||||
} | |||||
private void ToBuffer() | |||||
{ | |||||
// 固定单元长度 | |||||
DataUnitLength = Bodies.Buffer.Length; | |||||
Buffer = new byte[HeaderFixedByteLength + 1 + DataUnitLength]; | |||||
Buffer[0] = BeginFlag; | |||||
Buffer[1] = BeginFlag; | |||||
Buffer[2] = (byte)MsgId; | |||||
Buffer[3] = (byte)AskId; | |||||
Array.Copy(VIN.ToBytes(), 0, Buffer, 4, 20); | |||||
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[HeaderFixedByteLength + DataUnitLength] = BCCCode; | |||||
Array.Copy(Buffer,0, Header, 0, 22); | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -5,7 +5,7 @@ using System.Text; | |||||
namespace GBNewEnergy.Protocol | namespace GBNewEnergy.Protocol | ||||
{ | { | ||||
public abstract class NEUpStreamBase: IBuffered, IBuffer | |||||
public abstract class NEUpStreamBase | |||||
{ | { | ||||
public DateTime Utc{ get; set; } | public DateTime Utc{ get; set; } | ||||
public byte[] Buffer { get;protected set; } | public byte[] Buffer { get;protected set; } | ||||
@@ -4,12 +4,13 @@ using System.Text; | |||||
namespace GBNewEnergy.Protocol.Request | namespace GBNewEnergy.Protocol.Request | ||||
{ | { | ||||
public class NELoginUpStream: NEUpStreamBase | |||||
public class NELoginUpStream: NEBodies | |||||
{ | { | ||||
/// <summary> | |||||
/// 登入流水号 | |||||
/// </summary> | |||||
public int LoginNum { get; set; } | |||||
protected NELoginUpStream(byte[] buffer) : base(buffer) | |||||
{ | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// SIM 卡号 | /// SIM 卡号 | ||||
/// </summary> | /// </summary> | ||||
@@ -26,10 +27,5 @@ namespace GBNewEnergy.Protocol.Request | |||||
/// 电池编码 | /// 电池编码 | ||||
/// </summary> | /// </summary> | ||||
public IEnumerable<string> BatteryNos { get; set; } | public IEnumerable<string> BatteryNos { get; set; } | ||||
public override void ToBuffer() | |||||
{ | |||||
throw new NotImplementedException(); | |||||
} | |||||
} | } | ||||
} | } |