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包并编译新固件。

相关文章
相关标签/搜索