如何编写一个路由器的界面1Luci开发入门
Howto:如何寫Module(模塊)-----------------這一部分主要是翻譯github上的document
注意:如果您打算將模塊加入LUCI整合之前,您應該閱讀Module參考。
本教程介紹如何編寫自己的LUCIWebUI中的模塊。在本教程中,我們假設您的luci安裝目錄lucidir(如果您目前使用的是安裝版/usr/lib/LUA/LUCI),并假設你的luci安裝經由/cgi-bin/LUCI訪問您的Web服務器。
方法路線(針對調度過程)
要編寫模塊,您需要了解LUCI調度過程的基礎知識。LUCI使用,將通過執行每個可供使用的controller的索引功能建立一個調度樹。在CGI環境變量PATH_INFO將作為在這個調度樹,例如:/cgi-bin/luci/foo/bar/baz將被解析為foo.bar.baz
要注冊在調度樹中的功能,你可以使用luci.dispatcher的入口函數(Entryfunction)。進入需要4參數(其中的2個是可選的):
entry(path,target,title=nil,order=nil)
path是一個table結構,描述了在調度樹的的位置:例如,{"foo","bar","baz"}的path將被插入到foo.bar.baz.
target描述當用戶請求該節點時將要采取的行動.其中有三個預定義的對象是最重要的(call,template,cbi),他們將在本頁的后邊描述
title定義了在可見的菜單中的選項,也就是最終luci界面中可以看到的標題內容(可選)
order主要依據這個數字來使同一水平上的節點在菜單上的排序(可選)
你可以通過操作節點表的返回值來給entryfunction賦更多的參數。一些典型的參數例子:
i18n定義了當頁面被請求時,自動加載的解釋程序(文件)
dependent防止插件在其父節點的確實,也就是添加插件的依賴
leaf停止解析該節點的請求,并沒有更進一步的調度樹
sysauth要求用戶與給定系統的用戶帳戶進行認證
下邊就是命名與使用過程
既然你已經了解了調度的基礎知識,現在,我們可以開始寫module了。但是在這之前,我們必須先選擇目錄并且命名屬于你自己的新節點。
我們假設你想要創建一個新叫做myapp的應用,而且myapp的module是mymodule。
因此你必須創建一個子文件夾lucidir/controller/myapp,在該文件夾下創建一個mymodule.lua的文件,文件內容如下:
1 module("luci.controller.myapp.mymodule", package.seeall)
2
3 function index()
4
5 end
第一行要求lua正確識別模塊,并建立它的范圍。該indexfunction將用于注冊在調度樹中的動作。
到目前為止,你就已經有了一個新的節點,只不過是該節點中沒有任何的功能。
我們假設你想要復用你的myapp.mymodule模塊,那么你就必須開始最后一個步驟。
Actions
重新打開lucidir/controller/myapp/mymodule.lua并且添加一個函數類似下邊的內容:
1 module("luci.controller.myapp.mymodule", package.seeall)
2
3 function index()
4 entry({"click", "here", "now"}, call("action_tryme"), "Click here", 10).dependent=false
5
6 end
7
8 function action_tryme()
9 luci.http.prepare_content("text/plain")
10 luci.http.write("Haha, rebooting now...")
11 luci.sys.reboot()
12 end
現在在瀏覽器中輸入/cgi-bin/luci/click/here/now(http://192.168.1.1/luci/click/here/now在你的openwrt系統上應該是)
你可以發現這些動作已經被添加到了調度樹上。
正如你可能會或可能不知道的:CGI規范要求您發送您的內容頭之前,首先發送Content-Type。你會發現幾個快捷方式(如上面所使用的),以及在模塊luci.http重定向功能
Views
如果你僅僅是想展現給用戶一行字符或者一些有意思的家庭圖片,那么使用HTML-template就足夠了。這些template也可以包含lua代碼,但是你必須了解到僅僅使用template可以會寫入臟代碼。
現在讓我們來創建一個小的lucidir/view/myapp-mymodule/helloworld.htm,內容如下:
1 <%+header%> 2 <h1><%:Hello World%></h1> 3 <%+footer%>
然后添加下邊的一行index-function到你的module文件中去。
entry({"my","new","template"},template("myapp-mymodule/helloworld"),"Helloworld",20).dependent=false
現在在你的瀏覽器中輸入/cgi-bin/luci/my/new/template(在你的openwrt系統上是http://192.168.1.1/luci/my/new/template)。
你也許注意到了這些奇怪的標簽,這些是被LuCI的template處理程序使用的標記.在標準設計中使用header和footer,是個好的選擇.
CBImodels
CBI是LuCI中最酷的功能.它創建一個標準的用戶接口并且將內容保存在一個特定的UCIconfig文件中。.你只需要描述配置文件的結構,然后CBI程序會幫你完成剩下的部分。這包括生成,解析和驗證HTML表單和讀取和寫入UCI文件。
所以我們必須認真的創建一個實例lucidir/model/cbi/myapp-mymodule/netifaces.lua其內容如下:
1 m = Map("network", "Network") -- We want to edit the uci config file /etc/config/network
2 s = m:section(TypedSection, "interface", "Interfaces") -- Especially the "interface"-sections
3 s.addremove = true -- Allow the user to create and remove the interfaces
4 function s:filter(value)
5 return value ~= "loopback" and value -- Don't touch loopback
6 end s:depends("proto", "static") -- Only show thosewith"static"
7 s:depends("proto", "dhcp") -- or "dhcp" as protocol and leave PPPoE and PPTP alone
8
9 p = s:option(ListValue, "proto", "Protocol") -- Creates an element list (select box)
10 p:value("static", "static") -- Key and value pairs
11 p:value("dhcp", "DHCP")
12 p.default = "static"
13
14 s:option(Value, "ifname", "interface", "the physical interface to be used") -- This will give a simple textbox
15
16 s:option(Value, "ipaddr", translate("IP Address")) -- Ja, das ist eine i18n-Funktion ;-)
17
18 s:option(Value, "netmask", "Netmask"):depends("proto", "static") -- You may remember this "depends" function from above
19
20 mtu = s:option(Value, "mtu", "MTU")
21 mtu.optional = true -- This one is very optional
22 dns = s:option(Value, "dns", "DNS-Server")
23 dns:depends("proto", "static")
24 dns.optional = true
25 function dns:validate(value) -- Now, that's nifty, eh?
26 return value:match("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") -- Returns nil if it doesn't match otherwise returns match
27 end
28
29 gw = s:option(Value, "gateway", "Gateway")
30 gw:depends("proto", "static")
31 gw.rmempty = true -- Remove entry if it is empty
32
33 return m -- Returns the map
當然,別忘記添加你自己的index-function函數。
1 entry({"admin", "network", "interfaces"}, cbi("myapp-mymodule/netifaces"), "Network interfaces", 30).dependent=false
總結
以上是生活随笔為你收集整理的如何编写一个路由器的界面1Luci开发入门的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis 零散知识
- 下一篇: oracle 数据库查询多条数据的一列值