LuCI2 (OpenWrt web 管理界面)

Englishhtml

LuCI2 (OpenWrt web 管理界面)

一直以來OpenWrt都是採用Lua寫的web管理界面LuCI,(開機速度慢不說,竟然比不過騰達等弱路由器開機速度)。 LuCI須要使用多個Lua擴展(如 ubus, luci.model.uci, nixio.fs, 等等)去存取系統信息和設置. 不幸的是這種解決方案在慢CPU和低內存的低配機器設備上是個災難,此方案至關消耗資源且並不能很好的工做。git

這致使開發了LuCI2, 一個不一樣架構的新的web管理節目。它再也不使用Lua,而是使用靜態HTML頁面加JavaScript XHR方法。 這意味着從OpenWrt設備中下載後在客戶端(瀏覽器)中構建HTML頁面, 經過ubus存取各類系統數據(經過uhttpd-mod-ubus提供基於HTTP的接口API).web

重要說明

如上所述, LuCI2經過ubus和OpenWrt子系統通訊(包括如networkservice以及其它)。遺憾的是並不是每一個主要的OpenWrt工具都本身註冊了ubus,如LuCI2不能使用opkg(安裝包管理)。 LuCI2經過提供在附加ubus名稱空間的rpcd插件解決了這個問題。前面說的opkg它在ubus中註冊了一個新的luci2.opkg路徑來訪問。promise

綜上所述, LuCI2包括兩個方面: 打包的HTML/CSS/JS文件 (htdocs) 和一些在OpenWrt環境下運行的附加小工具。瀏覽器

在接下來的章節中,你會找到各類關於LuCI2開發幫助的細節。session

菜單

首先須要知道的是瀏覽器接收到的關於LuCI2菜單並不固定寫死在任何文件。代替的是經過ubus使用luci.ui路徑和menu方法。能夠經過使用如下命令來查看:架構

ubus call luci2.ui menu '{ "ubus_rpc_session": "invalid" }'

內部的rpcd插件分析在目錄/usr/share/rpcd/menu.d的全部文件,當前用戶(基於傳遞的ubus_rpc_session)不容許增長或者刪除條目。這將致使在一個二級菜單限制當前有權限訪問的條目。app

頂層菜單項用下面的JSON定義:異步

"foo": {
	"title": "Foo",
	"index": 12
}

(而且經過index值排序)。工具

第二層菜單項經過一樣的方法定義:

"foo/bar": {
	"title": "Bar",
	"acls": [ "baz", "qux" ],
	"view": "foo/bar",
	"index": 5
}

注意,第二層菜單項能夠在獨立的文件中定義,這樣就能夠方便的添加新的菜單項定義而不用修改原有的文件。

模板

每個LuCI2子頁面必須有一個存放在/www/luci2/template/目錄下的模板。它們提供了很是簡單的內容替換區的HTML文件。須要注意的是它們不包含任何變量的引用,這是JavaScript的功勞:用JavaScript去讀取並寫入內容。在爲本地化系統(i18n)這些文件中惟一特定的語法相似下面的標記:

<p><%:Hello world%></p>

視圖

從模板中分離,每一個LuCI2子頁面也須要一個定義並存放在/www/luci2/view/目錄下的一個視圖,視圖是使用了子頁面特定對象的L.ui.view擴展的JavaScript文件。Javascript中須要提供execute方法的實現,該方法將在膜拜加載後被執行。可選的也能夠提供子頁面的titledescription屬性。

有一點須要注意的是須要提供execute方法,建立視圖失敗有幾種緣由,特別是當它須要ubus加載額外的數據使用的時候。因此在execute方法中提供成功或者失敗的信息是有意義的。不幸的是在異步方法加載特定數據的時候,不能簡單的返回truefalse,解決的方法是返回一個Promise對象來運行推遲提供是否成功的信息。

最簡單的視圖能夠以下所示:

L.ui.view.extend({
	title: L.tr('Foo'),			/* 可選的標題 */
	description: 'Bar',			/* 可選的描述 */

	execute: function() {
		var deferred = $.Deferred();	/* 建立一個延遲對象 */
		deferred.resolve();		/* 當即Resolve,它不作任何事能夠返回失敗 */
		return deferred.promise();	/* 返回Promise對象 (延遲對象的子集) */
	}
});

經過ubus通信

在開始以前,須要知道的是LuCI2提供了一些存取UCI系統的一些幫助。若是寫一個簡單的管理/etc/config/下配置文件不須要徹底知道ubus的調用方法,則能夠跳過該部分。

構建一些更復雜的LuCI2視圖前最好先弄明白使用到的ubus調用。完整的對象和方法列表能夠經過運行ubus -v list命令來獲得。

下面這個簡單的例子調用了log對象和write方法,它須要提供一個event參數傳遞進去。使用ubus命令行國內根據是,須要以下所示命令:

ubus call log write '{ "event": "Foo" }'

LuCI2爲ubus通信提供了一個叫作L.rpc.declare的工具,它能夠如魔法般的幫助JavaScript訪問ubus方法。注意,定義聲明方法的時候方法並不被執行,參數也未傳遞,這是爲之後調用準備的一個方法。下面這個示例的方法調用了log對象的write方法:

var writeToLog = L.rpc.declare({
	object: 'log',
	method: 'write',
	params: [ 'event' ]
})

定義了一次這個方法後,能夠在任意時間經過以下示例簡單調用:

writeToLog('Foo');

在上面的例子中執行結果被忽略了,若是視圖須要處理ubus返回的數據時不能忽略執行結果。下面例子將經過訪問system對象的info方法來描述返回結果的處理。在命令行下經過如下命令訪問:

# ubus call system info
{
	"uptime": 123,
	"localtime": 1234567890,
	"load": [
		1,
		2,
		3
	],
	"memory": {
		"total": 67108864,
		"free": 33554432,
		"shared": 0,
		"buffered": 16777216
	},
	"swap": {
		"total": 0,
		"free": 0
	}
}

在LuCI2(JavaScript)定義上面的訪問以下所示:

var readSystemInfo = L.rpc.declare({
	object: 'system',
	method: 'info',
	expect: { memory: { } }			/* 可選, 只提取結果的一部分memory */
})

經過簡單的調用.then方法可訪問結果數據

readSystemInfo().then(function(memory) {
	console.log(memory);
});

怎樣測試

在"feeds.conf"中添加一個feed:

src-git luci2 git://git.openwrt.org/project/luci2/ui.git

安裝luci2包:

./scripts/feeds update
./scripts/feeds install luci2

在menuconfig中勾選Luci2包並編譯新固件。

相關文章
相關標籤/搜索