2013年8月31日 星期六

寫個 LuCI 介面設定 Serial Port 的 baud rate

OpenWrt 很多設定檔都是透過 UCI 介面 (Unified Configuration Interface) 來進行大部份的系統設定,包括 network, wireless, dhcp, firewall, dropbear (SSH Server) 以及跟網頁開發有關的 uhttpd 和 luci 都是。

UCI 的檔案格式是一致的。以 /etc/config/system 為例,它的內容如下:

在 LuCI 的 Web 管理介面上,有一頁是系統設定的操作介面,這個介面正是用來管理 /etc/config/system 設定檔:

image

LuCI 便是透過 UCI 程式介面來讀寫 /etc/config/system 設定檔。

我們也可以用 LuCI 來讀寫與管理自己的 UCI 設定檔。

Serial Port 的 baud rate 設定介面

來做個練習。首先編輯 /etc/config/arduino,輸入以下內容:

接著寫段程式碼 (arduino.lua,請存至 /usr/lib/lua/luci/model/cbi/myapp/arduino.lua):

其中,以 Map 對應 /etc/config/arduino,然後以 NamedSection 對應 /etc/config/arduino 設定檔中的 main 這個 section,然後建立兩個物件分別對應 serialport 與 baud_rate 這兩個 options。Value 屆時會在網頁上產生 TextBox,而 ListValue 則會在網頁上產生 Dropdown List (HTML 的 <select><option>…)

我們還要準備個 Controller 模組 (index.lua, 請存至 /usr/lib/lua/luci/controller/myapp/index.lua):

完成後,瀏覽 /cgi-bin/luci/myapp,便會看到如下畫面:

image

這是 LuCI 自動產生的介面,可以讓使用者管理 /etc/config/arduino 這個設定檔的內容,當你在 UI 上做好設定,點按 [Save & Apply] 後,/etc/config/arduino 的檔案內容就會自動更新。

再進一步

前一個版本只是方便管理 /etc/config/arduino 這個設定檔。現在,讓我們進一步做件事「當使用者改變 baud rate 時,便呼叫 stty 指令改變 serial port 的 baud rate」:

將 arduino.lua 修改成這樣:

現在,當使用者在 Web 管理介面上改變 baud rate 時,就會同時呼叫 stty 去修改 serial port 的 baud rate 囉。你可以利用 stty –F <serial port> 來確認 baud rate 是否有改變:

image

寫個 LuCI 模組

LuCI (Lua Configiration Interface) 是 OpenWRT 的 Web 管理介面。LuCI 是一個 MVC (Model View Controller) framework,所以我們可以在 LuCI 的基礎上寫 Web 的應用程式。

第一個 controller 模組

假設我們想做一件事:「當使用者瀏覽 /cgi-bin/luci/myapp/mymodule/time.htm 時,便在網頁上顯示 OpenWRT 目前的系統時間」。那麼可以寫一段程式碼如下 (mymodule.lua):

其中,以 entry() 定義了一個節點,作用是「當使用者瀏覽 /cgi-bin/luci/myapp/mymodule/time.htm 時,便會呼叫 action_time() 函式」,而 action_time() 函式則會負責產生一個顯示目前系統時間的網頁。

把 mymodule.lua 放到 /usr/lib/lua/luci/controller/myapp/mymodule.lua,然後瀏覽 /cgi-bin/luci/myapp/mymodule/time.htm,就會看到底下的結果:

image

建立 VIEW

跟 PHP, ASP.NET, JSP 一樣,LuCI 也有 template 的功能,可以在 HTML 裏混用 Lua Script 產生動態網頁。底下做個示範。

首先,建立了一個 template 檔如下,並把它存到 /usr/lib/lua/luci/view/myapp_mymodule/time.htm:

接著寫個 controller 模組如下,把它存到 /usr/lib/lua/luci/controller/myapp/mymodule.lua:

