告别命令行!用LuCI界面+自定义脚本,在OpenWrt上打造可视化设备监控面板
对于OpenWrt用户来说,命令行虽然强大,但频繁输入arp、iw等命令查看设备状态确实不够直观。想象一下,如果能在一个简洁的Web页面上实时看到所有连接设备的IP、MAC地址、设备名、在线时长甚至实时流量,那该有多方便?本文将带你一步步实现这个目标,无需复杂编程,只需几个简单的Shell脚本和LuCI的巧妙配置。
1. 为什么需要可视化设备监控?
在智能家居和中小企业网络中,了解设备连接状态至关重要。传统方式需要反复登录SSH输入命令,既低效又容易出错。通过LuCI界面打造可视化面板,可以:
- 实时监控:一目了然查看所有在线设备
- 历史记录:追踪设备连接时长和流量使用
- 异常检测:快速发现陌生设备接入
- 友好界面:适合非技术人员查看网络状态
提示:本文方案适用于OpenWrt 19.07及以上版本,需要基础的路由器管理权限
2. 准备工作:基础数据获取
2.1 获取设备连接信息的三种方式
OpenWrt提供了多种获取设备信息的方法,我们将综合利用以下命令:
ARP缓存- 显示IP与MAC对应关系:
cat /proc/net/arp输出示例:
IP address HW type Flags HW address Mask Device 192.168.1.100 0x1 0x2 00:11:22:33:44:55 * br-lan无线客户端信息- 针对WiFi设备:
iw dev wlan0 station dump输出包含信号强度、连接时间等详细信息
DHCP租约- 获取设备名信息:
cat /tmp/dhcp.leases格式为:
租约时间 MAC地址 IP地址 设备名
2.2 数据解析脚本编写
创建一个/usr/bin/device_monitor.sh脚本,整合上述信息:
#!/bin/sh echo "{" > /tmp/device_status.json echo '"devices": [' >> /tmp/device_status.json # 处理ARP表 awk '$3=="0x2" {print $1","$4}' /proc/net/arp | while IFS=, read ip mac; do # 从DHCP租约中查找设备名 name=$(grep "$mac" /tmp/dhcp.leases | awk '{print $4}') [ -z "$name" ] && name="Unknown" # 如果是无线设备,获取信号强度 signal=$(iw dev wlan0 station get $mac 2>/dev/null | grep "signal:" | awk '{print $2}') [ -z "$signal" ] && signal="0" echo '{"ip":"'$ip'","mac":"'$mac'","name":"'$name'","signal":"'$signal'"},' >> /tmp/device_status.json done # 删除最后一个逗号并结束JSON sed -i '$ s/,$//' /tmp/device_status.json echo "]}" >> /tmp/device_status.json给脚本执行权限:
chmod +x /usr/bin/device_monitor.sh3. LuCI界面集成方案
3.1 创建自定义状态页面
编辑/usr/lib/lua/luci/controller/device_monitor.lua:
module("luci.controller.device_monitor", package.seeall) function index() entry({"admin", "status", "devices"}, template("device_monitor"), _("Device Monitor"), 90) end创建模板文件/usr/lib/lua/luci/view/device_monitor.htm:
<%+header%> <h2><%:Device Monitor%></h2> <div class="cbi-map"> <div class="table" id="device-table"> <div class="tr table-titles"> <div class="th"><%:IP Address%></div> <div class="th"><%:MAC Address%></div> <div class="th"><%:Device Name%></div> <div class="th"><%:Signal%></div> <div class="th"><%:Uptime%></div> </div> <div class="tr placeholder"> <div class="td" colspan="5"><%:Loading device data...%></div> </div> </div> </div> <script> function loadDevices() { fetch('/cgi-bin/luci/admin/status/device_data') .then(response => response.json()) .then(data => { const table = document.getElementById('device-table'); // 移除加载提示 const placeholder = document.querySelector('.placeholder'); if (placeholder) placeholder.remove(); data.devices.forEach(device => { const row = document.createElement('div'); row.className = 'tr'; row.innerHTML = ` <div class="td">${device.ip}</div> <div class="td">${device.mac}</div> <div class="td">${device.name}</div> <div class="td">${device.signal} dBm</div> <div class="td">${device.uptime || 'N/A'}</div> `; table.appendChild(row); }); }); } // 初始加载 loadDevices(); // 每30秒刷新一次 setInterval(loadDevices, 30000); </script> <%+footer%>3.2 添加数据接口
创建/usr/lib/lua/luci/controller/device_data.lua:
module("luci.controller.device_data", package.seeall) function index() entry({"admin", "status", "device_data"}, call("get_device_data")) end function get_device_data() os.execute("/usr/bin/device_monitor.sh") local json = io.open("/tmp/device_status.json", "r"):read("*a") luci.http.prepare_content("application/json") luci.http.write(json) end4. 高级功能扩展
4.1 自动刷新与定时任务
为了让数据保持最新,添加cron任务:
(crontab -l 2>/dev/null; echo "*/5 * * * * /usr/bin/device_monitor.sh") | crontab -4.2 设备流量监控
扩展脚本,添加流量统计功能:
# 在device_monitor.sh中添加: for iface in $(ls /sys/class/net/ | grep -v lo); do tc -s class show dev $iface | awk '/Sent/ {print "Interface:",$2,"Sent:",$3,"Received:",$7}' done >> /tmp/device_status.json4.3 设备分类显示
修改HTML模板,添加分类选项卡:
<div class="cbi-tabmenu"> <ul class="cbi-tabmenu-tabs"> <li class="cbi-tab"><a href="#wired"><%:Wired Devices%></a></li> <li class="cbi-tab"><a href="#wireless"><%:Wireless Devices%></a></li> <li class="cbi-tab"><a href="#all"><%:All Devices%></a></li> </ul> </div>5. 界面美化与实用技巧
5.1 添加设备图标
根据MAC地址前几位识别厂商并显示对应图标:
// 在loadDevices函数中添加: fetch('https://macvendors.com/api/' + device.mac) .then(response => response.json()) .then(vendor => { device.vendor = vendor.result.company; });5.2 信号强度可视化
用CSS创建信号条:
.signal-bars { display: inline-block; width: 60px; height: 15px; position: relative; } .signal-bar { position: absolute; bottom: 0; width: 10px; background: #4CAF50; border: 1px solid #ddd; }5.3 设备连接时间计算
在脚本中添加:
connected_time=$(cat /proc/net/arp | grep "$mac" | awk '{print $2}') uptime=$(date -d @$connected_time +"%H:%M:%S")6. 安全注意事项
- 权限控制:确保脚本和接口只能被管理员访问
- 数据保护:MAC地址等敏感信息应考虑脱敏处理
- 性能优化:大量设备时需注意脚本执行效率
注意:定期检查脚本是否正常运行,特别是在OpenWrt升级后
这套方案在我的家庭网络中运行了半年多,最大的收获是再也不用为了查看谁连接了网络而反复登录SSH。当孩子抱怨网络慢时,我可以立即在网页上看到是不是又有新设备偷偷连了上来。