容器、接口、注册订阅、组合实现驱动层隔离

在工控系统开发中,随着项目和业务量的增加,接触到了各种各样的设备,上位工控系统要与设备通过串口、网口、PCI访问,等各种方式实现设备指令的调用。


各种设备指令,在业务调用层被映射到了各种功能调用和视图表现。因为新设备每个项目都在增加,客户也需要对设备的监控或控制的粒度各不同,底层的设备驱动层则要封装大量的功能函数。每次随着新设备的引入,业务场景为了对设备的调用功能更好的描述,也需要更改对应的业务调用。初期采用弱类型,通过在业务层反射类型并识别设备业务调用功能,虽然弱类型实现了设备驱动与业务层的解耦,但是由于是弱依赖,对二次开发人员,进行逻辑开发时,造成了重重的困难,主要是定位问题点不容易,因为弱类型很多时候在运行时进行业务关联。

为了解决设备增加,在软件产品版本中带来的冲击,采用过弱类型设计方案,也采用过公共指令集方式,等等,但是都会在其应用场景中带来很多不便因素。

参阅一些物联网工业标准,例如AllJoyn,其中也会出现大量的设备,而且各种设备也是预先无法界定的,但是其框架的通用性在于,设备只要具备AllJoyn中的接口,就可以实现插入AllJoyn网络的目的。因此在新的版本产品开发中,也引入了基于接口的业务剥离,大量的接口托管,通过其对应的接口容器来托管,设备驱动在实现时,按照框架接口实现,并且业务调用,仅仅支持接口调用,通过设备驱动构建时,注册到接口容器,实现设备实例到接口的关联。基于此思路之后,初期接口数量会随着设备的功能描述,大量增加,随着接口的逐步完善,后续新的设备引入时,不会再出现接口的增加,可能有几百个接口,就可以同时支撑几万种设备的应用了,业务层的开发,也会随着接口的调用,与驱动层完成了剥离。

接口容器类:

/// <summary>
    /// 容器接口服务
    /// </summary>
    interface IDockerService
    {
        /// <summary>
        /// 根据键取消某一个设备注册
        /// </summary>
        /// <param name="key"></param>
        void CancelRegister(string key);
        /// <summary>
        /// 取消所有注册
        /// </summary>
        void CancelRegisterAll();
        /// <summary>
        /// 注册设备到容器
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="device">设备</param>
        void RegisterDevice(string key, object device);
    }

接口容器基类:

 /// <summary>
    /// 容器服务基类
    /// </summary>
    public abstract class BaseDockerService<T> : IDockerService where T : class
    {
        public BaseDockerService()
        {
            this.dicMapDictionary = new Dictionary<string,T>();
        }
        /// <summary>
        /// 锁
        /// </summary>
        protected object syncLock = new object();
        /// <summary>
        /// 打开映射表
        /// </summary>
        protected Dictionary<string, T> dicMapDictionary = null;
        /// <summary>
        /// 注册设备
        /// </summary>
        /// <param name="key">唯一键</param>
        /// <param name="device">设备实例</param>
        public virtual void RegisterDevice(string key, object device)
        {
            if (device is T)
            {
                lock (syncLock)
                {
                    if (dicMapDictionary == null)
                    {
                        dicMapDictionary = new Dictionary<string, T>();
                    }
                    if (dicMapDictionary.ContainsKey(key) == false)
                    {
                        dicMapDictionary.Add(key, (T)device);
                    }
                }
            }
        }
        /// <summary>
        /// 取消注册,清理服务
        /// </summary>
        public virtual void CancelRegisterAll()
        {
            lock (syncLock)
            {
                if (dicMapDictionary != null)
                {
                    dicMapDictionary.Clear();
                }
            }
        }
        /// <summary>
        /// 取消注册,清理服务
        /// </summary>
        public virtual void CancelRegister(string key)
        {
            lock (syncLock)
            {
                if (dicMapDictionary != null)
                {
                    if (dicMapDictionary.ContainsKey(key))
                    {
                        dicMapDictionary.Remove(key);
                    }
                }
            }
        }
    }

