目       录

第六章           通讯控制器的设计... 2

6.1           控制器接口... 2

6.2           串口控制器... 3

6.3           网络控制器... 5

6.4           通讯控制管理器... 9

6.5           远程交互... 9

6.6           小结... 10

第六章     通讯控制器的设计

经过前几章的介绍,这章介绍通讯控制器。主要负责对设备驱动(IRunDevice)、IO通道(IIOChannel)进行协调、调度、以及事件做出响应,在此基础上实现轮询通讯模式、并发通讯模式和自控通讯模式的任务调度。由于串口和网络硬件链路特性的原因以及通讯机制不一样,所以通讯控制器的实现上也有很大差别。

6.1    控制器接口

控制器内置一个线程负责对设备驱动和IO实例进行任务协调、调度,相当于在《第4章 设备管理器的设计》、《第5章 串口和网络的IO设计》实现的基础上构建了一个更高层次的协调机制,并实现设备与IO的匹配、不同的通讯机制。

不管串口通讯控制器和网络通讯控制器如何实现,都会继承自统一的(IIOController)接口,接口定义的代码如下:

public interface IIOController
{
/// <summary>
/// 当然是否工作
/// </summary>
bool IsWorked { set; get; } /// <summary>
/// IO控制器的关键字。
/// </summary>
string Key { get; } /// <summary>
/// 启动服务
/// </summary>
void StartService(); /// <summary>
/// 停止服务
/// </summary>
void StopService(); /// <summary>
/// IO控制器类型
/// </summary>
CommunicationType ControllerType { get; }
}

控制层次结构图如下:

6.2    串口控制器

每个(硬件)串口都对应一个串口控制器,每个串口控制器里都会有一个独立的线程,也就是说用到多少个串口号就会有多少个控制器和线程。框架平台可能会挂载多个设备驱动(插件),有可能一个设备驱动对应一个串口,也可能几个设备驱动共用一个串口,那么也就是说串口控制器和设备驱动之间存在1对1或1对N的关系。结构示意图如下:

一个串口控制器内的所有设备设置的串口通讯参数都是一样的,所以设备驱动(IRunDevice)接口的COM中的Port属性、IO接口(IIOChannel)的Key属性、以及串口控制器(IIOController)接口Key属性是一致的,都用于标识串口号。既然一个串口控制器中的所有设备都共用一个硬件串口,就决定了所有设备驱动之间的任务调度只能采用轮询模式,一个设备发送和接收操作完之后,再调度下一个设备驱动,设备驱动之间就是串行工作模式,避免一个串口控制器内多个设备驱动同时操作串口IO导致数据混乱,影响正常通讯。

一个串口控制器内的设备驱动是串行工作模式,如果把所有设备驱动都设置成一个串口号,在一个串口控制器下串行调度,那么就会影响设备驱动的通讯效率,某个设备的调度周期的公式如下:

某个设备调度周期=(串口控制器所有设备数-1)* 单个设备驱动执行耗时

这仅是一个理论值,实际应用中要比这个理论值要大,因为涉及到不类型的设备驱动共用一个串口号,在一个串口控制器下工作,处理的数据流程、方式不同,例如:有可能数据保存在TXT文件中、有可能保存在SQL数据库中、有可能保存在NoSQL数据库中等等。

有人会想,岂不是在一个串口下挂载的设备越多效率越低,的确是这样的。但是,多个串口控制器之间是并行工作模式。如果现场环境对通讯效率有要求的话,可以增加串口服务器,也就是增加可用的串口硬件电路,把N个设备驱动平衡负载到不同的串口上,增加并行运行的串口控制器的节点,进而提高框架平台的运行效率。

但是,这样解决之后也带来一定的风险和瓶颈,就是对于数据的存储,如果多个并行的数据流同时向一个单线程的存储介质写数据,那么又会造成互斥的现象,甚至造成意想不到的结果或异常,如下图:

如果同时向Sql Server、Oracle、Mysql等数据库存储数据,那么是没有问题的;如果采用文本文件、桌面数据库等存储数据,那么可能存在问题,可以分多个文件进行保存操作。DCS系统大多采用PI(Plant Information System)数据库。总之,作为一个系统来讲,需要整体设计、考虑,这块需要特别注意。

6.3    网络控制器

框架平台只有一个网络控制器,网络控制器内有一个独立的线程负责对所有网络设备驱动进行轮询、并发、自控模式通讯调度。轮询通讯模式与串口控制器类似,只是串行的调度所有网络设备驱动,但是框架只有一个网络控制器,不能通过增加网络控制器来提高通讯效率,这种模式是网络通讯调度鸡肋;并发通讯模式,线程会通过控制器中的线程集中发送所有设备的请求命令数据,接收数据是通过IO异步监听来完成,异步接收到数据后再把数据分发到设备驱动的RunIODevice接口,进行数据处理;自控通讯模式,发送命令数据的职能移交给了设备驱动本身,可以通过定时器来完成发送命令数据的功能,线程不再负责发送命令数据,接收数据与并发通讯模式一样。网络控制器的内部示意图如下:

