@@ -0,0 +1,125 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using Xunit; | |||||
using GBNewEnergy.Protocol.Extensions; | |||||
using GBNewEnergy.Protocol.NEProperties; | |||||
using GBNewEnergy.Protocol.DownStream; | |||||
using GBNewEnergy.Protocol.Enums; | |||||
namespace GBNewEnergy.Protocol.Test.DownStream | |||||
{ | |||||
public class NEControlDownStreamTest : NEPackageBase | |||||
{ | |||||
#region NEControlCmd.unused | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_1() | |||||
{ | |||||
NEControlProperty nEControlProperty = new NEControlProperty | |||||
{ | |||||
VIN = "LGHC4V1D3HE202652", | |||||
CmdID=NEControlCmd.unused, | |||||
UpgradeParameter=new NEControlUpgradeParameter { | |||||
DialPassword = "123", | |||||
DialPointName = "xyz", | |||||
DialUserName = "11" | |||||
} | |||||
}; | |||||
NEControlDownStream nEControlDownStream = new NEControlDownStream(nEControlProperty, NEGlobalConfigs); | |||||
INEProperties nEPackageProperty = new NEPackageProperty | |||||
{ | |||||
Bodies = nEControlDownStream, | |||||
MsgId = Enums.NEMsgId.control, | |||||
AskId = Enums.NEAskId.cmd, | |||||
VIN = "LGHC4V1D3HE202652" | |||||
}; | |||||
NEPackage nEPackage = new NEPackage(nEPackageProperty, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_2() | |||||
{ | |||||
byte[] packageBytes = "23 23 82 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 07 12 06 0E 0A 0E 1B 00 57".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(packageBytes, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
#endregion | |||||
#region NEControlCmd.remoteupdate | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_3() | |||||
{ | |||||
NEControlProperty nEControlProperty = new NEControlProperty | |||||
{ | |||||
VIN = "LGHC4V1D3HE202652", | |||||
CmdID = NEControlCmd.remoteupdate, | |||||
UpgradeParameter=new NEControlUpgradeParameter { | |||||
DialPassword = "123", | |||||
DialPointName = "xyz", | |||||
DialUserName = "11" | |||||
} | |||||
}; | |||||
NEControlDownStream nEControlDownStream = new NEControlDownStream(nEControlProperty, NEGlobalConfigs); | |||||
INEProperties nEPackageProperty = new NEPackageProperty | |||||
{ | |||||
Bodies = nEControlDownStream, | |||||
MsgId = Enums.NEMsgId.control, | |||||
AskId = Enums.NEAskId.cmd, | |||||
VIN = "LGHC4V1D3HE202652" | |||||
}; | |||||
NEPackage nEPackage = new NEPackage(nEPackageProperty, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_4() | |||||
{ | |||||
byte[] packageBytes = "23 23 82 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 18 12 06 0E 0A 22 0B 01 3B 78 79 7A 3B 31 31 3B 31 32 33 3B 3B 3B 3B 3B 3B 05".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(packageBytes, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
#endregion | |||||
#region NEControlCmd.warning | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_5() | |||||
{ | |||||
NEControlProperty nEControlProperty = new NEControlProperty | |||||
{ | |||||
VIN = "LGHC4V1D3HE202652", | |||||
CmdID = NEControlCmd.warning, | |||||
AlarmParameter= new NEControlAlarmParameter { nEAlarmLevel= NEAlarmLevel.一级报警 } | |||||
}; | |||||
NEControlDownStream nEControlDownStream = new NEControlDownStream(nEControlProperty, NEGlobalConfigs); | |||||
INEProperties nEPackageProperty = new NEPackageProperty | |||||
{ | |||||
Bodies = nEControlDownStream, | |||||
MsgId = Enums.NEMsgId.control, | |||||
AskId = Enums.NEAskId.cmd, | |||||
VIN = "LGHC4V1D3HE202652" | |||||
}; | |||||
NEPackage nEPackage = new NEPackage(nEPackageProperty, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
[Fact] | |||||
public void NEControlDownStreamConstructor4_6() | |||||
{ | |||||
byte[] packageBytes = "23 23 82 FE 4C 47 48 43 34 56 31 44 33 48 45 32 30 32 36 35 32 01 00 08 12 06 0E 0B 2C 0B 06 01 6C".ToHexBytes(); | |||||
NEPackage nEPackage = new NEPackage(packageBytes, NEGlobalConfigs); | |||||
string headerHex = nEPackage.Header.ToHexString(); | |||||
string bodiesHex = nEPackage.Bodies.Buffer.ToHexString(); | |||||
string packageHex = nEPackage.Buffer.ToHexString(); | |||||
} | |||||
#endregion | |||||
} | |||||
} |
@@ -1,4 +1,5 @@ | |||||
using GBNewEnergy.Protocol.Extensions; | |||||
using GBNewEnergy.Protocol.Enums; | |||||
using GBNewEnergy.Protocol.Extensions; | |||||
using GBNewEnergy.Protocol.NEProperties; | using GBNewEnergy.Protocol.NEProperties; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -17,33 +18,75 @@ namespace GBNewEnergy.Protocol.DownStream | |||||
public NEControlDownStream(INEProperties nEProperties, NEGlobalConfigs nEConfigs) : base(nEProperties, nEConfigs) | public NEControlDownStream(INEProperties nEProperties, NEGlobalConfigs nEConfigs) : base(nEProperties, nEConfigs) | ||||
{ | { | ||||
} | |||||
} | |||||
/// <summary> | /// <summary> | ||||
/// 命令ID 只能发送一个 | /// 命令ID 只能发送一个 | ||||
/// </summary> | |||||
public byte CmdId { get; set; } | |||||
/// <summary> | |||||
/// 命令参数 | |||||
/// [{id,value},{id,value}], 没有内容则内容为空 | |||||
/// </summary> | |||||
public List<KeyValuePair<byte, string>> Vauels { get; set; } | |||||
/// </summary> | |||||
public NEControlCmd CmdID { get; set; } | |||||
/// <summary> | |||||
/// 命令参数 没有内容则内容为空 | |||||
/// </summary> | |||||
public string CmdParameter { get; set; } | |||||
protected override void InitializeProperties(INEProperties nEProperties) | protected override void InitializeProperties(INEProperties nEProperties) | ||||
{ | |||||
{ | |||||
NEControlProperty nEControlProperty = (NEControlProperty)nEProperties; | |||||
CmdID = nEControlProperty.CmdID; | |||||
if (CmdID == NEControlCmd.remoteupdate) | |||||
{ | |||||
CmdParameter = nEControlProperty.UpgradeParameter.ToString(); | |||||
} | |||||
else if(CmdID == NEControlCmd.warning) | |||||
{ | |||||
CmdParameter = nEControlProperty.AlarmParameter.nEAlarmLevel.ToString(); | |||||
} | |||||
} | } | ||||
protected override void InitializePropertiesFromBuffer() | protected override void InitializePropertiesFromBuffer() | ||||
{ | { | ||||
CurrentDateTime = Buffer.ReadDateTimeLittle(0, 6); | CurrentDateTime = Buffer.ReadDateTimeLittle(0, 6); | ||||
CmdID = (NEControlCmd)Buffer[6]; | |||||
switch (CmdID) | |||||
{ | |||||
case NEControlCmd.remoteupdate: | |||||
CmdParameter = Buffer.ReadStringLittle(7, Buffer.Length - 8);//最后一位为校验码,不在参数列 | |||||
break; | |||||
case NEControlCmd.warning: | |||||
CmdParameter = ((NEAlarmLevel)Buffer[7]).ToString(); | |||||
break; | |||||
case NEControlCmd.unused: | |||||
case NEControlCmd.shutdown: | |||||
case NEControlCmd.reset: | |||||
case NEControlCmd.restorefactorysettings: | |||||
case NEControlCmd.interruptrequest: | |||||
case NEControlCmd.OpenMonitoring: | |||||
default: | |||||
break; | |||||
} | |||||
} | } | ||||
protected override void ToBuffer() | protected override void ToBuffer() | ||||
{ | { | ||||
Buffer = new byte[6]; | |||||
Buffer.WriteLittle(CurrentDateTime, 0, 6); | |||||
if (CmdID == NEControlCmd.remoteupdate) | |||||
{ | |||||
var contentLength = NEConfigs.NEEncoding.GetBytes(CmdParameter).Length; | |||||
Buffer = new byte[6 + 1 + contentLength]; | |||||
Buffer.WriteLittle(CurrentDateTime, 0, 6); | |||||
Buffer.WriteLittle(CmdID.ToByteValue(), 6); | |||||
Buffer.WriteLittle(CmdParameter, 7); | |||||
} | |||||
else if (CmdID == NEControlCmd.warning) { | |||||
Buffer = new byte[6 + 1 + 1]; | |||||
Buffer.WriteLittle(CurrentDateTime, 0, 6); | |||||
Buffer.WriteLittle(CmdID.ToByteValue(), 6); | |||||
Buffer.WriteLittle(CmdParameter.ToEnum<NEAlarmLevel>().ToByteValue(), 7); | |||||
} | |||||
else | |||||
{ | |||||
Buffer = new byte[6 + 1]; | |||||
Buffer.WriteLittle(CurrentDateTime, 0, 6); | |||||
Buffer.WriteLittle(CmdID.ToByteValue(), 6); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -0,0 +1,18 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.Enums | |||||
{ | |||||
/// <summary> | |||||
/// 报警等级 | |||||
/// </summary> | |||||
public enum NEAlarmLevel:byte | |||||
{ | |||||
无报警 = 0x00, | |||||
一级报警 = 0x01, | |||||
二级报警 = 0x02, | |||||
三级报警 = 0x03, | |||||
无效数据 = 0xFF | |||||
} | |||||
} |
@@ -16,9 +16,9 @@ namespace GBNewEnergy.Protocol.Enums | |||||
/// </summary> | /// </summary> | ||||
unused= 0x00, | unused= 0x00, | ||||
/// <summary> | /// <summary> | ||||
/// 远程升级 | |||||
/// 远程升级 见表B.16 | |||||
/// </summary> | /// </summary> | ||||
remoteupdate=0x01, | |||||
remoteupdate = 0x01, | |||||
/// <summary> | /// <summary> | ||||
/// 车载终端关机 | /// 车载终端关机 | ||||
/// </summary> | /// </summary> | ||||
@@ -0,0 +1,135 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.ComponentModel; | |||||
using System.Reflection; | |||||
namespace GBNewEnergy.Protocol.Extensions | |||||
{ | |||||
/// <summary> | |||||
/// 枚举扩展 | |||||
/// </summary> | |||||
internal static class EnumExtensions | |||||
{ | |||||
/// <summary> | |||||
/// 转为整型 | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="t"></param> | |||||
/// <returns></returns> | |||||
public static int ToValue<T>(this T t) where T : struct | |||||
{ | |||||
return Convert.ToInt32(t); | |||||
} | |||||
/// <summary> | |||||
/// 转为Byte | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="t"></param> | |||||
/// <returns></returns> | |||||
public static byte ToByteValue<T>(this T t) where T : struct | |||||
{ | |||||
return Convert.ToByte(t); | |||||
} | |||||
/// <summary> | |||||
/// 字符转枚举 | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="value"></param> | |||||
/// <returns></returns> | |||||
public static T ToEnum<T>(this string value) where T : struct | |||||
{ | |||||
return (T)Enum.Parse(typeof(T), value); | |||||
} | |||||
/// <summary> | |||||
/// 获取枚举字符串 | |||||
/// </summary> | |||||
/// <param name="valueEnum"></param> | |||||
public static string GetName(this Enum valueEnum) | |||||
{ | |||||
return valueEnum.ToString(); | |||||
} | |||||
/// <summary> | |||||
/// 获取DescriptionAttribute特性枚举值的描述 | |||||
/// </summary> | |||||
/// <param name="value"></param> | |||||
/// <returns></returns> | |||||
public static string GetDescription(this Enum value) | |||||
{ | |||||
var attribute = value.GetAttribute<DescriptionAttribute>(); | |||||
return attribute == null ? value.ToString() : attribute.Description; | |||||
} | |||||
/// <summary> | |||||
/// 验证是否是枚举类型 | |||||
/// </summary> | |||||
/// <typeparam name="TEnum"></typeparam> | |||||
/// <param name="enumValue"></param> | |||||
/// <returns></returns> | |||||
public static bool IsEnumValid<TEnum>(this int enumValue) | |||||
{ | |||||
return Enum.IsDefined(typeof(TEnum), enumValue); | |||||
} | |||||
/// <summary> | |||||
/// 获取DescriptionAttribute特性枚举及描述 | |||||
/// </summary> | |||||
/// <param name="type"></param> | |||||
/// <returns></returns> | |||||
public static Dictionary<string, string> GetDescriptionAttributeDictionary(this Enum value) | |||||
{ | |||||
Dictionary<string, string> dictionary = new Dictionary<string, string>(); | |||||
var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public); | |||||
foreach (var fi in fields) | |||||
{ | |||||
DescriptionAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute), false) as DescriptionAttribute; | |||||
dictionary.Add(fi.Name, attr != null ? attr.Description : ""); | |||||
} | |||||
return dictionary; | |||||
} | |||||
/// <summary> | |||||
/// 获取DisplayNameAttribute特性枚举值的描述 | |||||
/// </summary> | |||||
/// <param name="obj">枚举值</param> | |||||
/// <returns></returns> | |||||
public static string GetDisplayName(this Enum value) | |||||
{ | |||||
var attribute = value.GetAttribute<DisplayNameAttribute>(); | |||||
return attribute == null ? value.ToString() : attribute.DisplayName; | |||||
} | |||||
/// <summary> | |||||
/// 获取DisplayNameAttribute特性枚举及描述 | |||||
/// </summary> | |||||
/// <param name="type"></param> | |||||
/// <returns></returns> | |||||
public static Dictionary<string, string> GetDisplayNameAttributeDictionary(this Enum value) | |||||
{ | |||||
Dictionary<string, string> dictionary = new Dictionary<string, string>(); | |||||
var fields = value.GetType().GetFields(BindingFlags.Static | BindingFlags.Public); | |||||
foreach (var fi in fields) | |||||
{ | |||||
DisplayNameAttribute attr = Attribute.GetCustomAttribute(fi, typeof(DisplayNameAttribute), false) as DisplayNameAttribute; | |||||
dictionary.Add(fi.Name, attr != null ? attr.DisplayName : ""); | |||||
} | |||||
return dictionary; | |||||
} | |||||
/// <summary> | |||||
/// 获取枚举对应特性 | |||||
/// </summary> | |||||
/// <typeparam name="T"></typeparam> | |||||
/// <param name="value"></param> | |||||
/// <returns></returns> | |||||
public static T GetAttribute<T>(this Enum value) where T : Attribute | |||||
{ | |||||
var type = value.GetType(); | |||||
var memberInfo = type.GetMember(value.ToString()); | |||||
var attributes = memberInfo[0].GetCustomAttributes(typeof(T), false); | |||||
return (T)attributes[0]; | |||||
} | |||||
} | |||||
} |
@@ -27,7 +27,8 @@ namespace GBNewEnergy.Protocol | |||||
return new NEPlatformLoginUpStream(buf, nEConfigs); | return new NEPlatformLoginUpStream(buf, nEConfigs); | ||||
case NEMsgId.platformlogout: | case NEMsgId.platformlogout: | ||||
return new NEPlatformLogoutUpStream(buf, nEConfigs); | return new NEPlatformLogoutUpStream(buf, nEConfigs); | ||||
case NEMsgId.control: | |||||
case NEMsgId.control: | |||||
return new NEControlDownStream(buf, nEConfigs); | |||||
case NEMsgId.settings: | case NEMsgId.settings: | ||||
case NEMsgId.heartbeat: | case NEMsgId.heartbeat: | ||||
case NEMsgId.checktime: | case NEMsgId.checktime: | ||||
@@ -8,7 +8,11 @@ namespace GBNewEnergy.Protocol | |||||
/// <summary> | /// <summary> | ||||
/// 加密编码 | /// 加密编码 | ||||
/// </summary> | /// </summary> | ||||
public Encoding NEEncryptEncoding { get; set; } = Encoding.UTF8; | |||||
public Encoding NEEncryptEncoding { get; set; } = Encoding.UTF8; | |||||
/// <summary> | |||||
/// 字符串编码 | |||||
/// </summary> | |||||
public Encoding NEEncoding { get; set; } = Encoding.UTF8; | |||||
/// <summary> | /// <summary> | ||||
/// 数据单元加密方式 | /// 数据单元加密方式 | ||||
/// 0x01:数据不加密;0x02:数据经过 RSA 算法加密;0x03:数据经过 AES128 位算法加密;“0xFE”表示异常,“0xFF”表示无效 | /// 0x01:数据不加密;0x02:数据经过 RSA 算法加密;0x03:数据经过 AES128 位算法加密;“0xFE”表示异常,“0xFF”表示无效 | ||||
@@ -0,0 +1,18 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using GBNewEnergy.Protocol.Enums; | |||||
namespace GBNewEnergy.Protocol.NEProperties | |||||
{ | |||||
/// <summary> | |||||
/// 控制命令 报警、预警 | |||||
/// </summary> | |||||
public class NEControlAlarmParameter | |||||
{ | |||||
/// <summary> | |||||
/// 报警等级 | |||||
/// </summary> | |||||
public NEAlarmLevel nEAlarmLevel { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,27 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
using GBNewEnergy.Protocol.Enums; | |||||
namespace GBNewEnergy.Protocol.NEProperties | |||||
{ | |||||
/// <summary> | |||||
/// 控制命令属性 | |||||
/// </summary> | |||||
public class NEControlProperty : INEProperties | |||||
{ | |||||
public string VIN { get; set ; } | |||||
/// <summary> | |||||
/// 命令ID 只能发送一个 | |||||
/// </summary> | |||||
public NEControlCmd CmdID { get; set; } | |||||
/// <summary> | |||||
/// 升级参数 | |||||
/// </summary> | |||||
public NEControlUpgradeParameter UpgradeParameter { get; set; } | |||||
/// <summary> | |||||
/// 报警,预警参数 | |||||
/// </summary> | |||||
public NEControlAlarmParameter AlarmParameter { get; set; } | |||||
} | |||||
} |
@@ -0,0 +1,57 @@ | |||||
using System; | |||||
using System.Collections.Generic; | |||||
using System.Text; | |||||
namespace GBNewEnergy.Protocol.NEProperties | |||||
{ | |||||
/// <summary> | |||||
/// 控制命令,升级 | |||||
/// </summary> | |||||
public class NEControlUpgradeParameter | |||||
{ | |||||
/// <summary> | |||||
/// URL地址 | |||||
/// </summary> | |||||
public string Url { get; set; } | |||||
/// <summary> | |||||
/// 拨号点名称 | |||||
/// </summary> | |||||
public string DialPointName { get; set; } | |||||
/// <summary> | |||||
/// 拨号用户名 | |||||
/// </summary> | |||||
public string DialUserName { get; set; } | |||||
/// <summary> | |||||
/// 拨号密码 | |||||
/// </summary> | |||||
public string DialPassword { get; set; } | |||||
/// <summary> | |||||
/// 服务器地址 | |||||
/// </summary> | |||||
public string ServerUrl { get; set; } | |||||
/// <summary> | |||||
/// 服务器端口 | |||||
/// </summary> | |||||
public string ServerPort { get; set; } | |||||
/// <summary> | |||||
/// 生产厂商代码 | |||||
/// </summary> | |||||
public string ProviderCode { get; set; } | |||||
/// <summary> | |||||
/// 硬件版本 | |||||
/// </summary> | |||||
public string HardwareVersion { get; set; } | |||||
/// <summary> | |||||
/// 固件版本 | |||||
/// </summary> | |||||
public string FirmwareVersion { get; set; } | |||||
/// <summary> | |||||
/// 升级服务器时限 | |||||
/// </summary> | |||||
public string UpLimitTime { get; set; } | |||||
public override string ToString() | |||||
{ | |||||
return $"{Url};{DialPointName};{DialUserName};{DialPassword};{ServerUrl};{ServerPort};{ProviderCode};{HardwareVersion};{FirmwareVersion};{UpLimitTime}"; | |||||
} | |||||
} | |||||
} |