基于NI PSP协议的分布式测试系统软件设计
2019-10-29娟2高艳军段海彬
高 涛,常 娟2,高艳军,段海彬
(1.西安翔迅科技有限责任公司,西安 710068; 2.空军工程大学 基础部,西安 710051)
0 引言
分布式测试系统是计算机网络技术的产物,是一种通过局域网或Internet,把分布于不同地点、独立完成特定测试功能的计算机连接起来,达到测试资源共享、分散操作、集中管理、协同工作等目的网络测试系统[1]。测试计算机(下位机)一般位于测试现场的被测对象附近,可独立完成数据采集和预处理任务,并通过以太网将数据传输给控制计算机(上位机)[2]。上位机接收各下位机传送来的数据进行储存和分析处理,以图形化的方式显示数据,生成测试报表供用户查看。
按照通常的分布式测试软件设计方法,需要在下位机软件中实现数据采集和组包操作,然后通过以太网完成数据包的发送;在上位机软件中通过Winsock API函数接收数据包,并按照约定的数据包格式完成数据的拆包和提取显示[3]。进行软件开发时,为保证数据传输的可靠性,需要考虑数据包校验、错误重发、FIFO缓存队列等流程的设计,开发难度大且容易出错,对软件开发人员有比较高的要求。此外,当系统中有多个下位机同时工作时,大量测试数据通过以太网传输到上位机的过程中,如何保证数据的一致性将成为一个难点[4]。
为了简化这种应用的软件开发,NI公司提供了网络变量库(Network Variable Library)。该函数库基于NI PSP(NI Publish-Subscribe Protocol)协议,通过网络变量对底层网络通讯协议(TCP/IP和DDE)进行了抽象[5]。用户在NI公司的LabVIEW、LabWindows/CVI和NI Measurement Studio开发环境中使用网络变量库提供的API函数,可以在不影响系统性能的情况下,在多个系统或多个应用程序之间灵活的传递数据。
1 分布式测试系统设计
某分布式测试系统采用星型网络结构,多台远程数据采集终端RTU(Remote Terminal Unit)作为下位机布置在测试现场,每台RTU有50个采集通道,每一台RTU均通过以太网与远离测试现场的测控计算机(上位机)相连。这种星型结构的优点是网络控制容易、便于扩充、可靠性好[6]。
开始测试时,上位机通过以太网发送命令控制RTU进行数据采集,RTU以每个通道10k/s的采样率进行数据采集,并通过以太网将数据传输到上位机;上位机接收RTU传输的测试数据,对不同RTU的数据分别进行解析和显示,供用户查看。RTU的AD采样精度为16Bit,通过计算可以得出每台RTU在1秒内采集的数据量为10 k×50 ch×2 Byte=1 000 kByte。
操作人员在远离测试现场的地点通过操作测控计算机查看系统中各个RTU采集的测试数据,支持多个测控计算机共享数据,分布式系统的组成如图1所示。
图1 分布式系统组成框图
2 软件设计与实现
该系统中的RTU和测控计算机均运行Windows操作系统,各个RTU运行相同的下位机软件,通过配置文件给不同的RTU分配不同的IP地址,主要功能模块包括数据采集、组包、共享变量数据发布。测控计算机运行上位机软件,同样通过配置文件中的IP地址来控制不同的RTU协同工作,主要功能模块包括共享变量数据订阅、数据解包、处理、显示和存储。上下位机软件均使用NI LabWindows/CVI环境进行开发。
下位机软件作为测试数据的发布者,上位机软件作为数据的订阅者。在下位机和上位机之间使用NI PSP协议进行数据传输,首先需要创建共享网络变量并进行配置。
共享网络变量被部署到一个用于在网络上托管该变量的共享变量引擎SVE(Shared Variable Engine)。SVE是共享网络变量的服务器,所有对共享变量的应用(读或写)都是客户端。网络变量首先向共享变量引擎服务器发送数据,然后该服务器将这些数据发布给网络上的所有节点。因为数据是采用“发布-订阅”消息结构来传输的,所以客户端节点无需编写复杂的代码就可以访问网络变量数据[7]。
图2 共享变量传输过程
共享变量的创建和配置可以采用以下两种方式:一是使用NI提供的Distributed System Manager软件,在软件中以图形化的方式创建共享网络变量,另一种是使用Network Variable Library库函数,通过编程的方式创建共享网络变量[8]。
a)显式创建共享网络变量
图3 分布式系统管理器软件界面
安装完LabWindows/CVI开发环境后,系统中安装了“Distributed System Manager”软件工具,软件路径如下:“开始所有程序National InstrumentsDistributed System Manager”,软件界面如图3所示。
使用Distributed System Manager软件创建共享变量的步骤如下:
1)选中“localhost”项,通过鼠标右键菜单的“添加进程”创建共享变量进程“my_process”;
2)选中刚创建的进程,通过鼠标右键菜单“添加变量”创建共享变量“my_variable”,并设置变量类型和网络,同一个进程下可创建多个变量;
3)选中刚创建的进程,通过鼠标右键菜单进行“启动进程”、“停止进程”和 “删除进程”等操作。
当网络变量创建好后,网络中的其它计算机就可以通过网络变量路径来共享数据。共享变量的网络路径包括计算机名称、进程名称以及共享变量名。例如:“192.168.1.100my_processmy_variable”,其中“192.168.1.100”是数据发布计算机的IP地址,“my_process”是网络变量进程,“my_variable”是网络变量名[9]。
b)编程创建共享变量
LabWindows/CVI开发环境提供了Network Variable Library(网络变量函数库)来方便软件开发人员在程序中对共享变量进行操作。Network Variable Library库函数结构如图4所示,主要功能包括共享变量配置、数据包处理、变量发布和订阅操作等。
图4 Network Variable Library库函数结构
通过编程方式使用共享网络变量更为灵活,下面结合软件设计详细描述网络变量的编程使用方法。
2.1 下位机软件设计
该分布式系统的下位机负责采集测试现场的数据,是数据的发布端。下位机软件的流程设计如图5所示。
图5 下位机软件设计流程图
第一步,首先创建网络变量进程,通过调用函数库中的CNVNewProcess("my_process")函数新建名为"my_process"的网络变量进程,并使用CNVStartProcess("my_process")函数来启动该进程。
第二步,创建网络变量,通过调用网络变量函数库中的CNVNewVariable("my_variable")函数新建名为"my_variable"的网络变量,使用CNVSetVariableAttribute()函数可以对该网络变量的属性进行设置,比如将CNVVariableSingleWriterAttribute属性设置为1,说明该网络变量只有1个写入者;CNVVariableServerBufferMaxItemsAttribute属性可以设置在服务器端能容纳数据项的数量。
第三步,使用网络变量函数库中的CNVCreateWriter()函数在刚才新建的网络变量地址:“IPmy_processmy_variable”创建数据发布者;当需要更新的数据量较大时,可以使用CNVCreateBufferedWriter()函数来创建发送缓存区,提高数据的发送效率。创建完成后可以使用CNVGetConnectionAttribute()函数获得与共享网络变量的连接状态。
第四步,发布数据,通过共享网络变量传输的数据类型可以是单个变量、字符串,也可以是一个数据结构。
共享网络变量的数据类型如表1所示,用户可以根据需要设置共享变量的数据类型。软件在通过共享网络变量进行数据发布和读取时,均是按已设定的数据类型进行操作,不用考虑在传输中的数据转换问题。
表1 共享网络变量数据类型
当进行单一数据类型的数据传输时,通过使用CNVCreateScalarDataValue()函数创建不同类型的数据,再通过CNVWrite()函数发布到共享共享网络变量。
当进行复杂数据的传输时,需要将发送的数据组包为结构体进行发送。将数据组包为结构体的方法如下:
1)首先根据需要定义网络变量数据,数据类型为:CNVData。使用CNVCreateArrayDataValue()函数创建数组型的数据;使用CNVCreateScalarDataValue()函数创建数值型的数据;最后使用CNVCreateStructDataValue()函数创建包含若干个网络变量数据的结构体,示例代码如下所示;
CNVData data, fields[3]; //3个变量数据
Check(CNVCreateArrayDataValue (&fields[0], CNVInt16, &dataArray, 1, dims)); //数据数组
Check(CNVCreateScalarDataValue (&fields[1], CNVUInt16, 0)); //通道号
Check(CNVCreateScalarDataValue (&fields[2], CNVUInt32, 0)); //包序号
Check(CNVCreateStructDataValue (&data, fields, FIELDSIZE));
2)接下来将数据填充到刚才创建的结构体中,示例代码如下:
Check(CNVSetArrayDataValue (fields[0], CNVInt16, DataBuf, 1, dims));
Check(CNVSetScalarDataValue (fields[1], CNVUInt16, i));
Check(CNVSetScalarDataValue (fields[2], CNVUInt32, pkgIndex++));
Check(CNVSetStructDataValue (data, fields, FIELDSIZE));
3)最后使用CNVPutDataInBuffer()函数将组包好的数据通过数据发布者发布到共享网络变量。
第五步,软件退出前,使用CNVDispose()函数释放创建数据发布者或发布缓存,最后使用CNVFinish()停止共享变量引擎。
2.2 上位机软件设计
上位机负责读取共享网络变量的数据并进行处理,是数据的订阅端。上位机软件的流程设计如图6所示。
图6 上位机软件设计流程图
第一步,使用CNVCreateSubscriber()函数在网络变量地址创建数据订阅者;如果数据量较大,则使用CNVCreateBufferedSubscriber()函数创建数据订阅缓存。通过使用缓冲区,可以解决对于一个变量读/写速度的波动问题。当读出操作偶尔比写入操作慢的情况可能会导致一些更新数据的丢失,如果应用可以容忍数据丢失,就不需要使用缓冲区;但是如果读取操作必须获得每个更新数据,就需要使用缓冲区[10]。
第二步,使用CNVGetConnectionAttribute()函数获得与网络变量的连接状态,如果连接异常,提示用户检查错误原因并退出;
第三步,创建数据接收线程,不断的从网络变量读取数据,解析数据并进行显示,同时将数据写入记录文件中存储。
从共享网络变量接收数据并提取出有效数据的方法与发布端相反,步骤如下:
1)使用CNVGetDataFromBuffer()函数检查网络变量是否有新数据到达;
2)使用CNVGetNumberOfStructFields()函数获取接收到的结构体数量,
3)使用CNVGetStructFields()函数获取结构体数据;
4)使用CNVGetArrayDataValue()函数获取结构体中的数组元素,使用CNVGetScalarDataValue()函数获取结构体中的数据值;
5)测试完成后使用CNVDisposeData()函数释放网络变量接收缓存;
如果不需要获得网络变量的每个更新数据,仅获取最新数据进行显示,那么上面的5个步骤可以简化为以下3个:
1)使用CNVGetConnectionAttribute()函数通过CNVMostRecentDataAttribute参数查询最新的结构体数据;
2)在定时器函数中重复调用CNVGetArrayDataValue()函数获取共享网络变量结构体中的数组元素,使用CNVGetScalarDataValue()函数获取数据值;
3)测试完成后使用CNVDisposeData()函数释放网络变量接收缓存。
最后,当用户结束数据接收操作时,软件停止数据接收线程,使用CNVDispose()函数释放创建数据订阅者或订阅缓存,最后使用CNVFinish()停止共享变量引擎。
2.3 上下位机软件交互协议
在下位机上完成共享网络变量数据的发布流程以及在上位机上完成网络变量数据的订阅流程后,还需要制定上下位机之间的通讯交互协议,由上位机向下位机发送控制命令,下位机根据控制命令开始或停止数据采集和发布。
上下位机软件之间的交互命令包括开始自检、停止自检、开始测试、停止测试和关闭软件等几个命令。这些命令采用TCP协议进行传输,这样做的好处是将交互命令和共享网络变量的数据传输相互分离,简化软件的开发和数据处理流程。
上下位机软件之间的命令交互流程如图7所示。
图7 上下位机软件交互流程
第一步,下位机启动后首先在指定端口创建TCP Server和共享网络变量,等待上位机进行连接;上位机启动后根据配置文件中定义的端口号连接TCP Server,连接成功后在界面上显示已连接状态;
第二步,根据用户在上位机软件界面上的操作,通过TCP连接向下位机发送开始测试等控制命令,下位机收到命令后发送应答,开始数据采集并将数据更新到共享网络变量中;上位机从共享网络变量中读取数据,完成解析并在软件界面中进行显示;
第三步,用户在上位机软件界面中点击停止测试按钮,软件通过TCP连接向下位机发送停止测试命令,下位机收到命令后发送应答,停止数据采集和共享变量的更新;
第四步,当用户点击退出按钮时,软件通过TCP连接向下位机发送关闭软件命令,下位机关闭网络共享变量和TCP连接,释放资源并退出。
3 功能验证
为了验证软件设计的可行性和NI PSP协议的传输效率,在测试系统中进行了上下位机的软件部署和软件功能的验证。
下位机没有图形化的软件界面,下位机软件运行后创建以时间命名的本地数据记录文件,将将采集到的数据保存在本地文件中。
上位机软件界面如图8所示,Tab页面分别对应两个RTU,这两个RTU通过各自的共享网络变量与上位机进行数据传输。用户点击“开始”按钮后,上位机软件向两个RTU的下位机软件发送开始测试命令,下位机软件将采集到的现场数据通过各自的共享网络变量发送给上位机;上位机分别从这两个共享变量读取数据,并对读取的数据进行解析,根据解析结果对RTU的每一个通道的状态进行显示,同时按照与下位机相同的格式将接收到的数据保存在数据记录文件中。
图8 上位机软件界面
测试过程结束后,通过对比上、下位机中的保存的数据记录文件,验证了在测试过程中软件通过共享网络变量进行数据传输没有错误发生,验证了数据传输的可靠性。
4 结束语
本文介绍了以共享网络变量技术为基础,具有多节点大数据量传输能力的分布式测试软件的设计方法。与传统采用Socket API函数进行数据传输的设计方法相比,使用共享网络变量的编程更为简单,降低了软件开发的难度,可以使开发人员专注于测试功能的实现,提高软件开发的效率。
采用该设计方法开发的分布式测试软件已在某型号电磁阀测试系统中得到了应用,实际验证了共享网络变量的传输效率和可靠性,具有一定的推广价值。