李丹清,韓利峰,李嘉曾,吳麗梅,張立園,陳永忠
(1.上海交通大學 軟件工程學院,上海 200240;2.中國科學院上海應用物理研究所 系統工程部,上海 201800)
視頻監控系統經歷了由模擬到數字的轉變,目前發展到第三代,通過利用多媒體壓縮算法,網絡通訊以及人工智能,更加趨向于網絡化和智能化[1]。
伴隨著網絡通訊技術的進步,大型SCADA(Supervisory Control And Data Acquisition)系統和視頻監控系統的平臺融合、信號聯動[2-4]逐漸成為可能。
在電力行業和軌道交通行業初步解決了系統間人為切換,但沒有互動的情況[5,6]。解決方案是SCADA系統的操作處理,通過事件的方式觸發執行機構動作,同時通過聯動服務器彈出視頻畫面,觀察事件處理狀況。這種簡單的互動不具有視頻監控系統縱深層次的優化和橫向平臺擴展的設計理念,況且越來越多的需求體現在視頻、環境、生產、運行等全面信息的深度融合。
解決平臺間信息的深度融合需要解決以下問題:統一的平臺下能同時支持SCADA通訊協議和視頻傳輸通訊協議;擁有事件處理機制,能實現兩系統之間的事件傳遞;擁有可靠的數據傳輸通道,解決客戶端信號數據和視頻數據的傳輸;擁有前端的數據渲染能力,能同時渲染實時變量數據和視頻流數據;具有深度融合所需要的數據處理,圖像處理、智能算法能力。
Nodejs平臺具有以上描述的系統集成和深度融合的能力。首先,它是一個讓JavaScript運行在服務端的開發平臺,采用Google-V8引擎作為編譯器,使得JavaScript的執行速度遠超Ruby、Python等腳本語言;另外,Nodejs具有開發實時監控系統的能力,它采用事件驅動、異步編程、非阻塞模式的IO處理工作機制,為其帶來在相對低系統資源耗用下的高性能與出眾的負載能力,非常適合用作依賴各種IO資源的中間層服務,可完美解決數據IO密集型、分布式部署環境下的實時應用系統[7-9]。
其次,Nodejs具有強大軟件包管理工具npm,它的在線代碼庫包含功能齊全的代碼模塊,如項目中使用的Web網站架設模塊Express,WebSocket通訊模塊socket.io,EPICS libCA接口模塊,node-epics、OpenCV算法模塊等都可以通過npm管理器安裝[10,11]。
再者,Nodejs可以通過FFI(Foreign Function Interface)調用本地C/C++鏈接庫,把視頻采集、解碼、算法處理等集成到平臺之下[12,13]。
本系統的開發就是基于Nodejs平臺,把Web網站服務,EPICS監控系統,視頻采集融合在一起。結合中科院TMSR(Thermal Molten Salt Reactor)核能項目,完成一套綜合實驗室安全監控系統的開發。該系統實現了對項目內的放射化學、熔鹽化學、高溫材料、同步輻照、電解制氫、集熱傳熱等實驗室內環境、設備安全、火警、視頻等信息的一站式監控[14]。
如圖1所示,本系統中使用Express框架建立Web網站。Express是由Nodejs提供的一款精簡、靈活的Web開發框架。它提供了路由,模塊支持,模板引擎,以及中間件等相關功能[15]。
系統服務器通過兩種方式與客戶端進行通信:一種是HTTP協議。客戶端發送Get請求或者Post請求,HTTP服務器在接受到請求時,通過路由機制以及中間件處理,來傳送頁面靜態數據;另一種是WebSocket協議。這種協議通過一次握手,建立瀏覽器和服務器之間一條可復用的通道,可以讓服務器主動并且不斷推送信息,來傳送實時性動態數據[16,17]。

圖1 實驗室監控系統軟件架構Fig.1 Laboratory monitoring system software architecture
系統通過socket.io建立客戶端與服務端的TCP連接對象,通過IP地址和端口號,規定目標服務器。服務器在接受到來自客戶端的請求之后就會建立相應的長連接來發送實時數據。
系統服務器端與第三方實時系統通信來獲取實時的數據,其中包括火災警報系統,EPICS實時信號監控系統和視頻監控系統。與火災警報系統的通信依賴于Modbus接口,與EPICS實時信號監控系統的通信依賴于libCA接口,而與視頻監控系統的通信依賴于視頻軟件供應商提供的SDK[18]。
node-ffi是一個Nodejs的第三方功能模塊,本質上是一個已經將Google-V8封裝好的專門用來調用動態庫/靜態庫的功能插件。本系統所使用的node-modbus和node-epics模塊的內部機制就是利用node-ffi對相應接口的封裝,使其能在Nodejs環境下運行。但是本系統的視頻軟件的SDK并沒有可以在Nodejs環境下運行的API,所以必須手動利用node-ffi對相應的SDK進行封裝并加以利用。
系統在客戶端通過JQuery、Angular、Echart、DataTable等基于JavaScript的框架進行數據可視化,通過Canvas來進行視頻圖像的顯示。

