OpenWrt中web界面功能实现及状态获取实例分析
UCI介绍及实例练习
LuCI是OpenWrt上的Web管理界面,LuCI采用了MVC三层架构,使用Lua脚本开发;
具体介绍及功能添加练习,可参考链接:https://blog.csdn.net/icy_river/article/details/48179649;
自己动手分析openwrt中web界面switch功能模块实现
功能截图:
![标签位置:web功能界面Network中Switch下](https://img-blog.csdnimg.cn/2019032909334694.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h4Yl9wb3A=,size_16,color_FFFFFF,t_70)
根据MVC架构,首先进入目录/usr/lib/lua/luci/controller/admin,找到对应的controller控制器文件,该文件中定义了Switch功能在web中Networ下的位置;
vim network.lua,从中截取switch 相关代码片段,如下:
......
uci:foreach("network", "switch",
function(s)
has_switch = true
return false
end)
if has_switch then
page = node("admin", "network", "vlan")
page.target = cbi("admin_network/vlan")
page.title = _("Switch")
page.order = 20 //在Web界面建立Switch标签节点
page = entry({"admin", "network", "switch_status"}, call("switch_status"), nil)
page.leaf = true
end
......
function switch_status(switches)
local s = require "luci.tools.status"
luci.http.prepare_content("application/json")
luci.http.write_json(s.switch_status(switches))
end
......
分析代码:
X:foreach(“config_file”,“type”, function(s) ... End) 针对某一类型的section,调用回调函数,参数s是一个table,包含所有option的值,还包括两个特殊的值:
s[‘.type’]-->section type
s[‘.name’]-->section name
page.target = cbi("admin_network/vlan")
//表示调用cbi模块,这里将会调用到/usr/lib/lua/luci/model/cbi/admin_network/vlan.lua
//vlan.lua 文件中完成VLAN使用,PROT端口号等状态信息获取及功能信息配置等UCI操作,并通过参数上传给Controller和View中的相关文件;
m.uci:foreach("network", "switch",
function(x)
local sid = x['.name']
local switch_name = x.name or sid
local has_vlan = nil
local has_learn = nil
local has_vlan4k = nil
local has_jumbo3 = nil
local has_mirror = nil
local min_vid = 0
local max_vid = 16
local num_vlans = 16
local cpu_port = tonumber(fs.readfile("/proc/switch/eth0/cpuport") or 5)
local num_ports = cpu_port + 1
......
end
......
page = entry({"admin", "network", "switch_status"}, call("switch_status"), nil)
//调用我们下面写的swithc_status函数
local s = require "luci.tools.status"
//加载运行库:admin/tools/status.lua
vim status.lua
function switch_status(devs)
local dev
local switches = { }
for dev in devs:gmatch("[^%s,]+") do
local ports = { }
local swc = io.popen("swconfig dev %q show" % dev, "r")
if swc then
local l
repeat
l = swc:read("*l")
if l then
local port, up = l:match("port:(%d+) link:(%w+)")
if port then
local speed = l:match(" speed:(%d+)")
local duplex = l:match(" (%w+)-duplex")
local txflow = l:match(" (txflow)")
local rxflow = l:match(" (rxflow)")
local auto = l:match(" (auto)")
ports[#ports+1] = {
port = tonumber(port) or 0,
speed = tonumber(speed) or 0,
link = (up == "up"),
duplex = (duplex == "full"),
rxflow = (not not rxflow),
txflow = (not not txflow),
auto = (not not auto)
}
end
end
until not l
swc:close()
end
switches[dev] = ports
end
return switches
end
local swc = io.popen(“swconfig dev %q show” % dev, “r”) //访问交换机芯片的底层驱动,获取link、speed等各种状态信息并存入switches数组返回;
swconfig命令模式
swconfig dev [port |vlan |csmap ] (help|set |get |load |show)
详细介绍参考:https://blog.csdn.net/oYangShanJin/article/details/38128295
OpenWRT swconfig wiki:http://wiki.openwrt.org/doc/techref/swconfig
在/usr/lib/lua/luci/controller/admin/netwrok.lua中:
function switch_status(switches)
local s = require "luci.tools.status"
luci.http.prepare_content("application/json")
luci.http.write_json(s.switch_status(switches))
end
luci.http.prepare_content("application/json")
luci.http.write_json(s.switch_status(switches))
//luci与页面的数据交互命令格式,上传switches参数给页面
查看View页面显示代码,admin/view/admin_network/switch_status.htm
var switches = [ '<%=table.concat(self.switches, "', '")%>' ];
XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "switch_status")%>/' + switches.join(','), null,
function(x, st)
{
for (var i = 0; i < switches.length; i++)
{
var ports = st[switches[i]];
var th0 = document.getElementById('portstatus-' + switches[i]);
if (th0 && ports && ports.length)
{
if (!th0.innerHTML)
th0.innerHTML = '<%:Port status:%>';
for (var j = 0; j < ports.length; j++)
{
var th = th0.parentNode.parentNode.childNodes[j+1];
if (ports[j].link)
{
th.innerHTML = String.format(
'<small><img src="<%=resource%>/icons/port_up.png" />' +
'<br />%d<%:baseT%><br />%s</small>',
ports[j].speed, ports[j].duplex
? '<%:full-duplex%>' : '<%:half-duplex%>'
);
}
else
{
th.innerHTML = String.format(
'<small><img src="<%=resource%>/icons/port_down.png" />' +
'<br /><%:no link%></small>'
);
}
}
}
}
}
);
//]]></script>
htm中通过XHR 动态调用lua脚本获取switches参数信息并处理,lua script location : /usr/lib/lua/luci/controller/admin/network.lua
参考:https://blog.csdn.net/jf_xu/article/details/71480632