摘 要: 目前商用WiFi路由器已應(yīng)用到多個領(lǐng)域,商家通過給用戶提供一個穩(wěn)定免費WiFi熱點達到吸引客戶、提升服務(wù)的目標(biāo)。傳統(tǒng)路由器自帶的Luci界面提供了工廠模式的Web界面,用戶可通過該界面配置路由器。Luci采用MVC模式(Model-View-Controller)構(gòu)造網(wǎng)頁,能實現(xiàn)動態(tài)的程序設(shè)計,便于修改和擴展。本文主要針對OpenWrt系統(tǒng)的路由器,介紹如何使用Lua和JavaScript腳本語言添加用戶模式Web界面。此外,還介紹了工廠模式和用戶模式之間的切換、添加Web頁面的方法,給出了一些應(yīng)用實例。
關(guān)鍵詞: OpenWrt系統(tǒng);Lua;Web界面;模式切換;MVC
0 引言
基于OpenWrt系統(tǒng)的家用路由器作為免費WiFi以及廣告投放的解決方案,具有成本低、部署靈活的優(yōu)點,被廣告商家以及大型連鎖門店以集中投放、集中管理的方式運用[1]。采用該方式需要解決以下問題:精簡配置管理界面,便于大規(guī)模投放部署;屏蔽認證頁、廣告頁投放等設(shè)置,避免路由器的經(jīng)營價值受損。因此需要在路由器管理界面中設(shè)定工廠模式以及用戶模式,以便于設(shè)備的管理、調(diào)試、部署[2]。
本文首先介紹了OpenWrt系統(tǒng)網(wǎng)頁的工作原理,然后具體介紹了如何添加用戶模式以及用戶模式和工廠模式的切換原理,接下來分析了基于Luci編寫網(wǎng)頁的具體過程。文章的最后對下一步的改進工作提出展望。
1 Luci搭建網(wǎng)頁
要理解Luci是如何搭建網(wǎng)頁的,首先就要了解Luci、Uhttpd、CGI、MVC幾個概念。
Luci是OpenWrt上的Web管理界面,它提供給用戶UCI、API接口組件,用于用戶在Web界面上對路由器進行管理與設(shè)置。Luci由Lua編寫完成,Lua是一種擴展語言,幾乎在所有操作系統(tǒng)和平臺上都可以編譯、運行。實際上,Lua程序的工作流程是嵌入到其他的程序中運行的[3]。
Uhttpd是OpenWrt系統(tǒng)路由下的一個精簡的Web服務(wù)器,它具有非常低的內(nèi)存開銷,CPU占用率低,效能好,通常用于輕量級的嵌入式設(shè)備[4]。Uhttpd是Luci默認的Web服務(wù)器,通過Web界面修改相關(guān)參數(shù)配置路由器。
CGI(Common Gateway Interface)是通用網(wǎng)關(guān)接口,它是外部應(yīng)用程序與Web服務(wù)器之間的接口標(biāo)準(zhǔn)[5]。CGI規(guī)定了CGI程序和Web服務(wù)器之間傳遞信息的規(guī)則和流程[5]。通常Web服務(wù)器Uhttpd的功能并沒有強大到直接運行php、asp這樣的網(wǎng)頁文件,因此與第三方約定,把請求參數(shù)發(fā)送至第三方,然后接收第三方處理結(jié)果給客戶端。Lua語言編寫的Luci就是這個第三方。
用戶端與Web服務(wù)器Uhttpd使用CGI方式交互。Uhttpd服務(wù)器在工作過程中分叉出一個子進程,用于處理用戶的具體需求,然后傳遞給Luci,并在網(wǎng)頁中將子進程的結(jié)果進行顯示。
Luci、Uhttpd、CGI與網(wǎng)頁之間的關(guān)系如圖1所示。
Luci采用MVC(Model-View-Controller)模式搭建網(wǎng)頁。MVC模式把軟件系統(tǒng)分為三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。
(1)控制器(Controller):負責(zé)轉(zhuǎn)發(fā)和處理請求。
?。?)視圖(View):設(shè)計的網(wǎng)頁界面。
(3)模型(Model):數(shù)據(jù)模型,是客觀事物的抽象。
使用MVC模式的目的是實現(xiàn)一種動態(tài)的程序設(shè)計,使后續(xù)對程序的修改和擴展簡化,并且使程序某一部分的重復(fù)利用成為可能[6]。
Controller、View、Model三者之間的關(guān)系如圖2所示[7]。
2 用戶模式切換
2.1 MVC框架設(shè)計
Luci是一個單用戶框架,在/usr/lib/lua/luci/下有三個目錄,分別是model、view、controller,它們對應(yīng)M、V、C[6]。公用的模塊放置在/usr/lib/lua/luci/controller/下面,各個用戶的模塊放置在該路徑下面對應(yīng)的文件夾中。如路由器自帶的工廠模式就位于該目錄下的admin文件夾下。新增用戶模式需新添加文件夾mini,然后在該路徑下添加功能程序。這樣既有效地管理了不同管理員的權(quán)限,又有利于系統(tǒng)的拓展和維護。Controller、Model、View生成網(wǎng)頁的關(guān)系如圖3所示。
在controller目錄下,每個Lua程序都以index()作為起始函數(shù)。在index()函數(shù)中,通過調(diào)用entry()函數(shù)創(chuàng)建子節(jié)點,并把它放在全局節(jié)點樹的相應(yīng)位置。entry()函數(shù)的參數(shù)規(guī)定了該節(jié)點的位置屬性。
2.2 利用控制器生成Target
Controller目錄下的子節(jié)點以Target的方式生成網(wǎng)頁。Target是由每個子節(jié)點的entry()函數(shù)創(chuàng)建的,這是dispatch()流程最后要執(zhí)行的方法。Target主要有alise、firstchild、call、cbi、form和template 6種生成方式??傮w上可以分成兩類,前兩種主要用于鏈接其他節(jié)點,后四種則是實現(xiàn)函數(shù)方法或頁面跳轉(zhuǎn)[7]。
鏈接節(jié)點:alias是網(wǎng)頁節(jié)點之間的鏈接。比如,當(dāng)用戶登錄路由成功后,進入的網(wǎng)頁節(jié)點未定義內(nèi)容,可以用alias的方法,自動鏈接到有內(nèi)容的Web節(jié)點。
實現(xiàn)函數(shù)方法或頁面跳轉(zhuǎn):這種方法一般用于一個路徑的葉節(jié)點leaf,執(zhí)行相應(yīng)的操作,并且動態(tài)生成頁面html文件,傳遞給用戶。在call、cbi、form、template四種方法中,call調(diào)用了自定義的功能函數(shù),直接調(diào)用以實現(xiàn)特定的目標(biāo),如發(fā)送數(shù)據(jù)、讀取文件等。調(diào)用cbi函數(shù)能夠使用CBI模塊簡潔高效地生成網(wǎng)頁。函數(shù)template是直接鏈接到目錄view下面的htm頁面,實現(xiàn)網(wǎng)頁跳轉(zhuǎn)。
如果要添加用戶模式(Mini),就必須在Controller目錄下添加文件夾mini。這樣Luci就能夠直接從Controller目錄下讀取子節(jié)點的數(shù)目及名稱,以便生成對應(yīng)的節(jié)點樹。在用戶模式的mini目錄下至少添加兩個文件。第一個是index.lua文件,index.lua程序是為了實現(xiàn)用戶名、密碼的認證和網(wǎng)頁節(jié)點的配置。第二個是要具體實現(xiàn)的功能網(wǎng)頁,該網(wǎng)頁定義了生成的Target。以顯示路由系統(tǒng)狀態(tài)為例,需要添加index.lua和system_state.lua文件。
添加的用戶模式(Mini)文件結(jié)構(gòu)如圖4所示。
要說明的是,此處system_state.lua規(guī)定是用template的方式生成Target,直接跳轉(zhuǎn)到view/mini文件夾下的system_state.htm文件。
實際上,用戶模式和工廠模式都是使用Luci搭建網(wǎng)頁,二者之間的原理完全相同。不同的是,在用戶模式下,給用戶顯示的是更加貼近實際使用需求的頁面。此外,使用用戶模式,關(guān)閉工廠模式的部分功能,還能使路由器更加高效地運轉(zhuǎn)。
在成功添加了用戶模式后,就要考慮登錄認證的問題。只有輸入正確的用戶名和密碼之后,才能成功登錄用戶模式。用戶模式下的所有子節(jié)點是由上而下逐層索引的,因此只要有一個節(jié)點需要認證,在該節(jié)點下的所有子節(jié)點也需要認證。只要mini節(jié)點有sysauth值,它以下的所有子節(jié)點都需要認證才能查看、操作。
此外,OpenWrt的精簡內(nèi)核是單用戶機制,路由器自動以root用戶登錄。也就是說,工廠模式和用戶模式使用的是同一個用戶名和密碼。通過認證后,服務(wù)器端會發(fā)給用戶端一個session值,該值以cookie的形式存在于請求報文中,供服務(wù)器識別用戶。
2.3 Footer頁腳標(biāo)簽
用戶成功登錄路由后,要求能夠在工廠模式與用戶模式之間自由切換。這個任務(wù)就由Footer頁腳標(biāo)簽來完成。Footer的工作原理是由Luci的主題決定的,主題包含兩個內(nèi)容,分別是header.htm和footer.htm。header.htm能顯示每個頁面的菜單欄,footer.htm則會讀取Controller目錄下的節(jié)點,最終顯示在頁腳中,以鏈接的方式切換用戶。
Footer頁腳標(biāo)簽的工作原理如圖5所示。
在成功添加頁腳之后,整個添加用戶模式和模式切換的工作就完成了。結(jié)果如圖6所示,其中footer.htm顯示在右下方,user model就是添加的用戶模式。
3 網(wǎng)頁設(shè)計
前面提到,為了在用戶模式下生成滿足特定功能的網(wǎng)頁,需要在controller/mini目錄下添加index.lua和system_state.lua兩個文件。在system_state.lua中,規(guī)定網(wǎng)頁是以template的方式鏈接到view/mini文件下的system_state.htm文件。這樣只要設(shè)計system_state.htm的內(nèi)容,就可以實現(xiàn)對應(yīng)的功能。
system_state.htm是將Lua和JavaScript兩種語言配合使用來完成相應(yīng)的功能。如果編寫的功能模塊不需要訪問路由器的數(shù)據(jù),則利用Lua和JavaScript可以比較輕松地實現(xiàn)[4]。特別地,還可以調(diào)用一些輔助性Shell script。在網(wǎng)頁中,利用Lua語言的luci.sys.exec()函數(shù),就可以調(diào)用shell腳本。
例如,要測試路由器與外網(wǎng)是否連通,可以簡單地通過ping命令,訪問某一主流網(wǎng)站即可。如果ping通,則返回值為1,否則返回0。該功能可以用shell腳本寫,在網(wǎng)頁中使用如下命令:
state=tonumber(luci.sys.exec("/shellfun/pingtest"))
這樣就能執(zhí)行/shellfun文件夾下的pingtest.sh Shell腳本,返回是否連通的狀態(tài),在網(wǎng)頁中顯示相應(yīng)的內(nèi)容。
如果編寫的功能模塊需要訪問路由器的數(shù)據(jù),這就需要一個從Lua腳本到JavaScript腳本數(shù)據(jù)交互的過程。因為JavaScript不太適合直接訪問路由器的數(shù)據(jù),一般都是由Lua腳本程序讀取路由器的數(shù)據(jù)。然后,用JSON(JavaScript Object Notation)這種輕量級的數(shù)據(jù)交換格式發(fā)送給JavaScript腳本,利用JavaScript腳本在網(wǎng)頁上顯示出傳遞的數(shù)據(jù)。
例如,當(dāng)要在網(wǎng)頁中顯示某一端口的實時流量時,需要不斷地訪問路由器的端口流量數(shù)據(jù)??梢栽?luci/controller/mini的system_state.lua中某一節(jié)點規(guī)定,通過Lua的函數(shù)不斷地訪問數(shù)據(jù),然后用JSON數(shù)據(jù)格式輸出數(shù)據(jù)[5]。在JavaScript腳本中,利用XHR.poll()函數(shù)每隔一段時間接收JSON數(shù)據(jù),最后將數(shù)據(jù)以圖表的方式動態(tài)顯示。
最終實現(xiàn)的路由器連通測試和流量監(jiān)控結(jié)果如圖7所示。
4 結(jié)論
本文深入地分析了路由器Web系統(tǒng)Luci搭建網(wǎng)頁的原理和實現(xiàn)細節(jié)。MVC模式是軟件工程實現(xiàn)網(wǎng)站搭建的核心,通過MVC模式,大大簡化了網(wǎng)站的開發(fā)和維護工作。在設(shè)計網(wǎng)頁的過程中,介紹了Lua和JavaScript如何進行數(shù)據(jù)交互,以及如何配合外部的shell腳本實現(xiàn)特定功能。
目前家用路由已經(jīng)支持采用TF卡、U盤等外置存儲硬件,可以采用Luci搭建接口實現(xiàn)路由器本地存儲以及內(nèi)容的投放,使之具有更高的運營價值和潛力。
參考文獻
[1] 海虎,李濤,韓俊剛,等.多態(tài)并行處理器的數(shù)據(jù)通信和路由器的設(shè)計[J].電子技術(shù)應(yīng)用,2014,40(8):38-40,47.
[2] 朱云雷.基于互聯(lián)與認證的無線路由器關(guān)鍵技術(shù)[J].微型機與應(yīng)用,2014,33(24):57-58,65.
[3] 張一弓.基于OpenWrt平臺的進程問通信[J].科技創(chuàng)新與應(yīng)用,2014(21):62.
[4] KIM C G, KIM K J. Implementation of a cost-effective home lighting control system on embedded Linux with OpenWrt[J]. Personal & Ubiquitous Computing, 2014, 18(3):535-542.
[5] PALAZZI C E, BRUNATI M, ROCCETTI M. An OpenWrt solution for future wireless homes[C]. 2010 IEEE International Conference on Multimedia and Expo, IEEE Computer Society, 2010:1701-1706.
[6] 吵吵博客.LuCI界面開發(fā)之CBI模塊[EB/OL].(2011-09-04)[2015-06-30]http://www.chaochaoblog.com/archives/698.
[7] 吵吵博客.LuCI實現(xiàn)啟動應(yīng)用程序等腳本命令2011[EB/OL].(2011-09-03)[2015-06-30]http://www.chaochaoblog.com/archives/691.