日志容器示例实现:

/// <summary>
    /// 容器接收日志服务
    /// </summary>
    public class DockerReceiveLogService : BaseDockerService<IReceiveLog>
    {
        /// <summary>
        /// 日志触发事件
        /// </summary>
        public event EventHandler<LogEventArgs> OnLogReceived;
        /// <summary>
        /// 注册设备
        /// </summary>
        /// <param name="key">唯一键</param>
        /// <param name="device">设备实例</param>
        public override void RegisterDevice(string key, object device)
        {
            if (device is IReceiveLog)
            {
                lock (syncLock)
                {
                    if (dicMapDictionary == null)
                    {
                        dicMapDictionary = new Dictionary<string, IReceiveLog>();
                    }
                    if (dicMapDictionary.ContainsKey(key) == false)
                    {
                        ((IReceiveLog)device).OnLogReceived += DockerReceiveLogService_OnLogReceived;
                        dicMapDictionary.Add(key, (IReceiveLog)device);
                    }
                }
            }
        }
        /// <summary>
        /// 日志接收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DockerReceiveLogService_OnLogReceived(object sender, LogEventArgs e)
        {
            if (OnLogReceived != null)
            {
                OnLogReceived(sender, e);
            }
        }
    }
设备驱动实现基类:

/// <summary>
    /// 基础驱动基类服务
    /// </summary>
    public abstract class BasicDriveService<TInputMessageFilter, TOutputMessageFilter, TRequest, TResponse> : IOpen, IClose, IReceiveLog, ISendLog,
        IInfoReceived, IConnectSessionInfo
        where TRequest : BaseRequestData
        where TResponse : BaseResponseData
        where TInputMessageFilter : BaseInPutMessageFilter<TRequest>
        where TOutputMessageFilter : BaseOutPutMessageFilter<TRequest, TResponse>
    {
        /// <summary>
        /// 连接
        /// </summary>
        protected ICommunication<TRequest, TResponse> iCommunication;
        /// <summary>
        /// 启动状态
        /// </summary>
        public virtual bool IsOpen
        {
            get 
            {
                if (iCommunication != null)
                {
                    return iCommunication.IsOpen;
                }
                return false;
            }
        }

        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="isAsyncOpen"></param>
        public virtual void Open(bool isAsyncOpen)
        {
            BaseCommunicationParameters receivePa = this.CreateCommunicationParameters();
            if (iCommunication == null)
            {
                iCommunication = CommunicationFactory<TInputMessageFilter, TOutputMessageFilter, TRequest, TResponse>.Create(receivePa);
                iCommunication.OnResponseInfo += iReceiveCommunication_OnResponseInfo;
                iCommunication.OnOperateStaus += iReceiveCommunication_OnOperateStaus;
                iCommunication.OnSessionAdded += iReceiveCommunication_OnSessionAdded;
                iCommunication.OnSessionRemoved += iReceiveCommunication_OnSessionRemoved;
                iCommunication.OnResponseBuffer += iReceiveCommunication_OnResponseBuffer;
            }
            if (iCommunication.IsOpen == false)
            {
                iCommunication.Open();
            }
        }
        /// <summary>
        /// 构建设备通信参数
        /// </summary>
        /// <returns></returns>
        protected abstract BaseCommunicationParameters CreateCommunicationParameters();
        /// <summary>
        /// 关闭
        /// </summary>
        public virtual void Close()
        {
            if (iCommunication != null)
            {
                if (iCommunication.IsOpen == true)
                {
                    iCommunication.Close();
                }
                iCommunication = null;
            }
        }
        /// <summary>
        /// 应答处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected abstract void iReceiveCommunication_OnResponseBuffer(object sender, TResponse e);
        /// <summary>
        /// 连接会话断开
        /// </summary>
        /// <param name="info"></param>
        protected virtual void iReceiveCommunication_OnSessionRemoved(SessionInfo info)
        {
            if (OnConnectSession != null)
            { 
                ConnectSessionDataEventArgs args=new ConnectSessionDataEventArgs();
                OnConnectSession(this, args);
            }
        }
        /// <summary>
        /// 连接会话建立
        /// </summary>
        /// <param name="info"></param>
        protected virtual void iReceiveCommunication_OnSessionAdded(SessionInfo info)
        {
            if (OnConnectSession != null)
            {
                ConnectSessionDataEventArgs args = new ConnectSessionDataEventArgs();
                OnConnectSession(this, args);
            }
        }
        /// <summary>
        /// 操作状态反馈
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void iReceiveCommunication_OnOperateStaus(object sender, OperateStatus e)
        {
            if (e == OperateStatus.Opening)
            {
                if (OnInfoDataReceived != null)
                {
                    InfoData infoData = new InfoData("请求启动");
                    InfoDataEventArgs args = new InfoDataEventArgs(infoData);
                    OnInfoDataReceived(this, args);
                }
            }
            else if (e == OperateStatus.Opened)
            {
                if (OnInfoDataReceived != null)
                {
                    InfoData infoData = new InfoData("启动成功");
                    InfoDataEventArgs args = new InfoDataEventArgs(infoData);
                    OnInfoDataReceived(this, args);
                }
            }
            else if (e == OperateStatus.Closing)
            {
                if (OnInfoDataReceived != null)
                {
                    InfoData infoData = new InfoData("请求关闭");
                    InfoDataEventArgs args = new InfoDataEventArgs(infoData);
                    OnInfoDataReceived(this, args);
                }
            }
            else if (e == OperateStatus.Closed)
            {
                if (OnInfoDataReceived != null)
                {
                    InfoData infoData = new InfoData("关闭成功");
                    InfoDataEventArgs args = new InfoDataEventArgs(infoData);
                    OnInfoDataReceived(this, args);
                }
            }
        }
        /// <summary>
        /// 消息应答
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected virtual void iReceiveCommunication_OnResponseInfo(object sender, ResponseInfo e)
        {
            if (e.ResponseInfoType == ResponseInfoType.NotifyInfo)
            {
                if (OnInfoDataReceived != null)
                {
                    InfoData infoData = new InfoData(e.Message);
                    InfoDataEventArgs args = new InfoDataEventArgs(infoData);
                    OnInfoDataReceived(this, args);
                }
            }
            else if (e.ResponseInfoType == ResponseInfoType.Exception)
            {
               
            }
            else if (e.ResponseInfoType == ResponseInfoType.ReceiveLog)
            {
                if (OnLogReceived != null)
                {
                    LogData logData = new LogData(e.Message);
                    LogEventArgs args = new LogEventArgs(logData);
                    OnLogReceived(this, args);
                }
            }
            else if (e.ResponseInfoType == ResponseInfoType.SendLog)
            {
                if (OnLogSended != null)
                {
                    LogData logData = new LogData(e.Message);
                    LogEventArgs args = new LogEventArgs(logData);
                    OnLogSended(this, args);
                }
            }
        }
        /// <summary>
        /// 接收日志
        /// </summary>
        public event EventHandler<Base.DriveData.LogEventArgs> OnLogReceived;
        /// <summary>
        /// 发送日志
        /// </summary>
        public event EventHandler<Base.DriveData.LogEventArgs> OnLogSended;
        /// <summary>
        /// 底层的消息通知
        /// </summary>
        public event EventHandler<InfoDataEventArgs> OnInfoDataReceived;
        /// <summary>
        /// 会话连接建立断开触发事件
        /// </summary>
        public event EventHandler<ConnectSessionDataEventArgs> OnConnectSession;
    }

