高 濤,常 娟2,高艷軍,段海彬
(1.西安翔迅科技有限責任公司,西安 710068; 2.空軍工程大學 基礎部,西安 710051)
分布式測試系統(tǒng)是計算機網(wǎng)絡技術的產(chǎn)物,是一種通過局域網(wǎng)或Internet,把分布于不同地點、獨立完成特定測試功能的計算機連接起來,達到測試資源共享、分散操作、集中管理、協(xié)同工作等目的網(wǎng)絡測試系統(tǒng)[1]。測試計算機(下位機)一般位于測試現(xiàn)場的被測對象附近,可獨立完成數(shù)據(jù)采集和預處理任務,并通過以太網(wǎng)將數(shù)據(jù)傳輸給控制計算機(上位機)[2]。上位機接收各下位機傳送來的數(shù)據(jù)進行儲存和分析處理,以圖形化的方式顯示數(shù)據(jù),生成測試報表供用戶查看。
按照通常的分布式測試軟件設計方法,需要在下位機軟件中實現(xiàn)數(shù)據(jù)采集和組包操作,然后通過以太網(wǎng)完成數(shù)據(jù)包的發(fā)送;在上位機軟件中通過Winsock API函數(shù)接收數(shù)據(jù)包,并按照約定的數(shù)據(jù)包格式完成數(shù)據(jù)的拆包和提取顯示[3]。進行軟件開發(fā)時,為保證數(shù)據(jù)傳輸?shù)目煽啃?,需要考慮數(shù)據(jù)包校驗、錯誤重發(fā)、FIFO緩存隊列等流程的設計,開發(fā)難度大且容易出錯,對軟件開發(fā)人員有比較高的要求。此外,當系統(tǒng)中有多個下位機同時工作時,大量測試數(shù)據(jù)通過以太網(wǎng)傳輸?shù)缴衔粰C的過程中,如何保證數(shù)據(jù)的一致性將成為一個難點[4]。
為了簡化這種應用的軟件開發(fā),NI公司提供了網(wǎng)絡變量庫(Network Variable Library)。該函數(shù)庫基于NI PSP(NI Publish-Subscribe Protocol)協(xié)議,通過網(wǎng)絡變量對底層網(wǎng)絡通訊協(xié)議(TCP/IP和DDE)進行了抽象[5]。用戶在NI公司的LabVIEW、LabWindows/CVI和NI Measurement Studio開發(fā)環(huán)境中使用網(wǎng)絡變量庫提供的API函數(shù),可以在不影響系統(tǒng)性能的情況下,在多個系統(tǒng)或多個應用程序之間靈活的傳遞數(shù)據(jù)。
某分布式測試系統(tǒng)采用星型網(wǎng)絡結構,多臺遠程數(shù)據(jù)采集終端RTU(Remote Terminal Unit)作為下位機布置在測試現(xiàn)場,每臺RTU有50個采集通道,每一臺RTU均通過以太網(wǎng)與遠離測試現(xiàn)場的測控計算機(上位機)相連。這種星型結構的優(yōu)點是網(wǎng)絡控制容易、便于擴充、可靠性好[6]。
開始測試時,上位機通過以太網(wǎng)發(fā)送命令控制RTU進行數(shù)據(jù)采集,RTU以每個通道10k/s的采樣率進行數(shù)據(jù)采集,并通過以太網(wǎng)將數(shù)據(jù)傳輸?shù)缴衔粰C;上位機接收RTU傳輸?shù)臏y試數(shù)據(jù),對不同RTU的數(shù)據(jù)分別進行解析和顯示,供用戶查看。RTU的AD采樣精度為16Bit,通過計算可以得出每臺RTU在1秒內采集的數(shù)據(jù)量為10 k×50 ch×2 Byte=1 000 kByte。
操作人員在遠離測試現(xiàn)場的地點通過操作測控計算機查看系統(tǒng)中各個RTU采集的測試數(shù)據(jù),支持多個測控計算機共享數(shù)據(jù),分布式系統(tǒng)的組成如圖1所示。
圖1 分布式系統(tǒng)組成框圖
該系統(tǒng)中的RTU和測控計算機均運行Windows操作系統(tǒng),各個RTU運行相同的下位機軟件,通過配置文件給不同的RTU分配不同的IP地址,主要功能模塊包括數(shù)據(jù)采集、組包、共享變量數(shù)據(jù)發(fā)布。測控計算機運行上位機軟件,同樣通過配置文件中的IP地址來控制不同的RTU協(xié)同工作,主要功能模塊包括共享變量數(shù)據(jù)訂閱、數(shù)據(jù)解包、處理、顯示和存儲。上下位機軟件均使用NI LabWindows/CVI環(huán)境進行開發(fā)。
下位機軟件作為測試數(shù)據(jù)的發(fā)布者,上位機軟件作為數(shù)據(jù)的訂閱者。在下位機和上位機之間使用NI PSP協(xié)議進行數(shù)據(jù)傳輸,首先需要創(chuàng)建共享網(wǎng)絡變量并進行配置。
共享網(wǎng)絡變量被部署到一個用于在網(wǎng)絡上托管該變量的共享變量引擎SVE(Shared Variable Engine)。SVE是共享網(wǎng)絡變量的服務器,所有對共享變量的應用(讀或寫)都是客戶端。網(wǎng)絡變量首先向共享變量引擎服務器發(fā)送數(shù)據(jù),然后該服務器將這些數(shù)據(jù)發(fā)布給網(wǎng)絡上的所有節(jié)點。因為數(shù)據(jù)是采用“發(fā)布-訂閱”消息結構來傳輸?shù)?,所以客戶端?jié)點無需編寫復雜的代碼就可以訪問網(wǎng)絡變量數(shù)據(jù)[7]。
圖2 共享變量傳輸過程
共享變量的創(chuàng)建和配置可以采用以下兩種方式:一是使用NI提供的Distributed System Manager軟件,在軟件中以圖形化的方式創(chuàng)建共享網(wǎng)絡變量,另一種是使用Network Variable Library庫函數(shù),通過編程的方式創(chuàng)建共享網(wǎng)絡變量[8]。
a)顯式創(chuàng)建共享網(wǎng)絡變量
圖3 分布式系統(tǒng)管理器軟件界面
安裝完LabWindows/CVI開發(fā)環(huán)境后,系統(tǒng)中安裝了“Distributed System Manager”軟件工具,軟件路徑如下:“開始所有程序National InstrumentsDistributed System Manager”,軟件界面如圖3所示。
使用Distributed System Manager軟件創(chuàng)建共享變量的步驟如下:
1)選中“l(fā)ocalhost”項,通過鼠標右鍵菜單的“添加進程”創(chuàng)建共享變量進程“my_process”;
2)選中剛創(chuàng)建的進程,通過鼠標右鍵菜單“添加變量”創(chuàng)建共享變量“my_variable”,并設置變量類型和網(wǎng)絡,同一個進程下可創(chuàng)建多個變量;
3)選中剛創(chuàng)建的進程,通過鼠標右鍵菜單進行“啟動進程”、“停止進程”和 “刪除進程”等操作。
當網(wǎng)絡變量創(chuàng)建好后,網(wǎng)絡中的其它計算機就可以通過網(wǎng)絡變量路徑來共享數(shù)據(jù)。共享變量的網(wǎng)絡路徑包括計算機名稱、進程名稱以及共享變量名。例如:“192.168.1.100my_processmy_variable”,其中“192.168.1.100”是數(shù)據(jù)發(fā)布計算機的IP地址,“my_process”是網(wǎng)絡變量進程,“my_variable”是網(wǎng)絡變量名[9]。
b)編程創(chuàng)建共享變量
LabWindows/CVI開發(fā)環(huán)境提供了Network Variable Library(網(wǎng)絡變量函數(shù)庫)來方便軟件開發(fā)人員在程序中對共享變量進行操作。Network Variable Library庫函數(shù)結構如圖4所示,主要功能包括共享變量配置、數(shù)據(jù)包處理、變量發(fā)布和訂閱操作等。
圖4 Network Variable Library庫函數(shù)結構
通過編程方式使用共享網(wǎng)絡變量更為靈活,下面結合軟件設計詳細描述網(wǎng)絡變量的編程使用方法。
該分布式系統(tǒng)的下位機負責采集測試現(xiàn)場的數(shù)據(jù),是數(shù)據(jù)的發(fā)布端。下位機軟件的流程設計如圖5所示。
圖5 下位機軟件設計流程圖
第一步,首先創(chuàng)建網(wǎng)絡變量進程,通過調用函數(shù)庫中的CNVNewProcess("my_process")函數(shù)新建名為"my_process"的網(wǎng)絡變量進程,并使用CNVStartProcess("my_process")函數(shù)來啟動該進程。
第二步,創(chuàng)建網(wǎng)絡變量,通過調用網(wǎng)絡變量函數(shù)庫中的CNVNewVariable("my_variable")函數(shù)新建名為"my_variable"的網(wǎng)絡變量,使用CNVSetVariableAttribute()函數(shù)可以對該網(wǎng)絡變量的屬性進行設置,比如將CNVVariableSingleWriterAttribute屬性設置為1,說明該網(wǎng)絡變量只有1個寫入者;CNVVariableServerBufferMaxItemsAttribute屬性可以設置在服務器端能容納數(shù)據(jù)項的數(shù)量。
第三步,使用網(wǎng)絡變量函數(shù)庫中的CNVCreateWriter()函數(shù)在剛才新建的網(wǎng)絡變量地址:“IPmy_processmy_variable”創(chuàng)建數(shù)據(jù)發(fā)布者;當需要更新的數(shù)據(jù)量較大時,可以使用CNVCreateBufferedWriter()函數(shù)來創(chuàng)建發(fā)送緩存區(qū),提高數(shù)據(jù)的發(fā)送效率。創(chuàng)建完成后可以使用CNVGetConnectionAttribute()函數(shù)獲得與共享網(wǎng)絡變量的連接狀態(tài)。
第四步,發(fā)布數(shù)據(jù),通過共享網(wǎng)絡變量傳輸?shù)臄?shù)據(jù)類型可以是單個變量、字符串,也可以是一個數(shù)據(jù)結構。
共享網(wǎng)絡變量的數(shù)據(jù)類型如表1所示,用戶可以根據(jù)需要設置共享變量的數(shù)據(jù)類型。軟件在通過共享網(wǎng)絡變量進行數(shù)據(jù)發(fā)布和讀取時,均是按已設定的數(shù)據(jù)類型進行操作,不用考慮在傳輸中的數(shù)據(jù)轉換問題。
表1 共享網(wǎng)絡變量數(shù)據(jù)類型
當進行單一數(shù)據(jù)類型的數(shù)據(jù)傳輸時,通過使用CNVCreateScalarDataValue()函數(shù)創(chuàng)建不同類型的數(shù)據(jù),再通過CNVWrite()函數(shù)發(fā)布到共享共享網(wǎng)絡變量。
當進行復雜數(shù)據(jù)的傳輸時,需要將發(fā)送的數(shù)據(jù)組包為結構體進行發(fā)送。將數(shù)據(jù)組包為結構體的方法如下:
1)首先根據(jù)需要定義網(wǎng)絡變量數(shù)據(jù),數(shù)據(jù)類型為:CNVData。使用CNVCreateArrayDataValue()函數(shù)創(chuàng)建數(shù)組型的數(shù)據(jù);使用CNVCreateScalarDataValue()函數(shù)創(chuàng)建數(shù)值型的數(shù)據(jù);最后使用CNVCreateStructDataValue()函數(shù)創(chuàng)建包含若干個網(wǎng)絡變量數(shù)據(jù)的結構體,示例代碼如下所示;
CNVData data, fields[3]; //3個變量數(shù)據(jù)
Check(CNVCreateArrayDataValue (&fields[0], CNVInt16, &dataArray, 1, dims)); //數(shù)據(jù)數(shù)組
Check(CNVCreateScalarDataValue (&fields[1], CNVUInt16, 0)); //通道號
Check(CNVCreateScalarDataValue (&fields[2], CNVUInt32, 0)); //包序號
Check(CNVCreateStructDataValue (&data, fields, FIELDSIZE));
2)接下來將數(shù)據(jù)填充到剛才創(chuàng)建的結構體中,示例代碼如下:
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()函數(shù)將組包好的數(shù)據(jù)通過數(shù)據(jù)發(fā)布者發(fā)布到共享網(wǎng)絡變量。
第五步,軟件退出前,使用CNVDispose()函數(shù)釋放創(chuàng)建數(shù)據(jù)發(fā)布者或發(fā)布緩存,最后使用CNVFinish()停止共享變量引擎。
上位機負責讀取共享網(wǎng)絡變量的數(shù)據(jù)并進行處理,是數(shù)據(jù)的訂閱端。上位機軟件的流程設計如圖6所示。
圖6 上位機軟件設計流程圖
第一步,使用CNVCreateSubscriber()函數(shù)在網(wǎng)絡變量地址創(chuàng)建數(shù)據(jù)訂閱者;如果數(shù)據(jù)量較大,則使用CNVCreateBufferedSubscriber()函數(shù)創(chuàng)建數(shù)據(jù)訂閱緩存。通過使用緩沖區(qū),可以解決對于一個變量讀/寫速度的波動問題。當讀出操作偶爾比寫入操作慢的情況可能會導致一些更新數(shù)據(jù)的丟失,如果應用可以容忍數(shù)據(jù)丟失,就不需要使用緩沖區(qū);但是如果讀取操作必須獲得每個更新數(shù)據(jù),就需要使用緩沖區(qū)[10]。
第二步,使用CNVGetConnectionAttribute()函數(shù)獲得與網(wǎng)絡變量的連接狀態(tài),如果連接異常,提示用戶檢查錯誤原因并退出;
第三步,創(chuàng)建數(shù)據(jù)接收線程,不斷的從網(wǎng)絡變量讀取數(shù)據(jù),解析數(shù)據(jù)并進行顯示,同時將數(shù)據(jù)寫入記錄文件中存儲。
從共享網(wǎng)絡變量接收數(shù)據(jù)并提取出有效數(shù)據(jù)的方法與發(fā)布端相反,步驟如下:
1)使用CNVGetDataFromBuffer()函數(shù)檢查網(wǎng)絡變量是否有新數(shù)據(jù)到達;
2)使用CNVGetNumberOfStructFields()函數(shù)獲取接收到的結構體數(shù)量,
3)使用CNVGetStructFields()函數(shù)獲取結構體數(shù)據(jù);
4)使用CNVGetArrayDataValue()函數(shù)獲取結構體中的數(shù)組元素,使用CNVGetScalarDataValue()函數(shù)獲取結構體中的數(shù)據(jù)值;
5)測試完成后使用CNVDisposeData()函數(shù)釋放網(wǎng)絡變量接收緩存;
如果不需要獲得網(wǎng)絡變量的每個更新數(shù)據(jù),僅獲取最新數(shù)據(jù)進行顯示,那么上面的5個步驟可以簡化為以下3個:
1)使用CNVGetConnectionAttribute()函數(shù)通過CNVMostRecentDataAttribute參數(shù)查詢最新的結構體數(shù)據(jù);
2)在定時器函數(shù)中重復調用CNVGetArrayDataValue()函數(shù)獲取共享網(wǎng)絡變量結構體中的數(shù)組元素,使用CNVGetScalarDataValue()函數(shù)獲取數(shù)據(jù)值;
3)測試完成后使用CNVDisposeData()函數(shù)釋放網(wǎng)絡變量接收緩存。
最后,當用戶結束數(shù)據(jù)接收操作時,軟件停止數(shù)據(jù)接收線程,使用CNVDispose()函數(shù)釋放創(chuàng)建數(shù)據(jù)訂閱者或訂閱緩存,最后使用CNVFinish()停止共享變量引擎。
在下位機上完成共享網(wǎng)絡變量數(shù)據(jù)的發(fā)布流程以及在上位機上完成網(wǎng)絡變量數(shù)據(jù)的訂閱流程后,還需要制定上下位機之間的通訊交互協(xié)議,由上位機向下位機發(fā)送控制命令,下位機根據(jù)控制命令開始或停止數(shù)據(jù)采集和發(fā)布。
上下位機軟件之間的交互命令包括開始自檢、停止自檢、開始測試、停止測試和關閉軟件等幾個命令。這些命令采用TCP協(xié)議進行傳輸,這樣做的好處是將交互命令和共享網(wǎng)絡變量的數(shù)據(jù)傳輸相互分離,簡化軟件的開發(fā)和數(shù)據(jù)處理流程。
上下位機軟件之間的命令交互流程如圖7所示。
圖7 上下位機軟件交互流程
第一步,下位機啟動后首先在指定端口創(chuàng)建TCP Server和共享網(wǎng)絡變量,等待上位機進行連接;上位機啟動后根據(jù)配置文件中定義的端口號連接TCP Server,連接成功后在界面上顯示已連接狀態(tài);
第二步,根據(jù)用戶在上位機軟件界面上的操作,通過TCP連接向下位機發(fā)送開始測試等控制命令,下位機收到命令后發(fā)送應答,開始數(shù)據(jù)采集并將數(shù)據(jù)更新到共享網(wǎng)絡變量中;上位機從共享網(wǎng)絡變量中讀取數(shù)據(jù),完成解析并在軟件界面中進行顯示;
第三步,用戶在上位機軟件界面中點擊停止測試按鈕,軟件通過TCP連接向下位機發(fā)送停止測試命令,下位機收到命令后發(fā)送應答,停止數(shù)據(jù)采集和共享變量的更新;
第四步,當用戶點擊退出按鈕時,軟件通過TCP連接向下位機發(fā)送關閉軟件命令,下位機關閉網(wǎng)絡共享變量和TCP連接,釋放資源并退出。
為了驗證軟件設計的可行性和NI PSP協(xié)議的傳輸效率,在測試系統(tǒng)中進行了上下位機的軟件部署和軟件功能的驗證。
下位機沒有圖形化的軟件界面,下位機軟件運行后創(chuàng)建以時間命名的本地數(shù)據(jù)記錄文件,將將采集到的數(shù)據(jù)保存在本地文件中。
上位機軟件界面如圖8所示,Tab頁面分別對應兩個RTU,這兩個RTU通過各自的共享網(wǎng)絡變量與上位機進行數(shù)據(jù)傳輸。用戶點擊“開始”按鈕后,上位機軟件向兩個RTU的下位機軟件發(fā)送開始測試命令,下位機軟件將采集到的現(xiàn)場數(shù)據(jù)通過各自的共享網(wǎng)絡變量發(fā)送給上位機;上位機分別從這兩個共享變量讀取數(shù)據(jù),并對讀取的數(shù)據(jù)進行解析,根據(jù)解析結果對RTU的每一個通道的狀態(tài)進行顯示,同時按照與下位機相同的格式將接收到的數(shù)據(jù)保存在數(shù)據(jù)記錄文件中。
圖8 上位機軟件界面
測試過程結束后,通過對比上、下位機中的保存的數(shù)據(jù)記錄文件,驗證了在測試過程中軟件通過共享網(wǎng)絡變量進行數(shù)據(jù)傳輸沒有錯誤發(fā)生,驗證了數(shù)據(jù)傳輸?shù)目煽啃浴?/p>
本文介紹了以共享網(wǎng)絡變量技術為基礎,具有多節(jié)點大數(shù)據(jù)量傳輸能力的分布式測試軟件的設計方法。與傳統(tǒng)采用Socket API函數(shù)進行數(shù)據(jù)傳輸?shù)脑O計方法相比,使用共享網(wǎng)絡變量的編程更為簡單,降低了軟件開發(fā)的難度,可以使開發(fā)人員專注于測試功能的實現(xiàn),提高軟件開發(fā)的效率。
采用該設計方法開發(fā)的分布式測試軟件已在某型號電磁閥測試系統(tǒng)中得到了應用,實際驗證了共享網(wǎng)絡變量的傳輸效率和可靠性,具有一定的推廣價值。