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