孫 宏,柯 捷
(桂林航天工業(yè)學(xué)院,廣西 桂林 541004)
智能家居網(wǎng)關(guān)用以實(shí)現(xiàn)家庭網(wǎng)絡(luò)與Internet互聯(lián),還可作為服務(wù)器,為用戶提供家居設(shè)備的遠(yuǎn)程訪問(wèn)服務(wù)。智能家居終端連網(wǎng)方式包括有線(以太網(wǎng))和無(wú)線(WiFi)兩種[1]。用戶也可利用網(wǎng)關(guān)享受文件信息服務(wù)和安防功能。
自從Backf i re版本出現(xiàn)后,OpenWRT的功能趨于穩(wěn)定,且新版本持續(xù)更新,亦可在開發(fā)者論壇獲取豐富的信息。本文旨在應(yīng)用簡(jiǎn)單的方式實(shí)現(xiàn)網(wǎng)關(guān)的功能多樣化。
本設(shè)計(jì)是一個(gè)軟硬件結(jié)合的產(chǎn)品,開發(fā)板通過(guò)移植OpenWRT系統(tǒng)對(duì)其進(jìn)行編譯和配置,之后使用PPPOE方式實(shí)現(xiàn)與Internet交互的功能。用戶可使用手機(jī)或電腦通過(guò)網(wǎng)關(guān)連接到互聯(lián)網(wǎng),獲取信息。還可使用瀏覽器控制家用電器和實(shí)現(xiàn)離線下載,進(jìn)行遠(yuǎn)程監(jiān)控。網(wǎng)關(guān)是整個(gè)智能家居系統(tǒng)的中樞,具有數(shù)據(jù)通信、業(yè)務(wù)處理、信息存儲(chǔ)等功能,可為用戶提供一個(gè)友好的操作界面。系統(tǒng)總體設(shè)計(jì)如圖1所示。
本文使用Linux系統(tǒng)進(jìn)行開發(fā)。硬件使用聯(lián)發(fā)科技的MT7688主板搭配MT7628開發(fā)底板,其中底板集成了GPIO,TTL,RS 232串口,1個(gè)WAN接口及2個(gè)LAN接口,紅外發(fā)射與紅外接收器,4個(gè)USB接口等。
本文移植的系統(tǒng)是OpenWRT。OpenWRT是一個(gè)高度可擴(kuò)展嵌入式設(shè)備的GNU/Linux發(fā)行版本。由于它擁有眾多網(wǎng)絡(luò)組件和良好的擴(kuò)展性,常常被應(yīng)用于工業(yè)控制、機(jī)器人、智能家居等領(lǐng)域。OpenWRT項(xiàng)目的建立從零開始,可被視為一個(gè)全功能的、易于修改的路由操作系統(tǒng)[2]。
OpenWRT的開發(fā)需要宿主機(jī),為便于開發(fā),本設(shè)計(jì)使用Windows系統(tǒng)的主機(jī)作為宿主機(jī),使用帶有圖形界面的串口工具和文件傳輸工具。并安裝一個(gè)Ubuntu系統(tǒng)的虛擬機(jī),與OpenWRT同為L(zhǎng)inux系統(tǒng),便于編譯固件。
首先進(jìn)行編譯環(huán)境的搭建,在宿主機(jī)的Linux環(huán)境下預(yù)裝一些軟件[3]。
(1)源碼下載之后,進(jìn)入源碼的根目錄。運(yùn)行make menuconf i g命令進(jìn)入編譯管理器;
(2)選擇適配的CPU型號(hào)和子型號(hào);
(3)添加Luci支持:Luci作為L(zhǎng)ua和Uci(統(tǒng)一配置接口)的結(jié)合體,用于實(shí)現(xiàn)網(wǎng)關(guān)的網(wǎng)頁(yè)配置界面;
(4)添加Luci中文支持:在之后的Web界面上將英文自動(dòng)替換為已設(shè)置好的中文;
(5)添加完上述幾項(xiàng)基礎(chǔ)固件之后運(yùn)行make V=s命令進(jìn)行固件的編譯,再將生成的固件通過(guò)燒錄器寫進(jìn)開發(fā)板。
經(jīng)過(guò)燒錄之后的開發(fā)板已攜帶了Uhttpd服務(wù)器,以實(shí)現(xiàn)對(duì)Web的支持。B/S工作原理如圖2所示。
圖2 B/S工作原理
用戶通過(guò)Web瀏覽器以get或post方式向Uhttpd服務(wù)器提交請(qǐng)求,并將提交的數(shù)據(jù)發(fā)送給Uhttpd服務(wù)器,服務(wù)器為CGI應(yīng)用程序Fork的一個(gè)子進(jìn)程,并使用Setenv將固定格式的數(shù)據(jù)(如PATH_INFO)保存到環(huán)境變量[4]。另外的非固定格式數(shù)據(jù)由父進(jìn)程通過(guò)w_pipe傳遞給Luci的Stdin。返回?cái)?shù)據(jù)則由Luci輸出到Stdout上[5],父進(jìn)程通過(guò)r_pipe讀取。
Web交互過(guò)程如圖3所示。
圖3 Web交互過(guò)程
(1)開始時(shí),服務(wù)器已將初始頁(yè)面定位到了www/index.html,此頁(yè)面通過(guò)href="cgi-bin/luci"自動(dòng)跳轉(zhuǎn)[6]。
(2)第一次執(zhí)行Luci,會(huì)使用Entry中的Alise方法,定位到Admin(索引到一個(gè)根節(jié)點(diǎn),并執(zhí)行Target方法),返回一個(gè)登錄界面。
(3)此時(shí)服務(wù)器已經(jīng)獲取到了登錄信息,并且使用Session保存了用戶信息。此時(shí)的索引不再是索引根節(jié)點(diǎn),而是索引子節(jié)點(diǎn),返回Admin/Status.html,此時(shí)進(jìn)入網(wǎng)關(guān)的Web主頁(yè)面。
(4)此后的每個(gè)主頁(yè)面的按鈕都會(huì)帶一個(gè)由服務(wù)器生成的Stok值,放在URL中,并且之后的每一個(gè)請(qǐng)求都會(huì)帶有Session,與Stok一起對(duì)用戶進(jìn)行聯(lián)合驗(yàn)證。
MVC,即 Model,View,Controller。Luci從功能的實(shí)現(xiàn)上來(lái)講屬于MVC模式,使用WinSCP工具執(zhí)行 cd /usr/lib/lua/luci/ 可發(fā)現(xiàn)此路徑下有Model,View,Controller三個(gè)目錄。
Controller主要存放Lua文件,用于接收用戶的請(qǐng)求,調(diào)用相關(guān)函數(shù)模型來(lái)響應(yīng)用戶的請(qǐng)求,在此目錄下,每一個(gè)Lua程序都以function index()作為函數(shù)的起點(diǎn),且通過(guò)調(diào)用entry()函數(shù)創(chuàng)建子節(jié)點(diǎn),選擇View文件進(jìn)行顯示。其中entry有多種不同的調(diào)用方式[6]:
call()方法可直接調(diào)用指定的函數(shù),如通過(guò)點(diǎn)擊按鈕實(shí)現(xiàn)某種功能,可直接執(zhí)行簡(jiǎn)短的腳本命令。
template()方法可直接調(diào)用位于View文件夾中的html。
cbi()方法主要用來(lái)配置頁(yè)面,往往用于調(diào)用Model文件夾中的子模塊Lua文件.
alias()方法可實(shí)現(xiàn)網(wǎng)頁(yè)節(jié)點(diǎn)之間的鏈接。如用戶成功登錄路由器后,進(jìn)入的網(wǎng)頁(yè)節(jié)點(diǎn)未定義內(nèi)容,可通過(guò)此方法自動(dòng)鏈接到有內(nèi)容的Web頁(yè)面中[5]。
Model的作用是封裝應(yīng)用程序狀態(tài),響應(yīng)來(lái)自Controller的請(qǐng)求,對(duì)來(lái)自用戶的請(qǐng)求做業(yè)務(wù)邏輯層面的處理,并通知視圖層進(jìn)行更新。
View顯示當(dāng)前的系統(tǒng)狀態(tài),主要由html文件構(gòu)成。
本節(jié)主要以控制照明工具為例,用詳細(xì)的代碼講解如何實(shí)現(xiàn)控制GPIO串口。
MT7628 datasheet文件中定義了GPIO的復(fù)用關(guān)系。并在源碼目錄下的/target/linux/ramips/dts/mt7628an.dtsi中可查看GPIO的分組。
在 /build_dir/target-mipsel_24kec+dsp_uClibc-0.9.33.2/linux-ramips_mt7620n/linux-3.10.28/arch/mips/ralink/mt7620.c中可看到引腳復(fù)用定義。
在/target/linux/ramips/dts/WRTNODE.dts里可注冊(cè)通過(guò)GPIO接口控制的設(shè)備。使用GPIO接口首先要使能GPIO并釋放GPIO引腳復(fù)用功能:
GPIO2:gpio@660 {
//gpio2 和gpio3兩組GPIO引腳是處于使能GPIO的狀態(tài)
status = "okay";
};
GPIO3:GPIO@688 {
status = "okay";
};
結(jié)合mt7628an.dtsi文件將需要釋放的GPIO引腳復(fù)用釋放,如需要釋放GPIO#18和GPIO#19,需將“PWM1”和“PWM0”寫入到ralink,group中。重新編譯將固件刷入開發(fā)板。
pinctrl { //引腳復(fù)用釋放核心代碼
state_default: pinctrl0 {
default {
ralink,group = "ephy","wled","pa","i2c","wdt","uartf","PWM1","PWM0";
ralink,function = "gpio";
};
};
};
通過(guò)SecureCRT連接開發(fā)板,執(zhí)行cd/sys/class/gpio目錄??煽吹絜xport和unexport兩個(gè)文件。
export用于通知系統(tǒng)需要導(dǎo)出控制的GPIO引腳編號(hào),此時(shí)的權(quán)限從用戶態(tài)過(guò)渡到內(nèi)核態(tài)運(yùn)行以下命令:
echo 18 > export
echo 19 > export
再次查看當(dāng)前目錄會(huì)發(fā)現(xiàn)多出GPIO18和GPIO19兩個(gè)目錄。
更改電流輸出方向,將兩個(gè)針腳都設(shè)置為電流輸出:
echo out > GPIO18/direction
echo out > GPIO19/ direction
為電流大小設(shè)置指定值,18號(hào)針腳設(shè)置為高電平,19號(hào)設(shè)置為低電平:
echo out > 1 GPIO18/value
echo out > 0 GPIO19/value
此時(shí)若上述命令都能正常運(yùn)行,使用一個(gè)發(fā)光二極管連接這兩個(gè)針腳,會(huì)有電流通過(guò)該二極管。
在此使用Luci實(shí)現(xiàn),首先打開Lua文件:
vi /usr/lib/lua/luci/controller/admin/
system.lua
在function index()下添加GPIO控制選項(xiàng):
entry({"admin","system","test"},cbi("admin_system/test"),_("GPIO Conf i gration"),3).index = true其中:第一個(gè){ }內(nèi)的內(nèi)容是定義菜單欄的顯示;第二個(gè)參數(shù)是target方式,此處采用cbi方式定位到admin_system/test.lua文件;第三個(gè)參數(shù)是菜單欄顯示名稱。3代表同級(jí)菜單下,此選項(xiàng)的顯示位置,從小到大。
再次進(jìn)入Web頁(yè)面可看到系統(tǒng)菜單欄中有了GPIO Conf i guration選項(xiàng)。
編寫test.lua 實(shí)現(xiàn)按鈕控制腳本。
在/usr/lib/lua/luci/model/cbi/admin_system 路徑下創(chuàng)建一個(gè)test.lua文件。部分業(yè)務(wù)處理代碼如圖4所示。
在etc/conf i g/network文件的最后添加conf i g gpioset,保存后重啟開發(fā)板查看Web。點(diǎn)擊GPIO Conf i guration后會(huì)跳轉(zhuǎn)至新頁(yè)面,通過(guò)點(diǎn)擊網(wǎng)頁(yè)的“開燈”“關(guān)燈”兩個(gè)按鈕,并使用繼電器連接開發(fā)板和電燈的控制電路,可實(shí)現(xiàn)對(duì)220 V家庭電路的控制。
圖4 部分業(yè)務(wù)處理代碼
通過(guò)上述方式,實(shí)現(xiàn)對(duì)更多家用電器的控制。使用同樣的前后端交互模式實(shí)現(xiàn)紅外收發(fā)以控制空調(diào)等電器。安裝各類傳感器,編寫自動(dòng)控制觸發(fā)條件實(shí)現(xiàn)更深層次的智能化。
在網(wǎng)關(guān)上添加文件信息服務(wù)功能,可實(shí)現(xiàn)文件共享。關(guān)鍵之處在于要先建立一個(gè)Samba文件服務(wù)器。它是一個(gè)開源實(shí)現(xiàn)SMB(Server Message Block,SMB)協(xié)議的軟件,客戶機(jī)可通過(guò)SMB協(xié)議訪問(wèn)服務(wù)器上的共享文件系統(tǒng)。將Samba36-Server軟件編譯成ipk包安裝至開發(fā)板后,對(duì)配置文件Smb.conf作出修改才可讓服務(wù)器正常運(yùn)行[7]。配置文件主要包含四個(gè)方面,分別是全局配置段、家目錄段、共享段、自定義段。對(duì)不同的段進(jìn)行修改,可修改和添加用戶、密碼、共享文件夾目錄和訪問(wèn)權(quán)限。
使用Transmission實(shí)現(xiàn)網(wǎng)關(guān)的脫機(jī)下載服務(wù)。此軟件具有多平臺(tái)、低功耗、支持Web界面、遠(yuǎn)程控制等特點(diǎn)[5]。
因網(wǎng)關(guān)內(nèi)存較小,不適合大容量文件的保存。因此需要設(shè)置USB掛載,使大容量U盤能夠掛載到網(wǎng)關(guān)平臺(tái)上,實(shí)現(xiàn)邏輯上的內(nèi)存擴(kuò)展。此過(guò)程需要安裝USB驅(qū)動(dòng)和文件系統(tǒng)格式。
考慮到NTFS格式的文件系統(tǒng)并非Linux的原生態(tài)文件系統(tǒng),因此將掛載的U盤格式化為ext4格式,有助于提高讀寫速度。
Transmission-Daemon是一個(gè)Transmission的后臺(tái)守護(hù)程序,本身不具備操作指令,通過(guò)Web來(lái)進(jìn)行控制,因此需要再添加Transmission-Eeb安裝包。安裝成功之后首先需要運(yùn)行一次以便生成相應(yīng)的配置文件,在/var/lib/transmissiondaemon/info/setting.json 下設(shè)置配置下載名單,Password設(shè)置為明文,啟動(dòng)Daemon后會(huì)自動(dòng)檢查密碼設(shè)置,若密碼配置發(fā)生變動(dòng),Deamon會(huì)自動(dòng)計(jì)算修改后的密碼hash值,并替換配置密碼中的明文密碼,這樣會(huì)使文件下載系統(tǒng)更加安全。此外還可進(jìn)行上傳/下載速度限制,DHT配置,端口設(shè)置等??稍跒g覽器中輸入IP+端口號(hào)登錄Web界面,設(shè)置文件下載路徑和粘貼BT進(jìn)行下載。
MT7628開發(fā)板沒有專門的攝像頭接口,因此采用USB的UVC攝像頭,也稱作免驅(qū)攝像頭,在主流的操作系統(tǒng)中都提供有UVC設(shè)備驅(qū)動(dòng)程序,而OpenWRT又是基于Linux內(nèi)核的系統(tǒng),免去了驅(qū)動(dòng)配置環(huán)節(jié),便于開發(fā)。在Linux下,USB攝像頭通過(guò)UVC驅(qū)動(dòng)捕捉圖像[8]。
需在OpenWRT中添加驅(qū)動(dòng)支持,在編譯模式下,選擇Device Drivers--->Kernel modules--->Video Supinterface--->[*]kmod-video-uvc,編譯之后將ipk寫入開發(fā)板。當(dāng)攝像頭插入時(shí)會(huì)在/dev路徑下生成一個(gè)Video 0文件。
使用V4L2接口獲取并處理攝像頭采集的數(shù)據(jù)幀,V4L2(Video 4 Linux 2)為L(zhǎng)inux訪問(wèn)圖像采集設(shè)備提供了統(tǒng)一的接口,完成對(duì)硬件設(shè)備的驅(qū)動(dòng)和圖像信息的獲取[9]。該接口驅(qū)動(dòng)的攝像頭對(duì)用戶空間調(diào)用I/O通道管理函數(shù)和mmap映射內(nèi)存空間。V4L2和圖像采集設(shè)備以及用戶程序組合構(gòu)成的三級(jí)結(jié)構(gòu)如圖5所示。
圖5 視頻采集結(jié)構(gòu)
攝像頭通過(guò)兩個(gè)內(nèi)存空間緩存圖像隊(duì)列交替覆蓋緩存進(jìn)行采集,過(guò)程與上圖的層次結(jié)構(gòu)相對(duì)應(yīng),如圖6所示。
圖6 圖像緩存過(guò)程
MJPEG-Streamer是一個(gè)開源的視頻服務(wù)器,源碼包括三部分:V4L2接口、Socket編程和多線程編程。
(1)V4L2接口定義了攝像頭采集的圖像信息,首先封裝一個(gè)結(jié)構(gòu)體描述攝像頭的信息,定義圖像的像素大小、圖片格式等。其次I/O通道管理函數(shù)將此結(jié)構(gòu)體寫入驅(qū)動(dòng)中,按照約定初始化攝像頭,并通過(guò)mmap完成內(nèi)存的映射。使用ioct完成圖片的過(guò)濾,將獲取的數(shù)據(jù)寫入文件構(gòu)成圖片,連續(xù)傳輸?shù)膱D片構(gòu)成視頻。
(2)Socket編程中使用的是TCP套接字,當(dāng)有連接請(qǐng)求時(shí),創(chuàng)建一個(gè)線程單獨(dú)和此請(qǐng)求通信。將TCP/IP數(shù)據(jù)報(bào)的繁瑣操作抽象成一個(gè)簡(jiǎn)單接口,提供給用戶層,以實(shí)現(xiàn)在網(wǎng)絡(luò)中通信。
(3)使用多線程的目的是為了同時(shí)響應(yīng)多個(gè)客戶端的請(qǐng)求,每個(gè)請(qǐng)求建立一個(gè)連接,每個(gè)連接就是一個(gè)線程[10]。
MJPEG-Streamer的工作流程如圖7所示。箭頭方向代表圖像數(shù)據(jù)流向。
圖7 MJPEG-Streamer工作流程
同樣需要在Linux下編譯生成新的固件,重啟設(shè)備后通過(guò)瀏覽器查看視頻畫面。
本文基于OpenWRT系統(tǒng)實(shí)現(xiàn)了多功能智能家居網(wǎng)關(guān),描述了前后端交互的工作原理、工作框架、交互流程。以實(shí)例的方式簡(jiǎn)述了設(shè)備控制方法,并對(duì)文件服務(wù)器、視頻服務(wù)器作了簡(jiǎn)明分析,實(shí)現(xiàn)了在網(wǎng)關(guān)平臺(tái)上集成多功能服務(wù),為廣大開發(fā)者和電子愛好者提供了智能家居產(chǎn)品的開發(fā)思路。