XMLHttP對(duì)象在嵌入式Web實(shí)時(shí)系統(tǒng)中的應(yīng)用
掃描二維碼
隨時(shí)隨地手機(jī)看文章
摘要:就Ajax技術(shù)中的XMLHttp對(duì)象在基于Web的嵌入式遠(yuǎn)程控制與實(shí)時(shí)監(jiān)測(cè)系統(tǒng)中的應(yīng)用開發(fā)進(jìn)行了研究,并基于Microchip TCP/IP協(xié)議棧給出了具體的實(shí)現(xiàn)方法,有效地解決了客戶端Web與嵌入式HTTP服務(wù)器的交互問題。
關(guān)鍵詞:嵌入式系統(tǒng);TCP/IP;Web開發(fā);Ajax;XMLHttp;Javascript
引言
傳統(tǒng)的Web應(yīng)用在交互操作過程中頻繁出現(xiàn)全頁刷新的問題無法避免,即使當(dāng)前頁面中僅有局部信息是需要?jiǎng)討B(tài)刷新顯示的。這不僅影響到界面效果,在實(shí)時(shí)監(jiān)測(cè)過程中還會(huì)明顯影響服務(wù)器的響應(yīng)速度。
Ajax技術(shù)的出現(xiàn)為解決客戶端Web與嵌入式HTTP服務(wù)器之間的交互問題提供了重要途徑。Ajax是異步Javascript與XML的簡稱,這一概念由Jesse James Garrett提出,它是一組與Web開發(fā)相關(guān)的技術(shù),包括基于HTML/XHTML與CSS標(biāo)準(zhǔn)的頁面表示、基于DOM的動(dòng)態(tài)顯示和交互,以及基于XMLHttpRequest與服務(wù)器之間的異步通信。所有上述技術(shù)通過Javascript綁定在一起。
嵌入式以太網(wǎng)實(shí)時(shí)系統(tǒng)開發(fā)者可以嘗試通過Ajax的核心對(duì)象XMLHttp在“后臺(tái)”與嵌入式HTTP服務(wù)器交瓦,對(duì)服務(wù)器發(fā)起遠(yuǎn)程控制,讀取服務(wù)器動(dòng)態(tài)返回的監(jiān)測(cè)信息并刷新顯示在客戶端Web界面中的特定位置,且所有操作均不會(huì)導(dǎo)致當(dāng)前Web界面被全頁刷新。
本文以Microchip公司的TCP/IP協(xié)議棧為基礎(chǔ),討論XMLHttp對(duì)象在嵌入式Web實(shí)時(shí)系統(tǒng)中的具體應(yīng)用方法。所選用的測(cè)試電路以PIC18F4 52單片機(jī)與以太網(wǎng)接口芯片RTL8019AS為核心,嵌入式HTTP服務(wù)器所有Web相關(guān)文件保存在系統(tǒng)外部EEPROM存儲(chǔ)器中。
1 XMLHttp在客戶端Web中的應(yīng)用
XMLHttp是Ajax技術(shù)的核心,由微軟公司在IE5.0瀏覽器中率先推出,后被命名為XMLHttpRequest。
1.1 客戶端Javascript函數(shù)
1.1.1 創(chuàng)建XMLHttp對(duì)象的通用函數(shù)
客戶端與嵌入式系統(tǒng)HTTP服務(wù)器的所有交互都將基于在客戶端所創(chuàng)建的XMLHttp對(duì)象。該函數(shù)在IE中創(chuàng)建XMLHttp對(duì)象的語句為:
創(chuàng)建XMLHttp對(duì)象后最重要的操作是設(shè)置onreaclystatechange屬性(非IE中為onload),為其綁定異步回調(diào)函數(shù)。當(dāng)XMLHttp對(duì)象狀態(tài)變化時(shí),所指定的回調(diào)函數(shù)將自動(dòng)處理服務(wù)器回應(yīng)數(shù)據(jù)。
1.1.2 客戶端發(fā)送控制命令的函數(shù)
(1)Send_Control_CMD(URL,Html_id)
該函數(shù)可由客戶端Web中的控制命令按鈕點(diǎn)擊事件onClick觸發(fā)調(diào)用,它調(diào)用CreateXMLHttpObj創(chuàng)建XMLHttp對(duì)象,設(shè)置回調(diào)函數(shù),然后以GET方法對(duì)HTTP服務(wù)器發(fā)起請(qǐng)求。函數(shù)的第一個(gè)參數(shù)URL可以是控制命令串,也可以是CGI、HTML及其他各種Web文件名。如果要求在客戶端Web中顯示HTTP服務(wù)器返回信息,則需要設(shè)置第二個(gè)參數(shù)Html_id。例如,在發(fā)送控制命令點(diǎn)亮系統(tǒng)中某個(gè)指示燈后,要求將服務(wù)器返回的該指示燈的當(dāng)前狀態(tài)顯示在客戶端。所設(shè)置的參數(shù)Html_id是客戶端Web頁中的某個(gè)容器的ID,返回信息將顯示到該容器中。如果不需要服務(wù)器回應(yīng)文本信息,或?qū)貞?yīng)信息不予處理,可將該參數(shù)設(shè)為空。函數(shù)具體實(shí)現(xiàn)如下:
Send_Control_CMD在每次被涮用時(shí)首先創(chuàng)建一個(gè)通用對(duì)象Obj,然后創(chuàng)建XMLHttp對(duì)象,并將其保存在自定義的Obj.xmlhttpobj屬性中,隨后調(diào)用XMLHttp對(duì)象的open方法與send方法,調(diào)用格式為:
oXMLHttpRequest.open(bstrMethod,bstrUrl,varAsync,
bstrUser,bstrPassword);
oXMLHttpRequest.send(varBody);
其中open方法的bstrMethod參數(shù)為HTTP請(qǐng)求的方法,例如所選擇的“GET”方法,bstrUrl參數(shù)為請(qǐng)求的URL地址,在本文討論的嵌入式Web實(shí)時(shí)系統(tǒng)中,它用來表示控制命令串,譬如用來啟動(dòng)外部直流電機(jī)的控制命令串“0?1=MOTOR”,varAsync參數(shù)用于指定當(dāng)前請(qǐng)求是否為異步方式,默認(rèn)為true,最后兩個(gè)參數(shù)提供帳號(hào)密碼,用于服務(wù)器驗(yàn)證。通過open方法初始化XMLHttp對(duì)象以后,要用send方法發(fā)送請(qǐng)求到HTTP服務(wù)器并等待回應(yīng)。由于XMLHttp對(duì)象被設(shè)為異步模式,send調(diào)用將不會(huì)被阻塞,XMLHttp對(duì)象的回調(diào)函數(shù)mReadyCallBack將在HTTP服務(wù)器回應(yīng)時(shí)異步執(zhí)行。[!--empirenews.page--]
由于Web頁中可能有多個(gè)不同按鈕要發(fā)送不同的控制命令,為簡化程序設(shè)計(jì)且便于管理對(duì)象,可將每一按鈕調(diào)用該函數(shù)創(chuàng)建的xMLHttp對(duì)象統(tǒng)一保存到全局對(duì)象數(shù)組ObjArray中。對(duì)象數(shù)組ObjArray由Web頁中的Javascript腳本定義,即:
<script language=“Javascript”>
var ObjArray=new Array;……
(2)mReadyCallBack()
它是Send_Control_CMD函數(shù)所創(chuàng)建的保存于對(duì)象數(shù)組ObjArray中的每個(gè)XMLHttp對(duì)象的異步回調(diào)函數(shù),通過該函數(shù)可統(tǒng)一異步處理服務(wù)器回應(yīng)數(shù)據(jù)。函數(shù)具體實(shí)現(xiàn)如下:
當(dāng)ObjArray中的任意一個(gè)XMLHttp對(duì)象的就緒狀態(tài)變化時(shí),將觸發(fā)對(duì)mReadyCallBack函數(shù)的異步調(diào)用,該函數(shù)將通過for循環(huán)掃描對(duì)象數(shù)組ObjArray,對(duì)HTTP服務(wù)器當(dāng)前回應(yīng)的對(duì)象進(jìn)行處理。通過XMLHttp對(duì)象的responseText屬性可獲取服務(wù)器回應(yīng)信息,通過Web容器的inner HTML屬性可將回應(yīng)信息顯示到Web頁中。在處理完當(dāng)前XMLHttp對(duì)象以后,mReadyCallBack最終將用delete釋放該對(duì)象所占用的資源。如果調(diào)用Send_control_CMD函數(shù)時(shí)第2個(gè)參數(shù)為空,則表示發(fā)出控制命令后不需要處理服務(wù)器回應(yīng)文本信息,回調(diào)函數(shù)僅僅需要釋放該對(duì)象所占用的資源。
1.1.3 實(shí)現(xiàn)客戶端實(shí)時(shí)監(jiān)測(cè)功能的函數(shù)
(1)RealTime_Monitoring()
該函數(shù)專門用于實(shí)時(shí)監(jiān)測(cè)動(dòng)態(tài)數(shù)據(jù),它由Web頁面加載事件onLoad觸發(fā)調(diào)用,通過所創(chuàng)建的xMLHttp對(duì)象向服務(wù)器請(qǐng)求動(dòng)態(tài)文件Status.cgi,以獲取監(jiān)測(cè)數(shù)據(jù)。
其中xmlhttp定義為全局變量。
(2)aReadyCallBack()
該函數(shù)是實(shí)時(shí)監(jiān)測(cè)系統(tǒng)外設(shè)數(shù)據(jù)函數(shù)RealTime_Monitoring所創(chuàng)建的XMLHttp對(duì)象的專用回調(diào)函數(shù),它在處理HTTP服務(wù)器回應(yīng)時(shí)將返回的動(dòng)態(tài)監(jiān)測(cè)數(shù)據(jù)顯示在ID為“txtStatus”的Web容器中,譬如<span id=“txtStatus”>…</span>,所返回的內(nèi)容將替換其中的“…”。函數(shù)具體實(shí)現(xiàn)如下:
回調(diào)函數(shù)aReadyCallBack與回調(diào)函數(shù)mReadyCallBack的差別在于:它釋放已經(jīng)處理回應(yīng)的XMLHttp對(duì)象(置為null)以后,接著執(zhí)行了一項(xiàng)重要工作,即調(diào)用實(shí)時(shí)監(jiān)測(cè)函數(shù)RealTime_Monitoring()。通過創(chuàng)建新的XMLhttp對(duì)象,將動(dòng)態(tài)請(qǐng)求與顯示刷新“接力”進(jìn)行下去,從而使實(shí)時(shí)監(jiān)測(cè)無限延續(xù)。
顯然,通過XMLHttp對(duì)象所實(shí)現(xiàn)的實(shí)時(shí)監(jiān)測(cè),其效果遠(yuǎn)遠(yuǎn)優(yōu)于傳統(tǒng)的Web請(qǐng)求與響應(yīng)操作模式下所使用的通過在網(wǎng)頁頭部加入<meta http-equiv=“refresh”content=“定時(shí)長度”>,或者使用Javascript的setTimeout函數(shù)設(shè)置超時(shí)值,使客戶端自動(dòng)按固定時(shí)間間隔請(qǐng)求服務(wù)器刷新顯示動(dòng)態(tài)信息的方法。
1.2 客戶端Web與嵌入式HTTP服務(wù)器的交互操作
有了上述以XMLHttp對(duì)象為中心的函數(shù)定義,完成客戶端Web與嵌入式HTTP服務(wù)器之間的交互操作就很容易了,例如:
①通過Web頁按鈕啟動(dòng)電機(jī).可有<input type=“button”onClick=“Send_Ctrl_CMD(’0?1=MOTOR’,’)”value=“運(yùn)行”>。按鈕事件觸發(fā)對(duì)Send_Control_CMD的調(diào)用,它通過XMLHttp對(duì)象在“后臺(tái)”發(fā)送命令串“O?1=MOTOR”,提交給嵌入式系統(tǒng)HTTP服務(wù)器處理,控制電機(jī)啟動(dòng),實(shí)現(xiàn)遠(yuǎn)程控制功能。
②實(shí)時(shí)監(jiān)測(cè)嵌入式系統(tǒng)外設(shè)狀態(tài),可有<body onLoad=“ReaITime Monitoring();”>。Web頁面加載事件onLoad觸發(fā)對(duì)RealTime_Monit oring的函數(shù)調(diào)用,它同樣也通過XMLHttp對(duì)象訪問嵌入式系統(tǒng)HTTP服務(wù)器,不同的是它所請(qǐng)求的是動(dòng)態(tài)文件status.cgi。現(xiàn)假設(shè)所訪問的動(dòng)態(tài)文件主要內(nèi)容如下:
<td width=“150”>%02</td>
<td width=“200”>LED1:%00 LED2:%01</td>
<td width=“168”>%10</td>
嵌入式系統(tǒng)HTTP服務(wù)器程序?qū)腗PFS文件系統(tǒng)讀取該動(dòng)態(tài)文件并將其發(fā)往客戶端。在發(fā)送過程中,HTTP服務(wù)器將對(duì)所遇到的形如“%xx”的變量碼進(jìn)行解析處理。例如“%02”被定義為測(cè)試電路中AN0通道的A/D值,“%00”“%01”被定義為兩個(gè)外接LED的開關(guān)狀態(tài),“%10”被定義為所控制的直流電機(jī)的啟/停狀態(tài)。經(jīng)過HTTP服務(wù)器處理后的變量值將被系統(tǒng)當(dāng)前實(shí)際的外設(shè)狀態(tài)值所替換并返回到客戶端。
由于RealTime_Monitoring函數(shù)與aReadyCallBack函數(shù)配合實(shí)現(xiàn)了XMLHttp對(duì)象的創(chuàng)建、請(qǐng)求、異步響應(yīng)、釋放,再創(chuàng)建、再請(qǐng)求、再異步響應(yīng)、再釋放等,從而借助XMLHttp對(duì)象在“后臺(tái)”實(shí)現(xiàn)了理想的實(shí)時(shí)監(jiān)測(cè)功能。由于監(jiān)測(cè)結(jié)果實(shí)時(shí)刷新顯示在Web中的特定容器位置,不會(huì)導(dǎo)致全頁刷新問題,這也為用戶操作帶來了良好體驗(yàn)。
解決了客戶端通過XMLHttp塒象在“后臺(tái)”與HTTP服務(wù)器進(jìn)行交互、發(fā)送控制命令及異步處理回應(yīng)、實(shí)現(xiàn)實(shí)時(shí)監(jiān)測(cè)功能的問題以后,接著要解決的是HTTP服務(wù)器端如何處理客戶端XMLHttp對(duì)象所發(fā)送的控制命令,以及如何處理并返回客戶端XMLHttp對(duì)象所請(qǐng)求的動(dòng)態(tài)文件。[!--empirenews.page--]
2 HTTP服務(wù)器功能簡介
Microchip TCP/IP協(xié)議棧是一套服務(wù)于標(biāo)準(zhǔn)的、基于TCP/IP的應(yīng)用程序,可應(yīng)用于HTTP服務(wù)器、FTP服務(wù)器等,它遵循了TCP/IP參考模型,協(xié)議棧按照模塊化方式實(shí)現(xiàn)。Microchip整個(gè)TCP/IP協(xié)議棧的代碼全部用C語言編寫,每層的實(shí)現(xiàn)代碼駐留在一個(gè)獨(dú)立的C程序文件中,服務(wù)和應(yīng)用程序編程接口則通過頭文件或C程序文件定義,協(xié)議??墒褂肕CC18或HI—TECH PICC 18編譯,圖1對(duì)比了TCP/IP參考模型與Microchip TCP/IP協(xié)議棧。
為實(shí)現(xiàn)HTTP服務(wù)器功能,協(xié)議棧所提供的相關(guān)文件主要有TCP.c與HTTP.c,它們分別處理客戶端與服務(wù)器端的連接及對(duì)HTTP請(qǐng)求的處理。在啟動(dòng)嵌入式系統(tǒng)HTTP服務(wù)器時(shí),主程序首先調(diào)用兩個(gè)初始化函數(shù):StackInit()與HTTPInit()。前者初始化協(xié)議棧,包括MACInit()、ARPInit()、TCPInit();后者初始化HTTP服務(wù)器,使所有的HTTP連接處于監(jiān)聽狀態(tài),受嵌入式系統(tǒng)資源限制,實(shí)際支持的最大連接數(shù)默認(rèn)為3個(gè)。
HTTP服務(wù)器主程序接下來的主要工作是在while(1)中循環(huán)調(diào)用HTTPServer()函數(shù),處理客戶端對(duì)HTTP服務(wù)器的請(qǐng)求并作出響應(yīng)。HTTPSer ver實(shí)際執(zhí)行的任務(wù)是循環(huán)掃描每個(gè)HTTP連接,并在每個(gè)連接上調(diào)用處理HTTP請(qǐng)求的函數(shù)HTTPProcess()。該函數(shù)對(duì)客戶端發(fā)送的控制命令串的處理及動(dòng)態(tài)文件的請(qǐng)求處理將分別通過回調(diào)函數(shù)HTTPExecCmd和HTTPGetVar完成,這兩個(gè)核心回調(diào)函數(shù)由主程序具體實(shí)現(xiàn)。
3 動(dòng)態(tài)響應(yīng)XMLHttp對(duì)象請(qǐng)求的核心函數(shù)
對(duì)于客戶端Web頁內(nèi)onClick事件與onLoad事件觸發(fā)的以下兩個(gè)調(diào)用示例,它們都基于XMLHttp對(duì)象,前者向嵌入式HTTP服務(wù)器發(fā)送控制命令,后者請(qǐng)求動(dòng)態(tài)文件:
①Send_Ctrl_CMD(’0? 1=MOTOR’,’);
②RealTime_Monitoring();
3.1 HTTPExecCmd函數(shù)
HTTPExecCmd函數(shù)對(duì)客戶端發(fā)送的命令串解碼并執(zhí)行相應(yīng)的操作。函數(shù)聲明為:void HTTPExecCmd(BYTE**argv,BYTE argc)??疾炜蛻舳撕瘮?shù)調(diào)用所發(fā)送的控制命令串:“0?1=MOTOR”。HTTP服務(wù)器函數(shù)HTTPProcess在調(diào)用HTTPExecCMD之前已經(jīng)先通過HTTPParse函數(shù)由該命令串解析出“0”、“1”、“MOTOR”這三項(xiàng)內(nèi)容并賦給函數(shù)參數(shù)argv,所解析出的三項(xiàng)的具體定義由主程序設(shè)置。
3.2 HTTPGetVar函數(shù)
每當(dāng)HTTP服務(wù)器當(dāng)前所處理的CGI動(dòng)態(tài)文件Status.cgi中遇到變量碼“%xx”時(shí)即調(diào)用該函數(shù),處理動(dòng)態(tài)請(qǐng)求。HTTPGetVar函數(shù)聲明為:WORD HTTPGetVar(BYTE var,WORD ref,BYTE*val)。該函數(shù)的val參數(shù)是待解析處理的動(dòng)態(tài)文件內(nèi)的某個(gè)變量的標(biāo)識(shí)符,參數(shù)ref用于跟蹤返回值的狀況,參數(shù)val用于逐個(gè)返回?cái)?shù)據(jù)字節(jié)。
以調(diào)用RealTime_Monitoring函數(shù)為例,它通過XMLHttp對(duì)象請(qǐng)求動(dòng)態(tài)文件Status.cgi,當(dāng)HTTP服務(wù)器接收到該請(qǐng)求時(shí),將從保存于EEPR OM的MPFS文件系統(tǒng)讀取Status.cgi文件,然后由HTTP.c的SendFile函數(shù)向客戶端XMLHttp對(duì)象回傳所請(qǐng)求的動(dòng)態(tài)文件。在回傳過程中,所遇到的動(dòng)態(tài)文件內(nèi)的變量將由主程序所實(shí)現(xiàn)的HTTPGetVar函數(shù)逐一進(jìn)行處理。動(dòng)態(tài)文件中的各種變量同樣將由HTTP服務(wù)器主程序進(jìn)行定義。以Status.cgi文件中表示AN0通道A/D轉(zhuǎn)換值的變量“%02”為例,由于主程序不僅循環(huán)調(diào)用HTTPServer函數(shù)響應(yīng)客戶請(qǐng)求并處理回應(yīng),在循環(huán)中還會(huì)分時(shí)處理外設(shè)操作,包括所需要執(zhí)行的AN0通道的A/D轉(zhuǎn)換操作。通常所有這些相關(guān)操作被集中放在處理I/O的函數(shù)ProccessIO()中實(shí)現(xiàn)。現(xiàn)假定RA0引腳外接可變電阻器RV1,則AN0通道的A/D轉(zhuǎn)換具體實(shí)現(xiàn)如下:
ADCON0=0B10000001;
ADCON1=0B10001110;
ADCON0bits.GO=1;
while(ADCON0bits.GO);
itoa(*((WORD*)(&ADRESL)),ANOString);
每一次的A/D轉(zhuǎn)換值都被刷新保存在ANOString字符串中,以便發(fā)往客戶端顯示。當(dāng)HTTP服務(wù)器的HTTPProcess函數(shù)所調(diào)用的SendFile函數(shù)當(dāng)前遇到了變量“%02”,它會(huì)將其交由HTTPGetVar函數(shù)處理。所輸入的第1個(gè)參數(shù)var為2,它由變量“%02”轉(zhuǎn)換為BYTE類型得到,用于標(biāo)識(shí)當(dāng)前變量要獲取的是AN0通道的A/D轉(zhuǎn)換值。
現(xiàn)假設(shè)AN0String當(dāng)前獲取的A/D值為“709”,HTTPGetVar函數(shù)可通過以下關(guān)鍵語句返回A/D值:
其中ref初始時(shí)默認(rèn)為0。顯然,該函數(shù)將被連續(xù)調(diào)用3次,每次調(diào)用時(shí)ref遞增,直到通過*val返回最后一個(gè)字節(jié)以后,通過返回HTTP_ END_OF_VAR告知SendFile函數(shù)當(dāng)前變量處理結(jié)束。對(duì)于待返回到客戶端的數(shù)據(jù)字節(jié),HTTP將通過調(diào)用TCP層提供的函數(shù)TCPPut及TCPFlush,通過指定的Socket套接字將數(shù)據(jù)字節(jié)發(fā)往客戶端,由客戶端XMLHttp對(duì)象的異步回調(diào)函數(shù)通過responseText屬性讀取并刷新顯示在Web中的特定位置。
結(jié)語
通過仿真及實(shí)物電路測(cè)試表明,使用Ajax的XMLHttp對(duì)象及Microchip TCP/IP協(xié)議棧,可以很好地解決以太網(wǎng)環(huán)境下Web操作界面與嵌入式控制系統(tǒng)的交互問題,實(shí)現(xiàn)對(duì)基于HTTP服務(wù)器模式的嵌入式系統(tǒng)進(jìn)行遠(yuǎn)程控制及實(shí)時(shí)監(jiān)測(cè),且能夠?qū)⑺邢嚓P(guān)操作保持在穩(wěn)定的瀏覽器窗口中執(zhí)行。