圖2 實時預覽流程圖Fig.2 Real-time preview flowchart

圖3 實時視頻監測實現流程圖Fig.3 Real-time video monitoring implementation flowchart
本系統的視頻軟件SDK提供了視頻圖像采集和視頻播放控制的軟件開發包。它們提供了可以供C/C++、C#和Java調用的API,但并沒有提供JavaScript調用的API。因此,需要通過node-ffi封裝相應的API以供JavaScript調用。封裝好的API就可以在Nodejs平臺上直接調用并且進行功能模塊的開發。
2.1.1 程序實現流程
SDK提供了設備網絡SDK和播放庫SDK。設備網絡SDK主要提供了實時碼流預覽、錄像文件下載、云臺控制、日志管理、格式化硬盤、參數配置等相關功能的開發模塊。播放庫SDK主要用于播放控制的相關功能的開發。
如圖2所示,本系統主要起到實時監測的功能,故調用SDK中的實時預覽功能開發流程。根據實時預覽流程完成程序實現流程,如圖3所示。
首先,需要通過NET_DVR_Init函數完成對設備的初始化,包括網絡初始化和內存預分配等。之后設置設備連接時間(NET_DVR_SetConnectTime)和設置設備重連次數與時間(DVR_SetReconnect)。
運行注冊函數(NET_DVR_Login_V30)需要傳入設備IP、端口號、用戶名、密碼等參數以供完成相應的設備注冊,從而獲取相應設備的使用權限。
NET_DVR_SetExceptionCallBack_V30函數用來捕捉異常信號。此函數基于事件驅動,如果產生異常信號則觸發其回調函數fExceptionCallBack來進一步處理異常信息。
NET_DVR_RealPlay_V40接口函數用于啟動預覽,此函數通過傳入注冊設備時返回的句柄來獲取需要播放的視頻數據的內存空間,也是基于事件驅動,每當產生視頻流數據時,觸發其內部回調函數fRealDataCallBack。
為了便于視頻圖像的顯示與傳送,要求所有的視頻幀圖像數據以JPEG格式進行編碼,同時JPEG格式數據必須存于內存中,SDK提供了相應的內存抓圖接口函數PlayM4_GetJPEG。
為了調用此接口函數,需調用播放庫接口函數PlayM4_SetDecCallBack,此函數將圖像幀數據轉交給內部回調函數DecCBFUN來處理,在DecCBFUN內部調用PlayM4_GetJPEG將視頻圖像數據編碼成JPEG格式。
2.1.2 數據類型封裝
Nodejs是基于JavaScript運行的平臺。JavaScript的變量基于弱類型,變量在聲明時并不需要說明其類型。它的變量類型只有在初始化時,才得以確定。同理,它的函數的返回類型以及參數類型在函數聲明時不需要確定,只有調用函數,傳入實參時,類型才能夠確定。而C/C++的變量是基于強類型,也就是變量在聲明時就必須指明具體的類型。對于函數聲明也是如此,函數的返回類型以及參數類型在函數聲明時也必須確定。因此,通過JavaScript調用基于C/C++編寫的接口函數時,首先需要解決的是變量類型的封裝與預聲明的問題。
為了完成變量類型的封裝,首先必須引入3個第三方功能模塊,分別是ref、ref-array與ref-struct。
安裝完畢后,3個模塊的文件包置入Express框架的modules文件夾下,通過require函數引入即可使用。其中,ref模塊用于變量基本類型與指針類型的封裝,ref-array模塊用于數組類型的數據封裝與預聲明,而ref-struct模塊則用于結構體的類型封裝與預聲明。
動態庫調用:
通過ref、ref-array與ref-struct模塊完成數據類型的封裝與預聲明后,就可以調用node-ffi模塊封裝相應的動態庫的接口函數。
通用格式如下:
var NewFun=new ffi.Library(“動態庫路徑”,{
‘調用函數名1’:[‘函數返回類型1’,[‘形參類型1’,‘形參類型2’,‘形參類型3’…]})
封裝動態庫接口函數需要輸入以下參數:
1)動態庫路徑:SDK動態庫所在路徑。
2)調用函數名:為SDK動態庫對應API的函數名。
3)函數返回類型:通過數據封裝后,預聲明的數據類型,用于定義函數返回類型。
4)形參類型:通過數據封裝后,預聲明的數據類型,用于定義形參類型。
封裝后的動態庫利用之前聲明的JavaScript實例(NewFun)進行調用。
通過這種通用格式,封裝實時預覽開發模塊中需要的API,通過這些API完成實時預覽的功能開發,將功能模塊封裝成JavaScript庫,對外生成可以直接調用的API(getVideo),通過向此函數中傳入設備IP、端口號、用戶名以及密碼,直接通過它的回調函數輸出JPEG格式的視頻圖像數據并加以處理。
如圖4所示,系統使用基于Nodejs的第三方功能模塊socket.io建立TCP/WebSocket連接。連接需要從客戶端和服務器兩方面進行建立,在兩者之間建立一個可以雙向傳送數據的通道,該通道在一次連接之后便可以復用,完成數據實時推送,事件的監聽或者事件的發射。