其中,程式以 entry() 定義了兩個節點。先說第二個節點,它的作用是「當使用者瀏覽 /cgi-bin/luci/myapp/mymodule/time.htm 時,會 描繪呈現 (render) /usr/lib/lua/luci/view/myapp_mymodule/time.htm 這個 template 的內容 」,而第一個節點只是第二個節點的別名,所以你可以瀏覽 /usr/lib/lua/luci/view/myapp_mymodule/time.htm,也可以簡寫成 /usr/lib/lua/luci/view/myapp_mymodule 這樣就好,兩者結果都是一樣的。當你執行這支程式時,會看到這樣的結果:

image

LuCI 現在預設都是用 bootstrap CSS frontend,time.htm 引入了 header template,因此享受 bootstrap 的好處,變得比較美觀了。

暫除 LuCI 模組暫存檔

在學習寫 LuCI 模組時,有件特別注意的事。由於 LuCI 會把 module 暫存起來,就算你寫的 module 有做過變動,LuCI 也不會跑更新過後的版本。所以當你更新 module 時,記得刪除 LuCI 的模組暫存檔,這樣 LuCI 才會跑新版本的模組。

刪除 LuCI 模組暫存檔的指令為:

  rm /tmp/luci-indexcache /tmp/luci-modulecache/*

參考資料

2013年8月24日 星期六

寫個 uhttpd 的 CGI

uhttpd 是一個小型的 HTTP Server,支援 TLS, CGI, Lua。OpenWRT 的 Web 管理介面 LuCI (Lua Configuration Interface) 一般都是搭配 uhttpd 使用。底下是一張 LuCI 的畫面截圖。新版 LuCI 現在預設都用 twitter bootstrap 當作佈景主題 (Theme),非常美觀,看起來很舒服。

image

uhttpd 的 Docuement Root 預設是在 /www,而 /cgi-bin/luci 則是預設的 CGI Gateway。

我們可不可以自己也寫個 CGI?當然可以,舉個例子,用 Lua 寫段簡單的程式碼如下:

檔名取為 helloCGI,把它存到 /www/cgi-bin/helloCGI,接著把檔案屬性改為可執行:

  chmod +x /www/cgi-bin/helloCGI

然後瀏覽 http://<OpenWrt’ IP Address>/cgi-bin/helloCGI,會得到這樣的結果:

image

這就是一個簡單的 uhttpd 的 CGI 程式了。

uloop: 一個簡單的 Event Loop implementation

我在 OpenWrt 裏找到一個小工具 uloop,一個簡單的 Event Loop Implementation,藏身在 libubox 裏。

uloop() 主要提供兩個功能,一個是簡單的 timer,可以設定在 timeout 後自動執行指定的 function,另一個是類似 exec 指令,可以執行外部程式,後面這個功能好像沒多大用處。uloop() 有 lua binding,所以可以在 lua 程式裏套用。

底下的程式示範 uloop()  timer 的使用方法 (timer_demo.lua):

執行結果如下:

image

其中,t1 只跑一次,t2 每兩秒跑一次,而 t3 則不會跑,因為它被取消了。

2013年8月20日 星期二

scp for Windows

在 Linux 上,要在兩台電腦之間傳輸檔案,最簡單的方法是用 scp (Secure Copy) 指令,例如「把 README 傳到 Arduino-Wrt 的 /tmp 資料夾下」:

   coopermaa@ubuntu:~$ scp README root@Arduino-Wrt:/tmp

如果想要複製目錄,那麼只要加個 -r 選項。

Windows 上也有 scp 指令可用。我找到兩個,一個是 msysgit (Git for Windows),msysgit 打包了很多 Linux 的指令,包括了 scp。另一個是 pscp (Putty Secure Copy)。這兩個工具的 scp 指令用法和 Linux 版本幾乎一模一樣。

除了指令列工具,你也可以用 WinSCP。WinSCP 是 GUI 的介面,用滑鼠就可以操作:

1) 安裝好 WinSCP 後,登入你的 Linux (Raspberry Pi or Openwrt or whatever):

image

2) 登入後,會看到 WinSCP 的管理介面,左邊是你的 PC,右邊則是你 Linux 的檔案系統。你只要用滑鼠拖放就可以傳輸檔案。

image