驱动实现,此处是一个简单的RMI实现过程,通过透明代理实现元数据的反射实现,此部分为服务器端的连接会话上的调用实现部分:
/// <summary>
    /// 调用测试Demo
    /// </summary>
    public class PDAScanDataService : BasicDriveService<PDAScanDataInputFilter, PDAScanDataOutputFilter, PDAScanDataRequest, PDAScanDataResponse>
    {
        /// <summary>
        /// 创建通信参数
        /// </summary>
        /// <returns></returns>
        protected override BaseCommunicationParameters CreateCommunicationParameters()
        {
            throw new NotImplementedException();
        }
        /// <summary>
        /// 应答处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void iReceiveCommunication_OnResponseBuffer(object sender, PDAScanDataResponse e)
        {
            if (e.ResponseException != null)
            {
                if (iCommunication != null && iCommunication.IsOpen == true)
                {
                    PDAScanDataRequest request = new PDAScanDataRequest();
                    request.ServerSend(e.ResponseException, e.ReturnTypeFullName);
                    iCommunication.Request(e.SessionID, request);
                }
                return;
            }
            try
            {
                object obj = e.Invoke();
                if (iCommunication != null && iCommunication.IsOpen == true)
                {
                    PDAScanDataRequest request = new PDAScanDataRequest();
                    request.ServerSend(obj, e.ReturnTypeFullName);
                    iCommunication.Request(e.SessionID, request);
                }
            }
            catch (Exception ex)
            {
                if (iCommunication != null && iCommunication.IsOpen == true)
                {
                    PDAScanDataRequest request = new PDAScanDataRequest();
                    request.ServerSend(ex.InnerException, e.ReturnTypeFullName);
                    iCommunication.Request(e.SessionID, request);
                }
            }
        }
        public virtual PDAScanData[] SearchAll(int a)
        {
            PDAScanData[] list = new PDAScanData[a];

            for (int i = 0; i < a; i++)
            {
                PDAScanData p = new PDAScanData();
                p.Id = i;
                p.Now = DateTime.Now;
                p.Status = STatus.正常;
                p.Str = i.ToString("0000000");
                list[i] = p;
            }
            return list;
        }
        public virtual PDAScanData[] FindAll()
        {
            PDAScanData[] list = new PDAScanData[30];

            for (int i = 0; i < 30; i++)
            {
                PDAScanData p = new PDAScanData();
                p.Id = i;
                p.Now = DateTime.Now;
                p.Status = STatus.正常;
                p.Str = i.ToString("0000000");
                list[i] = p;
            }
            return list;
        }

        public virtual PDAScanData[] SaveAll(PDAScanData[] collection)
        {
            for (int i = 0; i < collection.Length; i++)
            {
                PDAScanData p = collection[i];
                int id = p.Id;
            }
            return collection;
        }

        public virtual void Save(PDAScanData[] collection)
        {
            throw new Exception("保存数据失败");
        }

      
    }