针对网络通讯,轮询通讯模式是不能发挥其优势的,所以增加了并发通讯模式和自控通讯模式。后两种通讯模式会用到《第4章 设备驱动管理器的设计》的“4.6   设备计数器的特殊用处”的设计,设备驱动计数器如果大于等于某个值的时候,就会通过RunIODevice(new byte[]{})驱动当前设备,执行整个设备处理流程,以改变设备驱动的运行状态,实际上当前设备驱动处于“通讯中断”状态。

发送数据代码如下:

public void ControllerSend(IRunDevice dev, byte[] data)
{
int counter = DeviceManager.GetInstance().GetCounter(dev.DeviceParameter.DeviceID.ToString());
int sendNum = SessionSocketManager.GetInstance().Send(dev.DeviceParameter.NET.RemoteIP, data);
if (sendNum == data.Length && sendNum != 0)
{
DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "发送请求数据");
Interlocked.Increment(ref counter);
}
else
{
Interlocked.Increment(ref counter);
DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, "尝试发送数据失败");
}
dev.ShowMonitorIOData(data, "发送");
if (counter >= 3)
{
try
{
dev.RunIODevice(new byte[] { });
}
catch (Exception ex)
{
DeviceMonitorLog.WriteLog(dev.DeviceParameter.DeviceName, ex.Message);
GeneralLog.WriteLog(ex);
}
Interlocked.Exchange(ref counter, 0);
}
DeviceManager.GetInstance().SetCounter(dev.DeviceParameter.DeviceID.ToString(), counter);
}

异步接收、分数据的代码如下:

private void NETDeviceController_ReceiveSocketData(object source, ReceiveSocketDataArgs e)
{
if (GlobalProperty.GetInstance().ControlMode == ControlMode.Parallel || GlobalProperty.GetInstance().ControlMode == ControlMode.Self)
{
int counter = 0;
IRunDevice dev = null;
IRunDevice[] list = DeviceManager.GetInstance().GetDevices(e.RemoteIP, CommunicationType.NET);
for (int i = 0; i < list.Length; i++)
{
dev = list[i];
if (String.CompareOrdinal(dev.DeviceParameter.NET.RemoteIP, e.RemoteIP) == 0)
{
dev.ShowMonitorIOData(e.ReceiveData, "接收");
dev.AsyncRunIODevice(e.ReceiveData);
counter = DeviceManager.GetInstance().GetCounter(dev.DeviceParameter.DeviceID.ToString());
Interlocked.Decrement(ref counter);
if (counter < 0)
{
Interlocked.Exchange(ref counter, 0);
} DeviceManager.GetInstance().SetCounter(dev.DeviceParameter.DeviceID.ToString(), counter);
}
}
}
}

6.4    通讯控制管理器

通讯控制管理器负责对串口控制器和网络控制器进行管理,实际上是对Dictionary<Key,Value>进行的封装,所有涉及到操作控制器的地方都是通过控制管理器来完成的。IIOControllerManager<TKey, TValue>通讯控制管理器的接口定义如下:

6.5    远程交互

在了解串口控制器和网络控制器的基本原理和功能后,还要考虑到一个应用场景:控制器不仅仅要与硬件进行数据交互,还有可能要把采集上来的数据转发到其他服务器或节点上,也就是框架平台要具备路由的功能,整合设备驱动采集上来的数据,进行打包、转发。

从这个应用场景来看,在开发设备驱动的时候,不适合在设备驱动的处理流程中进行转发、多业务处理,受环境、网络、业务复杂度的影响可能会阻塞控制器的调度,影响框架的整体运行效率。

在物联网建设中,多级互联、逐层转发是很常见技术需求。为了解决这个现实问题,框架平台提供了IAppService应用服务接口,二次开发者可以把设备驱动中的数据信息封装后传入到IAppService接口中,可以在这里实现缓存、转发等具体的业务服务。这样设计的主要目的是不影响框架平台实时的数据采集,保证数据源的稳定性。

IAppService具体的设计和应用将来《第7章 外部接口的设计》中进行详细介绍。

6.6    小结

通讯控制器实现这后,理论上框架平台就能够跑起来了,但是距离我们开始设计的目标还差很多工作要做,还不能为二次开发提供很大的便利。在后续的设计中,慢慢的会把框架平台丰富起来。

作者:唯笑志在

Email:504547114@qq.com

QQ:504547114

.NET开发技术联盟:54256083

文档下载:http://pan.baidu.com/s/1pJ7lZWf

