本發(fā)明屬于解析內(nèi)網(wǎng)數(shù)據(jù)技術(shù)領(lǐng)域,具體說是一種基于非MMU內(nèi)核的嵌入式系統(tǒng)實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方法及系統(tǒng)。
背景技術(shù):
隨著車聯(lián)網(wǎng)產(chǎn)品的不斷發(fā)展,單單通過OBD來實(shí)現(xiàn)車輛的診斷及數(shù)據(jù)采集已經(jīng)不能滿足市場需要及業(yè)務(wù)的擴(kuò)展,鑒于OBD總線的特性,由于車輛在熄火狀態(tài)下OBD總線處于休眠狀態(tài),以及OBD采集數(shù)據(jù)為周期性查詢,效率偏低的特點(diǎn),對于數(shù)據(jù)采集和車輛控制不得不采用內(nèi)網(wǎng)CAN來實(shí)現(xiàn)。
由于車聯(lián)網(wǎng)產(chǎn)品面向不同車主,不同系列車,如奧迪,奔馳,寶馬,大眾,通用,豐田等,以及相同系列車款式不同,如奧迪2012款,奧迪2013款等,再由于同款車型配置又不同,如奧迪2012款天窗自動版,奧迪2012款手動舒適版等,這些不同的差異會引發(fā)相同數(shù)據(jù),如車速,發(fā)動機(jī)轉(zhuǎn)速等的解析規(guī)則不同,隨著市場不斷擴(kuò)大及新的車型款式不斷的更新,迫切需要一種方法來應(yīng)對不同車型相同數(shù)據(jù)不同解析規(guī)則帶來的開發(fā)壓力。
通過總結(jié)部分車型同一種數(shù)據(jù)的計(jì)算規(guī)則,發(fā)現(xiàn)基本毫無規(guī)律,并且復(fù)雜數(shù)據(jù)的運(yùn)算規(guī)則不能用過一個或幾個算式簡單累積就能得出計(jì)算結(jié)果,有相互依賴的,有分支判斷的,有的需循環(huán)計(jì)算才能得出,采用單純C語言開發(fā),幾乎每個數(shù)據(jù)就得寫一個小規(guī)模的計(jì)算函數(shù)來實(shí)現(xiàn),這樣就帶來了很大的工作量。
技術(shù)實(shí)現(xiàn)要素:
針對現(xiàn)有技術(shù)存在上述缺點(diǎn)和不足,本發(fā)明提供了一種基于非MMU內(nèi)核的嵌入式系統(tǒng)實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方法及系統(tǒng),保證嵌入式系統(tǒng)實(shí)時,高效的處理性能。
為實(shí)現(xiàn)上述目的,本發(fā)明提供了一種實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方法,包括:數(shù)據(jù)解析的步驟,數(shù)據(jù)解析模塊與lua交互的步驟。
具體的,數(shù)據(jù)解析的步驟為:
步驟1:首先數(shù)據(jù)通過CAN收發(fā)器產(chǎn)生中斷,收發(fā)CAN數(shù)據(jù)模塊接受數(shù)據(jù);
步驟2:數(shù)據(jù)打包成消息通過消息隊(duì)列發(fā)送到數(shù)據(jù)解析模塊;
步驟3:數(shù)據(jù)解析模塊剝離數(shù)據(jù),獲取數(shù)據(jù)幀頭和數(shù)據(jù)體;
步驟4:根據(jù)數(shù)據(jù)幀頭判斷數(shù)據(jù)屬于哪類數(shù)據(jù);
步驟5:將數(shù)據(jù)體與關(guān)鍵位進(jìn)行與運(yùn)算,判斷前后數(shù)據(jù)是否有變化,如果沒有變化不進(jìn)行解析;
步驟6:如果有變化,并且是模擬量,判斷是否到采集周期;
步驟7:到了采集周期,將數(shù)據(jù)傳遞給lua解析模塊,調(diào)用與之對應(yīng)lua腳本進(jìn)行解析;
步驟8:將解析出的數(shù)據(jù)存儲到數(shù)據(jù)中心模塊。
具體的,數(shù)據(jù)解析模塊與lua交互的步驟,包括:
S1.創(chuàng)建lua句柄;
S2.將lua腳本傳遞給lua解釋器,檢查合法性,如果合法則進(jìn)行步驟S3;
S3.通知lua解釋器,構(gòu)建全局共享數(shù)據(jù)表結(jié)構(gòu);
S4.CAN收發(fā)器中斷之后,接收CAN數(shù)據(jù)模塊將接收的數(shù)據(jù)傳遞給lua解釋器;
S5.把數(shù)據(jù)對應(yīng)的lua腳本傳遞給lua解釋器;
S6.lua解析器調(diào)用lua腳本解析,并將結(jié)果傳遞給數(shù)據(jù)解析模塊。
具體的,如果步驟S2中l(wèi)ua腳本不合法,則將該lua腳本輸出,并再也不傳輸至lua解釋器中。
具體的,S6中解析車窗狀態(tài)調(diào)用lua腳本解析方法為:
首先編寫一段解析車窗狀態(tài)數(shù)據(jù)的lua腳本;
再者調(diào)用lua提供的函數(shù)luaL_dofile來執(zhí)行上述lua腳本,有兩個過程:一是luaL_loadfile函數(shù)將lua文件加載進(jìn)來然后進(jìn)行詞法語法語義分析,得到一個closure放入棧中,二是接著調(diào)用lua_pcall函數(shù)來執(zhí)行棧頂?shù)腸losure。
更具體的,第一過程具體為:在luaL_loadfile函數(shù)中加載lua文件的是lua_load函數(shù),在lua_load函數(shù)中調(diào)用了luaD_protectedparser函數(shù)來進(jìn)行解析,在luaD_protectedparser函數(shù)中又調(diào)用了f_parser函數(shù),f_parser函數(shù)進(jìn)行選擇,如f_parser函數(shù)跑到luaY_parser函數(shù)中去,在luaY_parser調(diào)用luaX_next進(jìn)行分析,則這個函數(shù)首先讀取腳本的第一個token;
最后在luaX_next函數(shù)中調(diào)用了llex函數(shù),llex函數(shù)是真正切出token(符記)的例程,在讀取了第一個token后luaX_next函數(shù)返回,相關(guān)的詞法信息保存在了lexstate狀態(tài)中,接著luaY_parser函數(shù)調(diào)用chunk函數(shù)來遞歸的生成一個chunk塊,在chunk函數(shù)中循環(huán)讀取下一個token并根據(jù)token的類型一層一層的遞歸的生成chunks,將chunks根據(jù)層次組合成tree,位于root的是最外層chunk;
在分析完lua腳本后會返回到f_parser函數(shù),在f_parser函數(shù)中接著調(diào)用luaF_newLclosure函數(shù)來將分析結(jié)果包裹成一個closure然后push到lua棧中。
更具體的,第二過程具體為:
當(dāng)?shù)谝粋€過程完成后lua棧頂存放著一個closure,luaL_dofile中調(diào)用lua_pcall讓其來調(diào)用這個closure,
在lua_pcall中調(diào)用f_call函數(shù),f_call中又接著調(diào)用了luaD_call函數(shù),傳入了被調(diào)用的closure和參數(shù)個數(shù),最后在luaD_call函數(shù)中調(diào)用了luaV_execute函數(shù)來執(zhí)行closure中的opcode;
更具體的,luaV_execute是lua虛擬機(jī)執(zhí)行opcode的函數(shù),為一個無限循環(huán),利用switch來根據(jù)不同的opcode進(jìn)行不同的過程。
本發(fā)明還提供了一種實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方系統(tǒng),具體包括:
CAN收發(fā)器,使數(shù)據(jù)產(chǎn)生中斷;
接收CAN數(shù)據(jù)模塊,接收產(chǎn)生中斷后的數(shù)據(jù);
數(shù)據(jù)解析模塊,剝離數(shù)據(jù)獲取數(shù)據(jù)幀頭和數(shù)據(jù)體;
數(shù)據(jù)中心模塊,存儲解析出的數(shù)據(jù);
lua解釋器,構(gòu)建全局共享數(shù)據(jù)表結(jié)構(gòu)。
進(jìn)一步的,數(shù)據(jù)解析模塊,包括lua解析模塊,調(diào)用與數(shù)據(jù)對應(yīng)的lua進(jìn)行解析。
本發(fā)明由于采用以上技術(shù)方案,能夠取得如下的技術(shù)效果:在低成品硬件方案下,采用非MMU的系統(tǒng)內(nèi)核,以C語言為主開發(fā)的嵌入式系統(tǒng),依然能靈活處理短小、多變、并帶有一定復(fù)雜性的小任務(wù)并保證嵌入式系統(tǒng)實(shí)時,高效的處理性能;
鑒于解析數(shù)據(jù)需要靈活,高效,又易于擴(kuò)展開發(fā),采用LUA與C語言相互調(diào)用,把LUA靈活易擴(kuò)展和C語言高效有機(jī)結(jié)合在一起,實(shí)現(xiàn)內(nèi)網(wǎng)數(shù)據(jù)有效解析。
附圖說明
本發(fā)明共有附圖2幅:
圖1為數(shù)據(jù)解析流程圖,
圖2為數(shù)據(jù)解析模塊與lua交互流程圖。
具體實(shí)施方式
下面通過實(shí)施例,并結(jié)合附圖,對本發(fā)明的技術(shù)方案作進(jìn)一步的具體說明。
實(shí)施例1
一種實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方法,包括:數(shù)據(jù)解析的步驟,數(shù)據(jù)解析模塊與lua交互的步驟。
數(shù)據(jù)解析的步驟為:
步驟1:首先數(shù)據(jù)通過CAN收發(fā)器產(chǎn)生中斷,收發(fā)CAN數(shù)據(jù)模塊接受數(shù)據(jù);
步驟2:數(shù)據(jù)打包成消息通過消息隊(duì)列發(fā)送到數(shù)據(jù)解析模塊;
步驟3:數(shù)據(jù)解析模塊剝離數(shù)據(jù),獲取數(shù)據(jù)幀頭和數(shù)據(jù)體;如下所示2個標(biāo)準(zhǔn)幀
0x03c2,0x0000000000000004
0x0525,0x0000000000ff0000
0x03c2和0x0525是幀頭,一個是遠(yuǎn)光燈,一個是方向盤狀態(tài);
步驟4:根據(jù)數(shù)據(jù)幀頭判斷數(shù)據(jù)屬于哪類數(shù)據(jù);如車窗控制、車鎖控制、后備箱控制、喇叭控制、轉(zhuǎn)向燈控制;
步驟5:將數(shù)據(jù)體與關(guān)鍵位進(jìn)行與運(yùn)算,判斷前后數(shù)據(jù)是否有變化,如果沒有變化不進(jìn)行解析;
步驟6:如果有變化,并且是模擬量,判斷是否到采集周期;
步驟7:到了采集周期,將數(shù)據(jù)傳遞給lua解析模塊,調(diào)用與之對應(yīng)lua腳本進(jìn)行解析;
步驟8:將解析出的數(shù)據(jù)存儲到數(shù)據(jù)中心模塊。
具體的,數(shù)據(jù)解析模塊與lua交互的步驟,包括:
S1.創(chuàng)建lua句柄;
S2.將lua腳本傳遞給lua解釋器,檢查合法性,如果合法則進(jìn)行步驟S3;
S3.通知lua解釋器,構(gòu)建全局共享數(shù)據(jù)表結(jié)構(gòu);
S4.CAN收發(fā)器中斷之后,接收CAN數(shù)據(jù)模塊將接收的數(shù)據(jù)傳遞給lua解釋器;lua腳本不合法,則將該lua腳本輸出,并再也不傳輸至lua解釋器中。
S5.把數(shù)據(jù)對應(yīng)的lua腳本傳遞給lua解釋器;
S6.lua解析器調(diào)用lua腳本解析,并將結(jié)果傳遞給數(shù)據(jù)解析模塊。
本發(fā)明還提供了一種實(shí)現(xiàn)lua解析內(nèi)網(wǎng)數(shù)據(jù)方系統(tǒng),具體包括:
CAN收發(fā)器,使數(shù)據(jù)產(chǎn)生中斷;
接收CAN數(shù)據(jù)模塊,接收產(chǎn)生中斷后的數(shù)據(jù);
數(shù)據(jù)解析模塊,剝離數(shù)據(jù)獲取數(shù)據(jù)幀頭和數(shù)據(jù)體;
數(shù)據(jù)中心模塊,存儲解析出的數(shù)據(jù);
lua解釋器,構(gòu)建全局共享數(shù)據(jù)表結(jié)構(gòu)。
數(shù)據(jù)解析模塊,包括lua解析模塊,調(diào)用與數(shù)據(jù)對應(yīng)的lua進(jìn)行解析。
實(shí)施例2
作為實(shí)施例1的補(bǔ)充,在數(shù)據(jù)解析模塊與lua交互的步驟中S6解析車窗狀態(tài)調(diào)用lua腳本解析方法為:
首先編寫一段解析車窗狀態(tài)數(shù)據(jù)的lua腳本,例如:
再者調(diào)用lua提供的函數(shù)luaL_dofile來執(zhí)行上述lua腳本,有兩個過程:一是luaL_loadfile函數(shù)將lua文件加載進(jìn)來然后進(jìn)行詞法語法語義分析,得到一個closure(一個函數(shù)加上該函數(shù)所需訪問的所有"非局部的變量")放入棧中,二是接著調(diào)用lua_pcall函數(shù)來執(zhí)行棧頂?shù)腸losure(閉包)。
實(shí)施例3
作為實(shí)施例2的補(bǔ)充,第一過程具體為:在luaL_loadfile函數(shù)中加載lua文件的是lua_load函數(shù),在lua_load函數(shù)中調(diào)用了luaD_protectedparser函數(shù)來進(jìn)行解析,在luaD_protectedparser函數(shù)中又調(diào)用了f_parser函數(shù),f_parser函數(shù)進(jìn)行選擇,如f_parser函數(shù)跑到luaY_parser函數(shù)中去,在luaY_parser調(diào)用luaX_next進(jìn)行分析,則這個函數(shù)首先讀取腳本的第一個token(符記);
最后在luaX_next函數(shù)中調(diào)用了llex函數(shù),llex函數(shù)是真正切出token(符記)的例程,在讀取了第一個token(符記)后luaX_next函數(shù)返回,相關(guān)的詞法信息保存在了lexstate狀態(tài)中,接著luaY_parser函數(shù)調(diào)用chunk函數(shù)來遞歸的生成一個chunk(程序塊)塊,在chunk函數(shù)中循環(huán)讀取下一個token(符記)并根據(jù)token(符記)的類型一層一層的遞歸的生成chunks,將chunks根據(jù)層次組合成tree(樹結(jié)構(gòu)),位于root(根)的是最外層chunk(程序塊)。
在分析完lua腳本后會返回到f_parser函數(shù),在f_parser函數(shù)中接著調(diào)用luaF_newLclosure函數(shù)來將分析結(jié)果包裹成一個closure然后push到lua棧中。
第二過程具體為:
當(dāng)?shù)谝粋€過程完成后lua棧頂存放著一個closure,luaL_dofile中調(diào)用lua_pcall讓其來調(diào)用這個closure,
在lua_pcall中調(diào)用f_call函數(shù),f_call中又接著調(diào)用了luaD_call函數(shù),傳入了被調(diào)用的closure和參數(shù)個數(shù),最后在luaD_call函數(shù)中調(diào)用了luaV_execute函數(shù)來執(zhí)行closure中的opcode(詞法解析后腳本代碼);
更具體的,luaV_execute是lua虛擬機(jī)執(zhí)行opcode的函數(shù),為一個無限循環(huán),利用switch(GET_OPCODE(i))來根據(jù)不同的opcode進(jìn)行不同的過程。
鑒于LUA解釋器垃圾資源自動回收機(jī)制,和內(nèi)網(wǎng)數(shù)據(jù)頻繁更新以及數(shù)據(jù)幀格式固定的特點(diǎn),數(shù)據(jù)分析模塊在跟LUA通信時,采用全局?jǐn)?shù)據(jù)表結(jié)構(gòu),避免反復(fù)調(diào)用LUA解析而產(chǎn)生資源碎片。
以上所述,僅為本發(fā)明較佳的具體實(shí)施方式,但本發(fā)明的保護(hù)范圍并不局限于此,任何熟悉本技術(shù)領(lǐng)域的技術(shù)人員在本發(fā)明披露的技術(shù)范圍內(nèi),根據(jù)本發(fā)明的技術(shù)方案及其發(fā)明構(gòu)思加以等同替換或改變,都應(yīng)涵蓋在本發(fā)明的保護(hù)范圍之內(nèi)。