硬件管理平台-硬件产品库-硬件项目

发布时间 2023-08-05 09:56:10作者: 摧残一生

硬件管理平台-硬件产品库-硬件项目

本篇主要描述的是如何创建一个硬件项目,并将硬件信息进行展示。

讲了这么多至少应该能出个效果吧

在产品库文件夹中创建一个硬件集合文件夹,该文件夹存放所有硬件项目,在创建硬件项目前我们需要创建某类硬件项目的硬件接口。

我们在此以门禁和空调为例。门禁的功能有监听门禁事件,获取人员列表;空调的功能有开关机,定时获取温湿度等。

关于海康门禁的功能可以查看我的博客中的相关代码,在这里就不重复说明了。例如:门禁实时获取记录

硬件接口项目

接口项目何用

  • 创建接口项目主要用于对硬件进行分类,例如空调硬件,门禁类硬件,灯控类等等,就是之前提到的所谓的硬件类型。里面再分具体型号,例如门禁类中有海康门禁,中控门禁;空调类中可能还会分出不同的大类,具体大类如何区分,主要看他们的调用参数和功能是否一致,例如海康门禁需要的是ip,port,用户和密码,而某款门禁他只用门禁地址,这时候可以强制合并,但是建议还是分开,不然会出现冗余字段。至于有部分ip,port可以当作com和波特率使用(建议勤快的人还是分开)。
  • 在类中重新定义Type属性,为了将硬件类型进行强制区分,上一篇中TreeView的顶级就是以Type进行分类的,下面才是实际的硬件型号(实现该接口的类)。

接口项目

硬件集合文件夹中创建硬件接口文件夹,并创建IAccessControlLibraryIAirConditionLibrary项目

在这两个项目中分别创建IAccessControlClientIAriConditionClient类,并设置为抽象类(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的区别如下:

    1. HardwareProperties类中存放的是该硬件类的属性信息,例如硬件类型,型号,版本,依赖包和功能等针对于该硬件的信息。
    2. HardwareInfo类中存放了同一个硬件中不相同的属性,例如设备主键,IP地址,设备地址等,虽然也有相同部分,可以认为是冗余数据。
    3. 用处不同,HardwareProperties主要用于产品库的展示和更新硬件时依赖项的赋值及版本的判断,因此该类主要存储的是总体信息;而HardwareInfo用于硬件网关中调用数据时传入的信息,例如向上位机发送温湿度时,不添加设备主键如何知道哪个设备传入的信息。
    4. 是否能合并?答案肯定是可以的,不过一旦合并感觉冗余的数据有多了很多,而且两个类之间的使用可以部分解耦,因此暂时先不进行合并。

    该类的属性信息如下:

    /// <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,让我们来精简一下。

优化依赖项

  1. 在bin->Debug->产品库文件夹创建dlls文件夹(系统中的文件夹,非vs中的),将公共库中的项目生成路径都设置为该文件夹。路径设置为:..\..\bin\Debug\产品库\dlls\
  2. 同理,将硬件接口中的项目生成路径也修改为dlls文件夹中。路径设置为:..\..\..\bin\Debug\产品库\dlls\
  3. HardwareGatewayProductization和硬件项目引用依赖的属性复制本地都改为false。
  4. 在bin->Debug->产品库文件夹中创建runtime文件夹,如果不创建运行HardwareGatewayProductization会失败。

重新生成,查看效果。

此时exe同级下 就没有多余的dll依赖文件了(如果有,可以删除然后重新生成产品库的项目)。

硬件项目也只有本项目自己的dll,而其他依赖都没有进行复制,如果生成时还有,可将所有dll删除然后重新尝试。

此时,所有的依赖都来到了dlls文件夹中,这样在后期复制时可以直接复制dlls文件夹到硬件网关项目即可。

目前会发现这个报错(提示是未找到引用),不过我这边并不影响运行使用,因此就直接忽略了红线的报错。

运行后效果如图: