openWRT的luci web管理器添加新菜单案例--testclient

 

luci的开发不是像网页一样使用html,css,js进行开发,而是使用lua脚本和uci接口,下面就来仔细介绍一下luci的简单开发过程。
首先我们创建上面必需的三个文件,做一个简单的界面:

root@OpenWrt:/# cat /usr/lib/lua/luci/controller/testclient.lua
module("luci.controller.testclient", package.seeall) 
function index() 
if not nixio.fs.access("/etc/config/testclient") then 
return 
end 
entry({"admin", "services", "testclient"}, cbi("testclient"), _("Testclient")).dependent = true 
end

//首先检查有没有/etc/config/pdnsd文件,如果有就继续向下执行,没有就当什么都没有发生过
第一行中,固定格式是“luci.controller.我的项目名”,因为我们所有的lua文件和/etc/config下面的配置文件都是以pdnsd来进行命名的,所以应该填“luci.controller.pdnsd”
倒数第二行是一个固定格式
entry(路径, 调用目标, _("显示名称"), 显示顺序)
路径:{"admin", "services", "pdnsd"} 意思是登录用户可见,“服务”主菜单下,“名字叫pdnsd的配置文件”,如果你想要放到“系统”菜单下,就把“services”改成“system”
调用目标:指向/usr/lib/lua/luci/model/cbi/pdnsd.lua这个控制文件
显示名称:显示为“Pdnsd”,当然这里也可以填UTF-8的中文,用来在主菜单上显示
显示顺序:这里没填,使用系统默认的显示顺序

root@OpenWrt:/# cat /etc/config/testclient
config arguments

//这个文件是记录你配置好的参数的,由于我们现在并不需要记录什么参数,所以写个uci的开头就够,其中“arguments”是一个固定标志。

root@OpenWrt:/# cat /usr/lib/lua/luci/model/cbi/testclient.lua
local fs = require "nixio.fs" 
m=Map("testclient",translate("Testclient"),translate("testclient configuration ......")) 
s=m:section(TypedSection,"arguments","") 
s.addremove=false 
s.anonymous=true 
view_enable = s:option(Flag,"enabled",translate("Enable")) 
return m

//第1行是引用依赖库,这个依赖库是用来读取和写入文件的,目前不写这一行也可以,但是要实现读写配置文件的功能,这个库是必不可少的
第2行是固定格式
m = Map("配置文件文件名", "配置页面标题", "配置页面说明")
第一个参数:上一步我们新建配置文件/etc/config/pdnsd.这里就是建立与配置文件的联系.
第二个参数:主标题.
第三个参数:副标题,注意不能出现双引号“”,否则会报错,中文要使用UTF-8编码

第3行:
m:section(类型,“arguments”,“”)
在一个配置文件中可能有很多Section,所以我们需要创建与配置文件中我们想要的Section的联系. “arguments”就是section的uci名字,就是我们在/etc/config/pdnsd中写的那个config arguments
有两种方式可以选择:NamedSection(name,type,title,description)和TypedSection(type,title,description),前者根据配置文件中的Section名,而后者根据配置文件中的Section类型.我们选用了第二种.

第4行:设定不允许增加或删除Section,这样能保证页面的清爽,不然会多出一些奇奇怪怪的控件
第5行:设定是否显示Section的名称,建议为true
这里顺带提一句,lua脚本中使用--来作为注释的标记,而不是常见的//或者#;另外luci可以显示中文,但是你在编辑lua文件的时候必须指定“UTF-8”编码,否则出来的中文是乱码

--------------------------------------------
把这三个文件通过winscp上传到路由器对应的目录上,无需重启路由器,刷新一下路由器后台就可以看到效果:
root@OpenWrt:/# cat /etc/config/testclient

config arguments
option enabled '1'
//view_enable = s:option(Flag,"enabled",translate("Enable"))
Flag是checkbox控件的意思,如果改成Value就是文本框,相当于html中的input标签
“enabled”是/etc/config/pdnsd这个uci文件的字段名,所以我们可以顺带在这个文件里加入一个默认值,如下:
页面中果然多了一个“启用”checkbox,此时如果你点击“保存&应用”就会把该checkbox的状态记录到/etc/config/pdnsd文件中,如果勾选就是1,不勾选为0或者不显示该项


