劉鐵華 尹俊勛
【摘要】RFID中間件是RFID系統(tǒng)的神經(jīng)中樞。在深入研究EPCglobal后,文章借鑒EPCglobal的中間件標(biāo)準(zhǔn)ALE,提出了一種嵌入式RFID中間件設(shè)計(jì)的具體思路,以及較為詳細(xì)的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)和程序流程。該中間件結(jié)構(gòu)緊湊,可以直接運(yùn)行在讀寫器上,既可以為運(yùn)行在讀寫器上的應(yīng)用程序服務(wù),也可以通過網(wǎng)絡(luò)為運(yùn)行在PC上的應(yīng)用程序服務(wù)。
【關(guān)鍵詞】RFID 中間件 EPC ALE 嵌入式
1 前言
傳統(tǒng)RFID中間件運(yùn)行在PC服務(wù)器上,同時(shí)管理多臺(tái)讀寫器。讀寫器讀到的標(biāo)簽,要先通過網(wǎng)絡(luò)返回給運(yùn)行中間件的服務(wù)器,中間件對(duì)返回的標(biāo)簽數(shù)據(jù)進(jìn)行整理,把結(jié)果返回給客戶端,客戶端根據(jù)結(jié)果做進(jìn)一步的處理。隨著RFID應(yīng)用領(lǐng)域的擴(kuò)展,這種體系結(jié)構(gòu)已經(jīng)不能滿足一些應(yīng)用的需要,這些應(yīng)用要求對(duì)讀寫器的結(jié)果進(jìn)行快速、實(shí)時(shí)的處理,例如基于RFID的自動(dòng)化管理、控制系統(tǒng)。同時(shí),手持式讀寫器的應(yīng)用越來越廣泛,卻無法使用運(yùn)行在PC機(jī)上的中間件。對(duì)此,本文設(shè)計(jì)了一種嵌入式RFID中間件,該中間件遵循EPCglobal的中間件標(biāo)準(zhǔn)ALE,直接運(yùn)行在讀寫器上。
2 EPCglobal ALE標(biāo)準(zhǔn)
EPC(Electronic Product Code,產(chǎn)品電子代碼)是美國(guó)麻省理工學(xué)院的自動(dòng)識(shí)別中心(Auto-ID中心)提出的,其主要思想是為每一個(gè)參加互聯(lián)網(wǎng)的產(chǎn)品分配一個(gè)電子標(biāo)簽,該標(biāo)簽存儲(chǔ)了一個(gè)唯一的EPC碼。當(dāng)產(chǎn)品通過閱讀器時(shí),利用RFID技術(shù)來讀取數(shù)據(jù),得到對(duì)應(yīng)的EPC碼,再通過與互聯(lián)網(wǎng)相連的服務(wù)器完成相應(yīng)的EPC碼的解析。EPC系統(tǒng)主要由EPC編碼、EPC標(biāo)簽、EPC讀寫器、EPC中間件、PML(物理標(biāo)記語言)服務(wù)器和ONS(對(duì)象名解析服務(wù))服務(wù)器組成。系統(tǒng)協(xié)議主要由RFID通信協(xié)議、應(yīng)用事件管理(ALE,Application Level Event)協(xié)議等組成。
圖1 ALE在EPCglobal體系結(jié)構(gòu)中的位置
ALE是EPCglobal的中間件標(biāo)準(zhǔn),是閱讀器模塊和客戶應(yīng)用程序之間的接口協(xié)議。該協(xié)議定義了客戶可以如何過濾和整合來自讀寫器的EPC標(biāo)簽,并面向不同的企業(yè)應(yīng)用程序和閱讀器定義了統(tǒng)一的接口。這樣即使后端應(yīng)用程序增加或由其他軟件取代,或者RFID讀寫器的種類有所改變,其它部件都不需要做修改。ALE的處理過程是:接收來自一個(gè)或多個(gè)數(shù)據(jù)源的EPC標(biāo)簽碼;根據(jù)企業(yè)應(yīng)用程序要求以一定的時(shí)間間隔整合數(shù)據(jù),過濾重復(fù)和不感興趣的EPC碼;根據(jù)企業(yè)應(yīng)用程序要求以不同的形式打包發(fā)送報(bào)告。
3 嵌入式中間件的設(shè)計(jì)
本文所述系統(tǒng)硬件平臺(tái):ARM9內(nèi)核、32Mbyte內(nèi)存、16Mbyte Flash和10M網(wǎng)口。軟件系統(tǒng)平臺(tái):嵌入式Linux系統(tǒng)。
3.1 嵌入式中間件的工作原理
依照ALE,發(fā)送到中間件的事件請(qǐng)求都表示為Event Circle Specification(ECSpec),它包含請(qǐng)求的工作方式和報(bào)表的產(chǎn)生方式,能夠同時(shí)處理多個(gè)事件請(qǐng)求。從中間件返回的數(shù)據(jù)都表示為ECReports(Event Circle Reports)。ECSpec和ECReports是兩個(gè)標(biāo)準(zhǔn)XML片斷實(shí)例,以一種結(jié)構(gòu)化和統(tǒng)一的方式在EPC信息的讀取、存儲(chǔ)和傳輸過程中對(duì)其進(jìn)行描述,使得對(duì)標(biāo)簽信息的理解、存儲(chǔ)和傳送更容易。
中間件支持兩種異步模式:訂閱方式(subscribe)和輪詢方式(poll)。異步模式中客戶端可以訂閱一個(gè)事件,當(dāng)事件發(fā)生時(shí),ALE會(huì)異步地將數(shù)據(jù)交付給客戶端。中間件同時(shí)提供了一個(gè)同步模式,即立即返回模式(immediate)。
ECSpec有四種狀態(tài):Undefined(未定義),Unrequested(未請(qǐng)求),Requested(請(qǐng)求),Active(活動(dòng))。
ECSpec的狀態(tài)轉(zhuǎn) 移圖
當(dāng)ECSpec請(qǐng)求到達(dá)中間件時(shí),ECSpec進(jìn)入“Unrequested”狀態(tài);ECSpec進(jìn)入“Requested”狀態(tài)后,會(huì)等待中間件的處理;當(dāng)ECSpec進(jìn)入“Active”狀態(tài),中間件根據(jù)ECSpec中指定的開始觸發(fā)條件,在條件滿足的情況下收集來自讀寫器的原始EPC數(shù)據(jù),當(dāng)ECSpec中指定的停止觸發(fā)條件滿足時(shí)返回查詢報(bào)告ECReports。
3.2 中間件的系統(tǒng)結(jié)構(gòu)
圖3 中間件的系統(tǒng)結(jié)構(gòu)
整個(gè)嵌入式中間件作為一個(gè)獨(dú)立的進(jìn)程運(yùn)行,以消息隊(duì)列作為與其它進(jìn)程通信的接口。中間件的消息接收隊(duì)列與消息發(fā)送隊(duì)列,是兩個(gè)不同的消息隊(duì)列??紤]到中間件進(jìn)程可能同時(shí)為多個(gè)應(yīng)用進(jìn)程提供服務(wù),中間件使用固定的消息接收隊(duì)列,所有應(yīng)用進(jìn)程共享該消息隊(duì)列向中間件進(jìn)程發(fā)消息。中間件通過某種機(jī)制與每個(gè)應(yīng)用進(jìn)程協(xié)商,從而獲得一個(gè)只被中間件進(jìn)程與該應(yīng)用進(jìn)程使用的消息隊(duì)列,中間件通過該消息隊(duì)列向該應(yīng)用進(jìn)程發(fā)消息。換言之,中間件的消息接收隊(duì)列是固定的、唯一的,而中間件的消息發(fā)送隊(duì)列有多條,每條對(duì)應(yīng)一個(gè)應(yīng)用進(jìn)程。這種機(jī)制,將使中間件能并行地為上層應(yīng)用提供服務(wù),大大提高中間件的效能。
中間件包含五個(gè)模塊:消息接收模塊,XML數(shù)據(jù)解析模塊,命令處理模塊,XML數(shù)據(jù)構(gòu)造模塊,消息發(fā)送模塊。
其中,XML數(shù)據(jù)解析模塊基于Linux上開源的XML解析器Expat。Expat是一款基于事件、非驗(yàn)證的XML解析器,快速且輕巧,適合用在系統(tǒng)資源相對(duì)較小的嵌入式系統(tǒng)。Expat被編譯成動(dòng)態(tài)的鏈接庫(kù),要實(shí)現(xiàn)本文所需的功能,只要用到它的五個(gè)函數(shù):XML_ParserCreate(),XML_SetElementHandler(),XML_SetCharacterDataHandler(),XML_ParserFree(),XML_Parser()。
4 嵌入式RFID中間件的軟件實(shí)現(xiàn)
4.1 消息隊(duì)列設(shè)計(jì)
消息隊(duì)列是中間件與讀寫器上應(yīng)用進(jìn)程的通信接口。消息隊(duì)列設(shè)計(jì)的關(guān)鍵是消息結(jié)構(gòu)和應(yīng)用進(jìn)程與中間件進(jìn)層的協(xié)商機(jī)制,后者用來建立中間件到對(duì)應(yīng)應(yīng)用進(jìn)程的消息發(fā)送隊(duì)列(對(duì)于應(yīng)用進(jìn)程自身來說,為消息接收隊(duì)列)。
(1)消息結(jié)構(gòu)
typedef struct msg_text{
long intmsg_type;
unsigned intale_cmd;
charxml_text[MAX_SIZE];
} msg_text;
該結(jié)構(gòu)體中包括三個(gè)變量:msg_type標(biāo)識(shí)消息的類型,接收端可以根據(jù)該變量接收或忽略該消息;ale_cmd標(biāo)識(shí)具體的指令類型,命令處理模塊根據(jù)該變量調(diào)用相應(yīng)的處理函數(shù);xml_text數(shù)組保存消息的數(shù)據(jù)。
在消息隊(duì)列的發(fā)送端調(diào)用Linux的庫(kù)函數(shù)msgget()獲得消息隊(duì)列,調(diào)用msgsnd()發(fā)送消息;在接收端調(diào)用msgget()函數(shù)獲得消息隊(duì)列,調(diào)用msgrcv()函數(shù)提取消息[1]。
(2)中間件與應(yīng)用進(jìn)程的協(xié)商機(jī)制
應(yīng)用進(jìn)程通過getpid()函數(shù)獲得自身的進(jìn)程標(biāo)識(shí)號(hào),生成一個(gè)消息,把消息的ale_cmd置為0,把進(jìn)程標(biāo)識(shí)號(hào)寫入xml_text數(shù)組,通過中間件的消息接收隊(duì)列往中間件發(fā)消息。中間件收到ale_cmd為0的消息,知道有一個(gè)應(yīng)用進(jìn)程請(qǐng)求建立消息隊(duì)列。應(yīng)用進(jìn)層與中間件同時(shí)以該進(jìn)程標(biāo)識(shí)號(hào)作為鍵值,調(diào)用msgget()函數(shù),獲得消息隊(duì)列標(biāo)識(shí)號(hào)。
這種機(jī)制利用了系統(tǒng)中進(jìn)程號(hào)的唯一性,以進(jìn)程號(hào)作為鍵值建立消息隊(duì)列。
4.2 XML數(shù)據(jù)解析
XML數(shù)據(jù)的解析基于開源的XML解析器Expat,被編譯成共享庫(kù),這里需要調(diào)用其函數(shù)。
圖4 XML數(shù)據(jù)解析流程
圖4為基于Expat的XML格式數(shù)據(jù)解析流程圖。p為XML_ParserCreate()函數(shù)的返回值。start、end和cdata的函數(shù)定義由Expat規(guī)定,函數(shù)體由用戶自己實(shí)現(xiàn)以實(shí)現(xiàn)其應(yīng)用。當(dāng)解析器遇到XML元素的開始標(biāo)記就會(huì)執(zhí)行start函數(shù),遇到XML元素的結(jié)束標(biāo)記就會(huì)執(zhí)行end函數(shù)。具體的函數(shù)定義及細(xì)則可以參考Expat的官方文檔。
4.3 命令處理模塊
(1)命令處理模塊的數(shù)據(jù)結(jié)構(gòu)
命令處理模塊是嵌入式中間件的核心,是中間件接口API的內(nèi)部實(shí)現(xiàn)。嵌入式中間件可為網(wǎng)絡(luò)用戶服務(wù),也可為讀寫器上的嵌入式應(yīng)用程序服務(wù)。網(wǎng)絡(luò)用戶用其URL或IP地址標(biāo)識(shí),本地用戶即嵌入式應(yīng)用程序用其消息接收隊(duì)列標(biāo)識(shí)號(hào)標(biāo)識(shí)。URL/IP地址、隊(duì)列標(biāo)識(shí)號(hào)統(tǒng)一為URI。
在調(diào)用這個(gè)模塊之前,先在內(nèi)存中創(chuàng)建一個(gè)全局的指針變量,指向ECSpec_t鏈表。鏈表的節(jié)點(diǎn)包括ECSpec數(shù)據(jù)本身和相應(yīng)狀態(tài)信息及控制數(shù)據(jù)。ECSpec_t鏈表保存了中間件中所有已注冊(cè)的ECSpec的所有信息,命令處理函數(shù)的實(shí)現(xiàn)主要基于對(duì)該鏈表的操作。鏈表節(jié)點(diǎn)的結(jié)構(gòu)定義如下:
typedef struct ECSpec_t_node
{
ECSpec*p_ECSpec;//指向ECSpec結(jié)構(gòu)體的指針
Subscriber *firstSub;//訂閱者鏈表的頭指針
Poll*firstPoll;//查閱者鏈表的頭指針
int ECSpecState;//ECSpec的狀態(tài)
pthread_tthreadid;//工作線程標(biāo)識(shí)符
pthread_mutex_tecspec_state;//互斥量,用于線程同步
pthread_cont_tecspec_con;//條件變量,用于線程同步
ECSpec_t_node*nextECSpec_t;//下一個(gè)ECSpec_t_node的指針
}ECSpec_t_node;
依照ALE,節(jié)點(diǎn)中的ECSpec[2]是ALE事件周期的描述,它包含了事件周期的工作方式和事件周期后報(bào)表的產(chǎn)生方式。
訂閱者鏈表結(jié)構(gòu)如圖5:
圖5訂閱者鏈表
一個(gè)subscriber代表一個(gè)訂閱者,字符串指針uri指向訂閱者的地址(URL/IP地址或消息隊(duì)列標(biāo)識(shí)符),next指針指向下一個(gè)訂閱者,ECSpec的報(bào)表發(fā)送給每一個(gè)訂閱者。最后一個(gè)訂閱者的next指針指向空。
查閱者鏈表的結(jié)構(gòu)與訂閱者鏈表相似。
(2)命令處理模塊的函數(shù)定義
依照ALE,本命令處理模塊實(shí)現(xiàn)了九個(gè)函數(shù)。這些函數(shù)的類型定義及程序流程如下:
a)ale_define(specName:string,spec:ECSpec):void
往全局鏈表中增加一個(gè)該ECSpec_t的節(jié)點(diǎn),表示向中間件“注冊(cè)”了一個(gè)ECSpec;該ECSpec增加一個(gè)工作線程,即每個(gè)ECSpec對(duì)應(yīng)一個(gè)工作線程。工作線程按照ECSpec的要求開始事件周期,獲取讀寫器返回的原始標(biāo)簽數(shù)據(jù),產(chǎn)生報(bào)表。
b)ale_undefine(specName:string):void
根據(jù)提供的參數(shù)specName,向中間件注銷一個(gè)ECSpec,即從ECSpec_t鏈表中刪除該節(jié)點(diǎn),并終止該ECSpec對(duì)應(yīng)的工作線程。
c)ale_getECSpec(specName:string):ECSpec
根據(jù)提供的參數(shù)specName,在ECSpec_t鏈表中查找該ECSpec對(duì)應(yīng)的節(jié)點(diǎn)。若該節(jié)點(diǎn)存在,返回該ECSpec。
d)ale_getECSpecNames():List(String)
遍歷ECSpec_t鏈表,返回中間件中注冊(cè)的所有ECSpec的名字。
e)ale_subscribe(specName:string,notificationURI:string):void
為指定的ECSpec增加一個(gè)訂閱者,即在訂閱者鏈表中插入一個(gè)新的訂閱者,并根據(jù)圖2修改ECSpec的狀態(tài)。
f)ale_unsubscribe(specName:string,notificationURI:string):void
為指定的ECSpec取消一個(gè)訂閱者,即在訂閱者鏈表中刪除指定的訂閱者,并根據(jù)圖2修改ECSpec的狀態(tài)。
g)ale_getSubscribers(specName:String):void
返回參數(shù)指定的ECSpec的所有訂閱者的URI。
h)ale_immediate(spec:ECSpec):ECReports
注冊(cè)并訂閱ECSpec,在第一個(gè)事件周期結(jié)束并返回報(bào)表后取消訂閱,注消ECSpec。
i)ale_poll(specName:string,notificationURI:string):ECReports
為指定的ECSpec增加一個(gè)查閱者,即在查閱者鏈表中插入一個(gè)新的查閱者,并改變ECSpec的狀態(tài)。在第一個(gè)事件周期結(jié)束并返回報(bào)表后取消查閱,即在查閱者鏈表中刪除該查閱者。
參考文獻(xiàn)
[1]Neil Matthew, Richard Stones,著. 陳健,宋健健,譯.Linux程序設(shè)計(jì)(第3版)[M]. 北京:人民郵電出版社,2007.
[2]EPCglobal Inc. The Application Level Events (ALE) Specification Version1.0[S]. http://www.epcglobalinc.org/standards/ale/ale_1_0-standard-20050915.pdf.
[3]Finkenzeller K,著. 陳大才,譯. 射頻識(shí)別(RFID)技術(shù)(第2版)[M]. 北京: 電子工業(yè)出版社,2001.
[4]孟和,趙政,薛桂香,等. EPCglobal應(yīng)用層事件引擎設(shè)計(jì)與實(shí)現(xiàn)[J]. 計(jì)算機(jī)工程,2008(6): 12.★
【作者簡(jiǎn)介】
劉鐵華:華南理工大學(xué)電子與信息學(xué)院碩士研究生,主要研究領(lǐng)域?yàn)镽FID中間件。
尹俊勛:華南理工大學(xué)電子與信息學(xué)院博士生導(dǎo)師,主要研究領(lǐng)域?yàn)橥ㄐ排c音視頻處理。