圖4 WebSocket連接建立流程Fig.4 WebSocket Connection establishment process
在服務器方面,先實例化socket.io,生成對象io。利用io提供的API(io.listen)監聽HTTP服務器,等待客戶端的連接信號。在連接完成之后,根據客戶端的Get請求,調用JavaScript庫的API(getVideo),完成相應設備的視頻圖像數據的獲取并編碼(成為JPEG格式的圖像)。然后通過io對象的API(emit)發射圖像數據,將圖像數據發送到客戶端。最后在接收客戶端發來的停止信號后,調用io的監聽函數進行事件獲取和視頻推送停止處理。
在客戶端方面,通過在腳本中引入socket.io.js來初始化WebSocket協議,之后創建Connect類用于連接服務器,并且在實例化Connect對象時通過傳入IP和端口號的方式確定需要連接的目標服務器,在Connect類內部創建監聽函數用于監聽來自于服務器的連接成功事件和視頻圖像數據傳送成功事件,在播放確認(submit)后,發送基于HTTP的Get請求至服務器,HTTP服務器在接收到Get請求后,調用相應的庫函數,并利用WebSocket協議發送視頻圖像數據到客戶端,客戶端接收到視頻圖像數據后,調用Socket.on(‘Canvas’,fun(data))所定義的事件回調函數,對收到的視頻圖像數據進行處理和顯示。如希望停止播放,發送停止信號至服務器,對應的調用Socket.on(‘disconnect’,fun())來做停止播放后的后續處理。

圖5 信號聯動交互圖Fig.5 Signal linkage interaction diagram
Canvas是HTML5的新引進的一個標簽,主要是提供了畫布的功能,開發者可以使用Canvas以及其提供的API,在畫布上繪制想要繪制的圖像,也可以將BMP圖像以及JPEG圖像,直接在Canvas畫布上直接顯示。當然Canvas本身沒有畫圖的屬性,它是通過獲取繪制上下文(Rendering Context),并利用這種繪制上下文來進行繪圖或圖像顯示。Canvas的繪制上下文,現今有兩種:Canvas2D所提供的API和WebGL所提供的API,前者往往用于繪制2D圖像和2D圖片顯示,后者主要應用于繪制3D圖形[19]。考慮到實時視頻監控系統本身特點,這里選用Canvas2D來顯示圖像。
在服務器接收到來自攝像頭的視頻圖像數據后,為了方便Nodejs進行調用和處理,系統利用Nodejs所提供緩沖區技術(buffer)來接收并封裝視頻圖像數據。通過buffer提供的編碼功能將視頻圖像數據轉化成base64格式的字符串,以方便客戶端顯示和數據推送。
在客戶端接收到base64格式的JPEG圖像數據后,利用Canvas提供的API進行圖像實時顯示。
基本實現流程如下:
1)通過標簽的ID獲取canvas對象
var canvas=document.getElementById(‘videostream’)
2)獲取Canvas2D的繪制上下文
var context=canvas.getContext(‘2d’)
3)創建圖像對象來接收來自服務端的視頻數據
var imageObj=new Image()
4)通過圖像源的方式,將base64編碼的JPEG格式的圖像數據嵌入到圖像對象中
imageObj.src=“data:image/jpeg;base64,”+data
5)將圖像數據通過Canvas2D的繪制上下文進行顯示
context.drawImage(imageobj,0,0,context.width,context.height)

圖6 TMSR視頻監測系統頁面圖Fig.6 TMSR Video monitoring system page diagram
如圖5所示,本系統基于Nodejs集成火災警報系統,EPICS信號監控系統以及視頻監控系統,在客戶端登陸后,系統需獲取火災警報信號,EPICS實時數據以及實時視頻圖像數據。通過HTML5,CSS等渲染工具,以網頁的形式將數據顯示以供給用戶查看。在火災警報系統或EPICS實時系統發出異常信號時,系統通過Nodejs服務器將信號加工之后發送給客戶端,客戶端瀏覽器彈出新的瀏覽界面,之后新的瀏覽界面發送Get信號給Nodejs服務器,在服務器獲取到發送出異常信號的實驗室視頻數據后,通過WebSocket協議將實時視頻圖像數據發送給客戶端。客戶端新界面接收到圖像數據后,通過Canvas顯示實時視頻,如圖6所示。
本文著重闡述Nodejs平臺下兩系統融合的方法,網絡攝像頭通訊接口的封裝,基于WebSokcet技術的實時視頻數據傳輸,以及基于Canvas前端視頻流的顯示等。在TMSR研究堆的實驗室安全監控系統中的應用,為核能項目的實驗開展提供了安全保障。