root@OpenWrt:/# cat /usr/lib/lua/luci/model/cbi/testclient.lua //实现文件的读取功能
local fs = require "nixio.fs"
m=Map("testclient",translate("Testclient"),translate("testclient configuration ......"))
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
view_enable = s:option(Flag,"enabled",translate("Enable"))
view_cfg=s:option(TextValue,"1",nil) //TextValue就是大文本框的意思,相当于html中的text标签
view_cfg.rmempty=false //设置该文本框不许留空,如果为空在“保存&应用”中会出现相应的提示
view_cfg.rows=23 //.rows = 23是这个大文本框的高度为43行,如果内容超出会出现滚动条

function view_cfg.cfgvalue()
//要实现进入该界面的时候该文本框自动显示/etc/pdnsd.conf这个配置文件的内容,需要重写大文本框自带的.cfgvalue()方法,这样浏览器进入pdnsd页面之后luci后台就会自动调用该控件的.cfgvalue()方法,把文件内容呈现在浏览器上。
return nixio.fs.readfile("/etc/testclient.conf") or ""
//nixio.fs.readfile("文件路径")会读取一个文件的全部内容,返回值就是该文件的内容 or ""意思是如果前面那句报错,就输出空字符串。
end
return m


root@OpenWrt:/# cat /etc/config/testclient
config arguments
option enabled '1'
option 2 'hello ming!'

-------------------------------------------------------
root@OpenWrt:/# cat /usr/lib/lua/luci/model/cbi/testclient.lua //实现文件的写入功能,我们需要实现TextValue控件的另一个自带方法
local fs = require "nixio.fs"

function sync_value_to_file(value,file)
value = value:gsub("\r\n?","\n")
local old_value = nixio.fs.readfile(file)
if value ~=old_value then
nixio.fs.writefile(file,value)
end
end

m=Map("testclient",translate("Testclient"),translate("testclient configuration ......"))
s=m:section(TypedSection,"arguments","")
s.addremove=false
s.anonymous=true
view_enable = s:option(Flag,"enabled",translate("Enable"))
view_cfg=s:option(TextValue,"1",nil)
view_cfg.rmempty=false
view_cfg.rows=23

function view_cfg.cfgvalue()
return nixio.fs.readfile("/etc/testclient.conf") or ""
end

function view_cfg.write(self,section,value)
sync_value_to_file(value,"/etc/testclient.conf")
end

return m
//代码中又重写了.write(self,section,value)这个方法,其中value这个参数就是当前TextValue这个控件中显示的文字,于是我又写了一个函数 sync_value_to_file(文本,文件路径)方法来将控件中的内容写入到文件中去。
而那个信函数主要作用就是先把windows中的换行符“\r\n”换成linux的换行符“\n”
然后检查一下新旧文本有没有发生变化,如果发生变化才调用库函数nixio.fs.writefile(file, value)将文本写入到文件中去。


root@OpenWrt:/# cat /etc/testclient.conf
hello ming!
hahada
heheheroot@OpenWrt:/#

root@OpenWrt:/# cat /etc/config/testclient
config arguments
option 2 'hello ming!
'
option enabled '1'
----------------------------------------------------------
可是我们还想在配置文件发生修改之后自动重启后台的服务,应该怎么做呢,首先我们记得我们上面的checkbox记录了启用与否,并记在了/etc/config/pdnsd这个文件里。那么我们可以根据这个文件记录的内容,如果是1就restart pdnsd这个服务并enable,如果是0就stop这个服务并disable。

root@OpenWrt:/# cat /etc/testclient_init.sh
echo luci for testclient
local vt_enabled=`uci get testclient.@arguments[0].enabled 2>/dev/null`
echo $vt_enabled
if [ "$vt_enabled" = 1 ]; then
logger -t alex restarting testclient
echo "restarting testclient"
/etc/init.d/testclient enable
/etc/init.d/testclient restart
else
logger -t alex stopping testclient
echo "stopping testclient"
/etc/init.d/testclient disable
/etc/init.d/testclient stop
fi


function sync_value_to_file(value,file)
value = value:gsub("\r\n?","\n")
local old_value = nixio.fs.readfile(file)
if value ~=old_value then
nixio.fs.writefile(file,value)
end
os.execute("/etc/testclient_init.sh >/dev/null")
end

root@OpenWrt:/# cat /etc/testclient.conf
hello ming!
my name is meng!
test...

  

参考:http://blog.csdn.net/lvshaorong/article/details/53939138

posted @ 2017-12-11 09:31  bkycrmn  阅读(1263)  评论(0)    收藏  举报