官方网址:http://www.bmpj.net

[连载]《C#通讯(串口和网络)框架的设计与实现》- 6.通讯控制器的设计的更多相关文章

  1. [连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言

                                  目       录 前言 前言 刚参加工作,使用过VB.VC开发软件,随着C#的崛起,听说是C++++,公司决定以后开发软件使用C#,凭借在 ...

  2. 《连载 | 物联网框架ServerSuperIO教程》-4.如开发一套设备驱动,同时支持串口和网络通讯。附:将来支持Windows 10 IOT

    1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...

  3. [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍

    [连载]<C#通讯(串口和网络)框架的设计与实现>- 0.前言 目       录 第一章           通讯框架介绍... 2 1.1           通讯的本质... 2 1 ...

  4. [连载]《C#通讯(串口和网络)框架的设计与实现》-2.框架的总体设计

    目       录 C#通讯(串口和网络)框架的设计与实现... 1 (SuperIO)- 框架的总体设计... 1 第二章           框架总体的设计... 2 2.1           ...

  5. [连载]《C#通讯(串口和网络)框架的设计与实现》- 5.串口和网络统一IO设计

    目       录 第五章           串口和网络统一IO设计... 2 5.1           统一IO接口... 2 5.1.1    串口IO.. 4 5.1.2    网络IO.. ...

  6. [连载]《C#通讯(串口和网络)框架的设计与实现》-4.设备驱动管理器的设计

    目       录 第四章           设备驱动管理器的设计... 2 4.1           接口定义... 2 4.2           设备容器... 7 4.3          ...

  7. [连载]《C#通讯(串口和网络)框架的设计与实现》-3.设备驱动的设计

    目       录 第三章           设备驱动的设计... 2 3.1           初始化设备... 4 3.2           运行设备接口设计... 4 3.3        ...

  8. Android网络框架Volley(体验篇)

    Volley是Google I/O 2013推出的网络通信库,在volley推出之前我们一般会选择比较成熟的第三方网络通信库,如: android-async-http retrofit okhttp ...

  9. 家庭洗车APP --- Androidclient开展 之 网络框架包介绍(一)

    家庭洗车APP --- Android客户端开发 之 网络框架包介绍(一) 上篇文章中给大家简单介绍了一些业务.上门洗车APP --- Android客户端开发 前言及业务简单介绍,本篇文章给大家介绍 ...

随机推荐

  1. Maven搭建SpringMVC+Hibernate项目详解 【转】

    前言 今天复习一下SpringMVC+Hibernate的搭建,本来想着将Spring-Security权限控制框架也映入其中的,但是发现内容太多了,Spring-Security的就留在下一篇吧,这 ...

  2. 如何使用本地账户"完整"安装 SharePoint Server 2010+解决“New-SPConfigurationDatabase : 无法连接到 SharePoint_Config 的 SQL Server 的数据 库 master。此数据库可能不存在,或当前用户没有连接权限。”

    注:目前看到的解决本地账户完整安装SharePoint Server 2010的解决方案如下,但是,有但是的哦: 当我们选择了"完整"模式安装SharePointServer201 ...

  3. React Native 之 Text的使用

    前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所 ...

  4. 解决:win10_x64 VMware Workstation and Hyper-V are not compatible. Remove the Hyper-V role from the system before running VMware Workstation

    bcdedit /set hypervisorlaunchtype off A reboot of of the Windows OS is necessary  必须重启才能生效   To enab ...

  5. Struts2.5需要的最少jar文件

    以Struts2.5.2为例 从官网上下载“struts-2.5.2-min-lib.zip”,里面有7个jar文件: commons-fileupload-1.3.2.jarcommons-io-2 ...

  6. 面向组合子设计Coder

    面向组合子 面向组合子(Combanitor-Oriented),是最近帮我打开新世界大门的一种pattern.缘起haskell,又见monad与ParseC,终于ajoo前辈的几篇文章. 自去年9 ...

  7. WebEssentials 在vs2013 update5安装报错的解决方法.

    WebEssentials 最高支持到update4 如果更新到了update5 RC, 则无法直接安装. 解决方法是 1,下载WebEssentials2013.vsix 文件. 2, 安装7zip ...

  8. Running Dubbo On Spring Boot

    Dubbo(http://dubbo.io/) 是阿里的开源的一款分布式服务框架.而Spring Boot则是Spring社区这两年致力于打造的简化Java配置的微服务框架. 利用他们各自优势,配置到 ...

  9. some OpenGL constants

    some OpenGL constants This is from (https://github.com/peterderivaz/pyopengles/blob/master/gl2.py) G ...

  10. SQL Server 服务器磁盘测试之SQLIO篇(一)

    数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速度,通过性能计数器Avg.Disk sec/Read(Wr ...