硬件管理平台-硬件网关-插件模块-集成(下)

硬件管理平台-硬件网关-插件模块-集成(下)

简介

通过以上的几篇文章说明了xml的相关配置信息和配置项,我们可以对插件模块的剩余部分进行说明了。当网关服务加载了本地的硬件插件后就产生了硬件类型的实例,通过该实例就可以去调用下位机了。而去调用哪个下位机,我们就需要通过xml的配置信息去指定,例如我们要调用IP为192.168.1.52的门禁,测试它的登录功能,HardwareInfo.xml中就需要有该门禁的相关信息,包含了ip地址,用户名,密码以及端口号,还有相关的对外暴露的功能。当初始化了门禁类的实例后,再加上xml中特定的信息就可以对特定门禁的特定功能进行调用,这样的好处是可以动态的进行插拔更新,也可以很好的将硬件与网关解耦。

正文

完成RefreshHardware方法后,开始为读取HardwareInfo.xml做准备:

  1. HardwareServices中申明HardwareOptXml 类并进行实例化:

    private HardwareOptXml xmlClient = new HardwareOptXml();
    

    在RefresHardware下放增加一个OnStartByXml方法,该方法的功能是将HardwareInfo.xml文件的硬件信息进行读取并存放到HardwareXmlEntity列表中,然后通过获取TimeingFuninitializationFun的变了来分别完成各自的业务需求,其中InitializationFun为将该设备初始化,而TimeingFun功能涉及到了任务调度部分,因此本章不涉及,会在后续进行详细说明。

    public void OnStartByXml()
    {
    	// 重新打开一次HardwareInfo文件-意味着刷新硬件实例列表
        xmlClient.RefreshXml();
        // 获取硬件实例
        List<HardwareXmlEntity> hardwareDics = xmlClient.GetHardwareInfos();
        // 调用插件类的开始方法,将硬件实例放置到该方法中进行相关的开始工作
        Task.Factory.StartNew(async () =>
                              {
                                  await pluginManager.OnStartAsync(hardwareDics);
                              });
    }
    

    插件模块的OnStart方法部分主要描述的是硬件实例的初始化和调用部分

    public async Task OnStartAsync(List<HardwareXmlEntity> hardwareDics)
    {
        if (hardwareDics.Count > 0)
        {
            // 将反射的硬件类型实例与硬件实例合并,转换为以key为型号,value为设备实例的字典,便于后面使用
            Dictionary<String, List<HardwareXmlEntity>> dic = new Dictionary<string, List<HardwareXmlEntity>>();
            hardwareDics.ForEach(item => {
                String sbxh = item.Param["设备型号"];
                if (hardwareDic.ContainsKey(sbxh))
                {
                    // 判断是否存在该类型,如果不存在就创建一个
                    if (!dic.ContainsKey(sbxh))
                    {
                        dic.Add(sbxh, new List<HardwareXmlEntity>());
                    }
                    dic[sbxh].Add(item);
                }
            });
            foreach (var key in dic)
            {
                // 进行初始化方法操作,后期会将回调一个调度实例,然后继续调度任务的操作
                await Initialization(key.Value, hardwareDic[key.Key], key.Key);
                // 该处将增加调用任务的相关代码
            }
        }
    }
    

    Initialization方法为调用硬件类型的初始化实例

    public async Task<bool> Initialization(List<HardwareXmlEntity> item, HardwareAbstract @abstract, String sbxh)
    {
        // 设置一个初始化实例
        InitHardwareEntity iInitClass = new InitHardwareEntity(item, @abstract, sbxh);
        bool v = await Task<bool>.Factory.StartNew(init =>
        {
            // 获得到,之前怕传入的方法多,该实例会变
            InitHardwareEntity initClass = (InitHardwareEntity)init;
            initClass.item.ForEach(t =>
            {
                try
                {
                    // 如果存在InitializationFun功能模块
                    if (null != t.InitializationFun)
                    {
                        t.InitializationFun.ForEach(fun =>
                        {
                            try
                            {
                                // 调用InitializationFun中存储的功能模块
                                AjaxResult result = initClass.@abstract.Execute(fun, t.ParamJson, "");
                            }
                            catch (Exception ex)
                            {
    
                            }
                        });
                    }
                }
                catch (Exception ex)
                {
                    _logerror.Error("hardwareDics.ForEach错误", ex);
                }
            });
            return true;
        }, iInitClass);
        return v;
    }
    
  2. 创建GetFunction方法,该方法的主要作用是调用硬件的OperationFun部分的功能码,为硬件网关主动调用下位机的操作。

    之前的设计为全是异步操作,硬件网关获取数据后通过上位机暴露的方法再进行传输,这样可完成上位机到硬件网关的异步操作。

    在HardwareService中增加存储硬件实例的声明

    readonly Dictionary<string, HardwareXmlEntity> hardwareXmlEntities = new Dictionary<string, HardwareXmlEntity>();
    

    增加OperationFun调用的方法

    public AjaxResult GetFunction(String function, String hardwareInfo, String param)
    {
        String deviceId = "";
        // 如果硬件实例为空,则刷新获得
        if (hardwareXmlEntities.Count == 0)
        {
            RefreshHardwareDics();
        }
        // 没有未找到该主键,则尝试获取
        if (!String.IsNullOrEmpty(hardwareInfo) && hardwareXmlEntities.ContainsKey(hardwareInfo))
        {
            deviceId = hardwareInfo;
            hardwareInfo = JSONUtils.SerializeObject(hardwareXmlEntities[hardwareInfo].Param);
        }
        //根据描述获得
        Function fun = AssemblyUtil.GetEnumByDescription<Function>(function);
        if (fun == 0)
        {
            fun = AssemblyControl.GetEnumByName<Function>(function);
        }           
        try
        {
            // 调用方法
            return pluginManager.Function(fun, hardwareInfo, param);
        }
        catch (Exception ex)
        {
            String msg = $"GetFunction function:{function} hardwareInfo:{hardwareInfo} param:{param}";
            _logerror.Error(msg, ex);
            return AjaxResult.error("报错", ex.Message);
        }
    }
    

结尾

本文章主要介绍了上次集成时遗留下来的尾巴,主要涵盖了如何将反射的硬件类实例与xml中存储的硬件实例进行处理,并进行初始化以及等待上位机调用所开放的接口,接下来我们将开始系统调度的说明。

posted @ 2023-09-02 18:05  摧残一生  阅读(19)  评论(0编辑  收藏  举报