LUCI 使用其原有機制的創建新的頁面

1.LUCI簡介

LUCI是一個小巧的語言,誕生於2008年3月份,目的是爲OpenWrt固件從 Whiterussian 到 Kamikaze實現快速配置接口。輕量級 LUA語言的官方版本只包括一個精簡的核心和最基本的庫。這使得LUA體積小、啓動速度快,從而適合嵌入在別的程序裏。UCI是OpenWrt中爲實現全部系統配置的一個統一接口,英文名Unified Configuration Interface,即統一配置接口。LuCI,便是這兩個項目的合體,能夠實現路由的網頁配置界面。[·引自百度百科https://baike.baidu.com/item/...]html

2. 我作過什麼

其實我接觸LUCI並不久,主要用它來爲OpenWrt寫UCI接口,來存取配置文件裏的內容。存取有兩種方式:git

  • 使用LUCI原有機制實現存取
  • 自定義界面進行存取

這兩種我都會介紹。本文主要介紹一些LUCI的基本內容和一種方式的應用。web

3. LUCI的基本架構

LUCI能夠歸屬爲web開發行列。由於它的內容都是直接在瀏覽器裏體現出來的。它的基本架構跟不少WEB開發語言的框架同樣,都是MVC架構。如下給出一些簡單的解釋:
M(Model): 模型層,路徑是/usr/lib/lua/luci/model/。這個是數據處理的具體代碼的層。該層中有一個cbi文件夾,那裏面是預約義的一些的邏輯文件。
V(View): 視圖層,路徑是/usr/lib/lua/luci/view/。這個很容易理解,就是存放視圖文件的地方。LUCI裏的視圖文件是.htm文件。
C(Controller): 控制層,路徑是/usr/lib/lua/luci/controller/admin/。這個層最主要的功能是設定路由;它還有一個功能跟模型層一致——處理數據。
根目錄: /usr/lib/lua/luci
資源文件存放目錄: /www/luci-static/vim

4. 開始創建新頁面

以配置network文件爲例,實現一個testnet模塊須要完成下面的步驟。
步驟:瀏覽器

  1. 創建一個配置文件
  2. 定義控制層
  3. 定義模型層
1> 創建一個配置文件

以前介紹的時候有說到,LUCI是用於存取配置文件的信息,因此咱們的若要新建一個模塊,須要一個配置文件。配置文件的路徑通常是在/etc/config/。因爲如今咱們是須要配置network文件,而這個是系統必備文件,它已經存在,因此咱們不須要新建,但咱們要了解一下里面的結構是怎麼樣的:架構

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth1'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

這個是配置裏有內容,而其餘配置文件內容格式也是差很少:框架

-- 編輯配置文件
root@openWrt:~# vim /etc/config/<config name>
-- 配置文件格式
config <section type> <section name>
    option <option name> <option value>
    option <option name> <option value>
    option <option name> <option value>

那麼咱們創建一個新的配置給testnet模塊使用函數

config interface testnets
    option ifname 'testnets'
    option type 'test'
    option ipaddr '192.168.1.1'
    option net '192.168.251.1'
2> 定義控制層

控制層中,咱們主要定義訪問的路由。每個模塊的控制都是獨立的,那樣才能方便控制。路由的定義是在控制器的index()函數裏。控制器裏還能夠定義其餘的函數用於處理處理,相信這一點有過WEB開發經驗的童鞋們都知道。
接下來咱們創建一個能以/admin/testnet訪問的路由
話很少說,直接上代碼:oop

-- /controller/admin/testnet.lua
module("luci.controller.admin.testnet")
function index()
    entry({"admin", "testnet", "index"}, cbi("admin_test/net"), translate("Test Net"), 10)
end

function test()
    return 'This is a test function.'
end

module("luci.controller.admin.testnet"): 這一句是命名空間的聲明,luci指的是/usr/lib/lua/luci這個的文件夾,也就是LUCI的根目錄
entry({"admin", "testnet", "index"}, cbi("admin_test/net"), translate("Test Net"), 10): 這一句必須寫在控制器文件的index()函數裏。它的格式定義是這樣子的:post

entry(path, target[[, title][, order]])
  • path: 即路由規則,格式是{"admin","testnet","index"[[,"..."][,"..."]]}基本上能夠無限延伸,但通常不建議這麼幹,到五六層已經很深了,再潛就很差了。
  • target: 即頁面指向,格式是cbi("admin_test/net")。這裏的cbi的函數指的是調用/luci/model/cbi/裏的admin_test/裏的net.lua文件。它還有其餘的使用方法:

    1. cbi("..."):調用/luci/model/cbi/文件夾中的指定lua文件,這裏指向的文件至關於指向一個處理函數。使用的是LUCI自帶邏輯的處理方法,本文就是使用這種方法來生成的頁面。
    2. template("..."):調用/luci/view/文件夾裏指定的.htm視圖文件。這個方法是直接調用視圖。在視圖裏咱們也能夠嵌入代碼讀取配置。
    3. alias("..."): 這個是重定向函數, 通常用於頂級菜單上,使其重定向到指定的子菜單。
    4. call("..."): 這個函數的做用是將該路由指向控制下的某個函數,通常用於處理數據,做用與指向模型層的cbi("...")函數相似,只是一個指向到其餘文件,一個還是存在於控制層文件內。
    5. post("..."): 這個函數在openwrt裏的其餘模塊有使用過,本人研究了一下,其做用於call方法相似,但在使用的時候彷佛沒有成功,如果有成功使用過的猿友,歡迎交流探討。

* title: 即標題展現,這個是設置在菜單裏顯示的內容項。格式有_("Test Net")translate("Test Net"),前一個使用我也沒有成功(有點摸不清楚),後一個是調用translate('...')函數,用於與後期的語言包進行適配。該項能夠用nil代替,表示爲不在菜單欄顯示。

  • order: 這個是排序,爲子菜單進行排序,序號以1開始,最大不限。該項也能夠忽略,表示爲不在菜單欄顯示。

* 若想讓某項隱藏,能夠寫成如下格式:

entry({"admin", "testnet", "index"}, cbi("admin_test/net"), nil)
3> 定義模型層

OK,說了那麼多,終於到了咱們最關鍵的模型層。在模型層,LUCI擁有一套自動生成機制,接下來讓咱們一一介紹。先上代碼再解釋——

-- /model/cbi/admin_test/net.lua
m = Map("network", translate("Test Net"))

s = m:section(NamedSection, "testnets", "interface", translate("Net Configuration")
s.addremove = true
s.anonymouse = true

ifname = s:option(Value, "ifname", translate("Ifname: "))
ifname.datatype = 'string'

itype = s:option(Value, "type", translate("Type: "))
itype.datatype = 'string'

ipaddr = s:option(Value, "ipaddr", translate("Ipaddr: "))
ipaddr.datatype = 'ipaddr'

net = s:option(Value, "net", translate("Net:"))
net.datatype = 'ipaddr'

return m
  • m = Map("network", translate("Test Net")):這一句是鏈接配置文件,是以LUCI機制的必不可少的語句。第一個參數是配置文件的名稱,第二個參數頁面的大標題。
  • s = m:section(NamedSection, "testnets", "interface", translate("Net Configuration"):這一句是以section`的name名鏈接到指定的section

    1. 第一個參數是指定存取section的方法,本文用的是以section的name名進行查找的方式NamedSecton。其餘還有幾種方式:

      • TypedName: 根據section的type來進行存取
      • SimpleSection:(這個沒用過,就很少說了)
      • Table:以表格的形式體現section
      • Tab:以標籤的形式體現section
    2. 第二個參數是section的名字
    3. 第三個參數是section的類型
    4. 第四個參數是模塊標題的名稱

其餘類型的代碼示例分別以下:

-- TypedSection
s = m:section(TypedSection, "interface", translate("Net Configuration")

-- SimpleSection
s = m:section(SimpleSection, "interface", translate("Net Configuration")

-- Table
s = m:section(TypedSection, "interface", translate("Net Configuration")--也能夠用NamedSection
s.Table(Table, "Table Title")

-- Tab
s = m:section(TypedSection, "interface", translate("Net Configuration")--也能夠用NamedSection
s.Table(Tab, "Tab Title")
  • s.addremove = false:打開/關閉添加刪除按鈕,這個爲true時,會在頁面上添加一個添加和一個刪除按鈕,這樣就可以在頁面快速進行增減項了。不過有一點要注意的是,那樣的頁面比較醜……
  • s.anonymouse = true:這一句是不顯示section的名字在頁面上。還能夠加上s.template = 'admin_test/net'這樣的語句
  • net = s:option(Value, "net", translate("Net:")):這一句是鏈接具體的option。

    1. 第一個參數是顯示類型。經常使用的顯示類型有:

      • Value(普通文本框)、ListValue(下拉列表)、Flag(複選框)、MultiValue(文本域)、DummyValue(純文本)、TextValue(多行input)、Button(按鈕)、StaticList(靜態列表)、DynamicList(動態列表)
    2. 第二個參數是option的名稱
    3. 第三個參數是顯示項的說明
  • net.datatype = 'ipaddr':這一句是指定option的類型。這裏的是ip地址類型,其餘還有不少類型:

    • neg、list、bool(布爾類型)、uinteger、integer(整型)、ufloat、float(浮點型)、ipaddr(IP地址)、ip4addr(IP4型IP地址)、ip4prefix(IP4前綴)、ip6addr、ip6prefix、port、portrange、macaddr、hostname、host、network、wpakey、wepkey、string、directory、file、device、uciname、range、min、max、rangelength、minlength、maxlength、phonedigit

這時訪問/admin/testnet便可以看到頁面了。

clipboard.png
參考連接:

相關文章
相關標籤/搜索