RMI客户端的调用部分,通信采用TCP,底层基于Json进行序列化和反序列化,此处为客户端Stub:

/// <summary>
    /// 测试Demo部分,与服务器端的定义一致
    /// </summary>
    public class PDAScanDataService : ClientProxy
    {
        public PDAScanDataService()
            : base("Trace.Drive.Service.PDAScanDataService, Trace.Drive.Service, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
        {
        
        }
        public virtual PDAScanData[] SearchAll(int i)
        {
            Func<int,PDAScanData[]> tempAction = new Func<int, PDAScanData[]>(SearchAll);
            return (PDAScanData[])ClientSend(tempAction, new object[] { i });
        }

        public virtual PDAScanData[] FindAll()
        {
            Func<PDAScanData[]> tempAction = new Func<PDAScanData[]>(FindAll);
            return (PDAScanData[])ClientSend(tempAction, new object[] { });
        }

        public virtual PDAScanData[] SaveAll(PDAScanData[] collection)
        {
            Func<PDAScanData[],PDAScanData[]> tempAction = new Func<PDAScanData[],PDAScanData[]>(SaveAll);
            return (PDAScanData[])ClientSend(tempAction, new object[] { collection });
        }
        public virtual void Save(PDAScanData[] collection)
        {
            Action<PDAScanData[]> tempAction = new Action<PDAScanData[]>(Save);
            ClientSend(tempAction, new object[] { collection });
        }
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值