硬件管理平台-硬件产品库-硬件项目
本篇主要描述的是如何创建一个硬件项目,并将硬件信息进行展示。
讲了这么多至少应该能出个效果吧
在产品库文件夹中创建一个硬件集合文件夹,该文件夹存放所有硬件项目,在创建硬件项目前我们需要创建某类硬件项目的硬件接口。
我们在此以门禁和空调为例。门禁的功能有监听门禁事件,获取人员列表;空调的功能有开关机,定时获取温湿度等。
关于海康门禁的功能可以查看我的博客中的相关代码,在这里就不重复说明了。例如:门禁实时获取记录
硬件接口项目
接口项目何用
- 创建接口项目主要用于对硬件进行分类,例如空调硬件,门禁类硬件,灯控类等等,就是之前提到的所谓的硬件类型。里面再分具体型号,例如门禁类中有海康门禁,中控门禁;空调类中可能还会分出不同的大类,具体大类如何区分,主要看他们的调用参数和功能是否一致,例如海康门禁需要的是ip,port,用户和密码,而某款门禁他只用门禁地址,这时候可以强制合并,但是建议还是分开,不然会出现冗余字段。至于有部分ip,port可以当作com和波特率使用(建议勤快的人还是分开)。
- 在类中重新定义Type属性,为了将硬件类型进行强制区分,上一篇中TreeView的顶级就是以Type进行分类的,下面才是实际的硬件型号(实现该接口的类)。
接口项目
在硬件集合文件夹中创建硬件接口文件夹,并创建IAccessControlLibrary和IAirConditionLibrary项目
在这两个项目中分别创建IAccessControlClient和IAriConditionClient类,并设置为抽象类(abstract),继承HardwareAbstract类。
以IAriConditionClient为例
public abstract class IAriConditionClient : HardwareAbstract
{
public static readonly string Type = "空调";
}
public class AirConditionInfo : HardwareInfo
{
string _设备地址;
/// <summary>
/// 设备号
/// </summary>
public string 设备地址 { get => _设备地址; set => _设备地址 = value; }
}
-
IAriConditionClient
IAriConditionClient中Type为该类型的名称,用于进行分类
-
HardwareInfo
该类是硬件信息,与HardwareProperties的区别如下:
- HardwareProperties类中存放的是该硬件类的属性信息,例如硬件类型,型号,版本,依赖包和功能等针对于该硬件的信息。
- HardwareInfo类中存放了同一个硬件中不相同的属性,例如设备主键,IP地址,设备地址等,虽然也有相同部分,可以认为是冗余数据。
- 用处不同,HardwareProperties主要用于产品库的展示和更新硬件时依赖项的赋值及版本的判断,因此该类主要存储的是总体信息;而HardwareInfo用于硬件网关中调用数据时传入的信息,例如向上位机发送温湿度时,不添加设备主键如何知道哪个设备传入的信息。
- 是否能合并?答案肯定是可以的,不过一旦合并感觉冗余的数据有多了很多,而且两个类之间的使用可以部分解耦,因此暂时先不进行合并。
该类的属性信息如下:
/// <summary> /// 设备类型 /// </summary> private string _设备类型; /// <summary> /// 设备主键 /// </summary> private string _设备主键; /// <summary> /// 设备型号 /// </summary> private string _设备型号; /// <summary> /// 设备ip地址 /// </summary> private string _Ip地址; /// <summary> /// 设备端口号 /// </summary> private string _端口号; /// <summary> /// 备注 /// </summary> private string _备注; /// <summary> /// 定时功能设定 /// </summary> private List<FunctionSetting> _定时功能; /// <summary> /// 功能列表 /// </summary> private List<Function> _操作功能; /// <summary> /// 初始化 /// </summary> private List<Function> _初始化;
其中FunctionSetting类为调度任务所需要的类,为防止后续忘记,在此也将属性进行罗列
/// <summary> /// 功能码 /// </summary> private Function _runFunction; /// <summary> /// 功能码说明 /// </summary> private string _functionStr; /// <summary> /// Cron /// </summary> private string _cronTime;
本来还有_nextFunction,意为执行该功能码后是否有关联功能码直接调用,之后由于并没有因此将该属性去掉。
_cronTime 原来为执行时间(_dateTime),之后改为了cron,因此在此将属性进行修改。
门禁项目接口同空调接口,本文就不再重复,门禁接口代码如下:
硬件项目
硬件项目说明
在硬件集合文件夹中添加门禁和空调的文件夹,并分别创建两个硬件类,实现各自的抽象类。
项目创建如图:
这里将之前的硬件接口文件夹改为了00硬件接口,每个硬件类都创建了单独的文件夹,硬件类前面的标号为约定好的硬件类型编号,而例如01HkAccessControlLibrary表示为门禁类中,海康门禁的型号是0501,这样就有了唯一的硬件类别和唯一标识与该dll对应。该唯一标识在硬件实现类中也有使用。
实现抽象类
在01TestAirConditionLibrary中创建TestAirConditionClient.cs类,并继承抽象类IAriConditionClient
public class TestAirConditionClient : IAriConditionClient
{
public override AjaxResult Execute(Function function, string hardware, string param)
{
throw new NotImplementedException();
}
public override HardwareProperties GetHardwareInfo()
{
throw new NotImplementedException();
}
}
注:这里改正之前描述的错误,就是abstract抽象接口与interface的接口方法一致,class继承后必须实现该类,否则会报错。之前编写的时候有误。
对TestAirConditionClient进行修改,添加GetHardwareInfo方法的返回值
#region 约定的相关信息
private const String Model = "实际硬件型号";
private const int Version = 1;
private const String Describe = "对于该硬件的信息描述";
#endregion
#region 功能部分
private readonly List<Function> OperationFun = new List<Function>() { Function.SettingTemputre, Function.HumAndTem, Function.OpenMachine, Function.CloseMachine};
private readonly List<Function> TimeingFun = new List<Function>() { Function.HumAndTem, Function.Beat };
#endregion
public override HardwareProperties GetHardwareInfo()
{
return new HardwareProperties("04", "0401", IAriConditionClient.Type, Model, null, null, Version, Describe, typeof(AirConditionInfo), OperationFun, null, TimeingFun, null);
}
-
HardwareProperties构造函数传入的属性请参见上文的构造类。其中OperationFun和TimeingFun分别表示的可操作功能和定时功能。
-
Function.HumAndTem和Function.Beat为新增功能,需要在Function中添加
/// <summary> /// 获取温湿度 /// </summary> [Description("获取温湿度")] HumAndTem = 08, /// <summary> /// 心跳 /// </summary> [Description("心跳")] Beat = 09,
门禁项目接口类似,就不一一描述了,最后实现类如下:
private const string Model = "海康门禁";
private const int Version = 1;
private const string Describe = "海康门禁";
private const string RelyOnFolder = "hk";
private readonly List<Function> OperationFun = new List<Function>() { Function.GetPersonList, Function.Beat };
private readonly List<Function> TimeingFun = new List<Function>() { Function.Beat };
private readonly List<Function> InitializationFun = new List<Function>() { Function.Initialization };
public override AjaxResult Execute(Function function, string hardware, string param)
{
throw new NotImplementedException();
}
public override HardwareProperties GetHardwareInfo()
{
return new HardwareProperties("05", "0501", IAccessControlClient.Type, Model, RelyOnFolder, null, Version, Describe, typeof(AccessInfo), OperationFun, InitializationFun, TimeingFun, null);
}
- 新添加的Function请按照上面的写法自行添加
- RelyOnFolder为依赖的文件夹,因为海康有一整个文件夹的运行库作为依赖,将该依赖放置在第五个参数中;如果只依赖一个文件,我们可以将它放在第六个参数中,注意relyOnFiles为文件夹列表,文件名称也要写全。
- 第11个参数为当实例加载完成后调用的初始化方法
- 第13个参数independentFun为模块功能,例如在硬件类中做一个端口映射,该功能不需要指定设备,是独立与设备之外的,类似于设备类的功能。
编译一下,如果有问题,可能是引用问题,需使用Alt+Enter进行库的引用。
项目生成路径修改
将HardwareGatewayProductization项目的生成路径改为:..\bin\Debug\产品库\
将硬件项目的生成路径改为:..\..\..\bin\Debug\产品库\plugins\硬件类型名称
,例如01HkAccessControlLibrary可修改为:..\..\..\bin\Debug\产品库\plugins\空调
。
重新生成后,生成路径会修改为
同级依然还存在很多dll,而且每个硬件中也有大量dll,让我们来精简一下。
优化依赖项
- 在bin->Debug->产品库文件夹创建dlls文件夹(系统中的文件夹,非vs中的),将公共库中的项目生成路径都设置为该文件夹。路径设置为:
..\..\bin\Debug\产品库\dlls\
。 - 同理,将硬件接口中的项目生成路径也修改为dlls文件夹中。路径设置为:
..\..\..\bin\Debug\产品库\dlls\
。 - 将HardwareGatewayProductization和硬件项目引用依赖的属性
复制本地
都改为false。 - 在bin->Debug->产品库文件夹中创建runtime文件夹,如果不创建运行HardwareGatewayProductization会失败。
重新生成,查看效果。
此时exe同级下 就没有多余的dll依赖文件了(如果有,可以删除然后重新生成产品库的项目)。
硬件项目也只有本项目自己的dll,而其他依赖都没有进行复制,如果生成时还有,可将所有dll删除然后重新尝试。
此时,所有的依赖都来到了dlls文件夹中,这样在后期复制时可以直接复制dlls文件夹到硬件网关项目即可。
目前会发现这个报错(提示是未找到引用),不过我这边并不影响运行使用,因此就直接忽略了红线的报错。
运行后效果如图:
标签:Function,string,平台,产品库,private,硬件,文件夹,门禁 From: https://www.cnblogs.com/wanghun315/p/17607549.html