开发OpenWrt路由器上LuCI的模块

【一、LuCI配置界面开发的框架】

LuCI是OpenWrt上的Web管理界面,LuCI采用了MVC三层架构,同时其使用Lua脚本开发,所以开发LuCI的配置界面不需要编辑任何的Html代码,除非想自己单独去创建网页(View层),否则我们基本上只需要修改Model层就可以了。官方也有一个如何去创建模块的说明文档,虽然写的比较晦涩:http://luci.subsignal.org/trac/wiki/Documentation/ModulesHowTo

要为LuCI增加一个新模块,首先需要创建两个文件,一个位于Controller(/usr/lib/lua/luci/controller/)下,定义模块的入口;另一个位于Model(/usr/lib/lua/luci/model/cbi/)下,为配置模块实际的代码。

首先我们定义模块的入口,在/usr/lib/lua/luci/controller/下创建一个lua文件,类似如下:

module("luci.controller.控制器名", package.seeall)

function index()
        entry(路径, 调用目标, _("显示名称"), 显示顺序)
        end

第一行说明了程序和模块的名称,比如在controller/目录创建一个mymodule.lua,那么就可以写成“luci.controller.mymodule”,如果你的程序比较多,可能分为好几个模块,那么可以在controller下再常见一个子目录,比如controller/myapp/,那么就可以写成“luci.controller.myapp.mymodule”。

接下来的entry表示添加一个新的模块入口,官方给出了entry的定义,其中后两项都是可以为空的:

entry(path, target, title=nil, order=nil)

第一项是访问的路径,不过路径是按字符串数组给定的,比如路径按如下方式写“{"click", "here", "now"}”,那么就可以在浏览器里访问“http://192.168.1.1/cgi-bin/luci/click/here/now”来访问这个脚本。而通常我们希望为管理员菜单添加脚本,那么我们需要按如下方式编写“{"admin", "一级菜单名", "菜单项名"}”,系统会自动在对应的菜单中生成菜单项。比如想在“网络”菜单下创建一个菜单项,那么一级菜单名可以写为“network”。

第二项为调用目标,调用目标分为三种,分别是执行指定方法(Action)、访问指定页面(Views)以及调用CBI Module。

  • 第一种可以直接调用指定的函数,比如点击菜单项就直接重启路由器等等,比如写为“call("function_name")”,然后在lua文件下编写名为function_name的函数就可以调用了。
  • 第二种可以访问指定的页面,比如写为“template("myapp/mymodule")”就可以调用/usr/lib/lua/luci/view/myapp/mymodule.htm文件了。
  • 而如果要编写配置页面,那么使用第三种方法无非是最方便的,比如写为“cbi("myapp/mymodule")”就可以调用/usr/lib/lua/luci/model/cbi/myapp/mymodule.lua文件了。

而title和order无非是针对管理员菜单来的,可以参考其他的lua文件来决定编写的内容。

这里我们创建/usr/lib/lua/luci/controller/njitclient.lua文件,定义我们的入口,代码如下:

module("luci.controller.njitclient", package.seeall)

function index()
        entry({"admin", "network", "njitclient"}, cbi("njitclient"), _("NJIT Client"), 100)
        end

【二、用Lua和UCI接口开发LuCI配置模块

我们要做的实际上就是希望能将用户名、密码等信息存储在路由器文件中,同时路由器开机时能根据设定的配置自动运行njit-client,同时我们还希望能动态的禁用和启用njit-client等等。所以最方便的方式就是使用CBI Module,上一节我们也添加了这个调用,那么接下来我们就要根据上边写的路径来创建/usr/lib/lua/luci/model/cbi/njitclient.lua文件。

开发LuCI的配置模块有很多种方式,比较基本的可以用SimpleForm,就跟开发普通的Web应用类似,当然最方便的还是使用UCI(Unified Configuration Interface,统一配置接口)的方式,因为使用UCI接口可以使得在LuCI中可以无需考虑配置文件如何存储和读取(这种方式也会自动创建“保存&应用”、“保存”以及“复位”三个按钮),同时在Bash文件中也可以非常方便的存储和读取。

对于使用UCI的方式,我们首先需要创建对应的配置文件(如果配置文件不存在的话,访问配置页面将会报错),格式即为linux配置文件的格式,文件需要存储在/etc/config,比如文件路径为“/etc/config/njitclient”,内容如下:

config login
    option username ‘‘
    option password ‘‘
    option ifname ‘eth0‘
    option domain ‘‘

然后我们要在CBI Module的lua文件中首先需要映射与存储文件的关系,比如:

m = Map("配置文件文件名", "配置页面标题", "配置页面说明")

第一个参数即为配置文件存储的文件名,不包含路径,比如按上述创建的话,应该写为“njitclient”,而第二与第三个参数则是用在来页面上显示的,比如如下所示的图:

接下来需要创建与配置文件中对应的Section,Section分为两种,NamedSection和TypedSection,前者根据配置文件中的Section名,而后者根据配置文件中的Section类型,这里我们使用后者,代码如下。同时我们设定不允许增加或删除Section(“.addremove = false”),以及不显示Section的名称(“.anonymous = true”)。

s = m:section(TypedSection, "login", "")
s.addremove = false
s.anonymous = true

接下来我们需要创建Section中不同内容的交互(创建Option),常见的比如有Value(文本框)、ListValue(下拉框)、Flag(选择框)等等,详细的可以参考官方的文档:http://luci.subsignal.org/trac/wiki/Documentation/CBI

创建Option的过程非常简单,而且创建后系统会无需考虑读取以及写入配置文件的问题,系统都会自动处理。但是根据上述的要求,我们在应用配置以后可能希望启用、禁用或重新启动njit-client,所以我们还需要在页面最后判断用户是否点击了“应用”按钮,这里与编写asp网页等都是相同的,我们可以通过如下的代码判断是否点击了“应用”按钮:

local apply = luci.http.formvalue("cbi.apply")
if apply then
    --[[
        需要处理的代码
    ]]--
end

由于剩余的代码都非常简单,所以所以这部分的全部代码见下:

 1 require("luci.sys")
 2
 3 m = Map("njitclient", translate("NJIT Client"), translate("Configure NJIT 802.11x client."))
 4
 5 s = m:section(TypedSection, "login", "")
 6 s.addremove = false
 7 s.anonymous = true
 8
 9 enable = s:option(Flag, "enable", translate("Enable"))
10 name = s:option(Value, "username", translate("Username"))
11 pass = s:option(Value, "password", translate("Password"))
12 pass.password = true
13 domain = s:option(Value, "domain", translate("Domain"))
14
15 ifname = s:option(ListValue, "ifname", translate("Interfaces"))
16 for k, v in ipairs(luci.sys.net.devices()) do
17     if v ~= "lo" then
18         ifname:value(v)
19     end
20 end
21
22 local apply = luci.http.formvalue("cbi.apply")
23 if apply then
24     io.popen("/etc/init.d/njitclient restart")
25 end
26
27 return m

其中Luci全部类库的函数定义和使用说明可以参考如下地址:http://luci.subsignal.org/api/luci/index.html

【三、在Bash文件中调用UCI接口】

上边我们已经完成了LuCI配置界面的开发,在配置界面中我们已经能读取并保存配置文件了。接下来我们要编写/etc/init.d/njitclient脚本,使程序最终能运行起来。关于UCI接口在脚本文件中的官方说明可以参考:http://wiki.openwrt.org/doc/devel/config-scripting

要使用UCI调用脚本,首先第一步需要读取配置文件,命令为“config_load 配置文件名”,比如我们可以这样读入刚才的配置文件:

config_load njitclient

接下来要遍历配置文件中的Section,可以使用“config_foreach 遍历函数名 Section类型”,例如我们可以这样:

config_foreach run_njit login

然后我们去编写名为“run_njit”的函数,在这个函数中,我们可以使用“config_get 变量名 Section名 Section参数名”获取变量的值,或者使用“config_get_bool 变量名 Section名 Section参数名”获取布尔型的值。所以全部的代码见下:

 1 #!/bin/sh /etc/rc.common
 2 START=50
 3
 4 run_njit()
 5 {
 6     local enable
 7     config_get_bool enable $1 enable
 8
 9     if [ $enable ]; then
10         local username
11         local password
12         local domain
13         local ifname
14
15         config_get username $1 username
16         config_get password $1 password
17         config_get domain $1 domain
18         config_get ifname $1 ifname
19
20         if [ "$domain" != "" ]; then
21             njit-client [email protected]$domain $password $ifname &
22         else
23             njit-client $username $password $ifname &
24         fi
25
26         echo "NJIT Client has started."
27     fi
28 }
29
30 start()
31 {
32     config_load njitclient
33     config_foreach run_njit login
34 }
35
36 stop()
37 {
38     killall njit-client
39     killall udhcpc
40
41     echo "NJIT Client has stoped."
42 }

【四、编译开发的程序

如果按上述内容创建好上述4个文件,那么配置页面和程序就能在OpenWrt上运行起来了。但是如果要想把自己写的程序打包,还需要创建OpenWrt的Makefile来使用OpenWrt的SDK进行编译。

关于LuCI上配置Makefile的官方说明可以见这个地址:http://luci.subsignal.org/trac/wiki/Documentation/Modules

无非就是定义包的名称(PKG_NAME)、版本和生成次数(PKG_VERSION、PKG_RELEASE)、在menuconfig中的分类说明等(define Package/luci-app-njitclient)以及安装时进行的操作(define Package/luci-app-njitclient/install)等等。其中安装的文件分为三种,分别是配置文件、可执行文件以及其他数据文件,其中配置可执行文件时,会自动加入执行权限的,所以不需要额外进行处理。Makefile全部的代码见下:

 1 include $(TOPDIR)/rules.mk
 2
 3 PKG_NAME:=luci-app-njitclient
 4 PKG_VERSION=1.0
 5 PKG_RELEASE:=1
 6
 7 PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
 8
 9 include $(INCLUDE_DIR)/package.mk
10
11 define Package/luci-app-njitclient
12     SECTION:=luci
13     CATEGORY:=LuCI
14     SUBMENU:=3. Applications
15     TITLE:=NJIT 802.1X Client for LuCI
16     PKGARCH:=all
17 endef
18
19 define Package/luci-app-njitclient/description
20     This package contains LuCI configuration pages for njit8021xclient.
21 endef
22
23 define Build/Prepare
24 endef
25
26 define Build/Configure
27 endef
28
29 define Build/Compile
30 endef
31
32 define Package/luci-app-njitclient/install
33     $(INSTALL_DIR) $(1)/etc/config
34     $(INSTALL_DIR) $(1)/etc/init.d
35     $(INSTALL_DIR) $(1)/usr/lib/lua/luci/model/cbi
36     $(INSTALL_DIR) $(1)/usr/lib/lua/luci/controller
37
38     $(INSTALL_CONF) ./files/root/etc/config/njitclient $(1)/etc/config/njitclient
39     $(INSTALL_BIN) ./files/root/etc/init.d/njitclient $(1)/etc/init.d/njitclient
40     $(INSTALL_DATA) ./files/root/usr/lib/lua/luci/model/cbi/njitclient.lua $(1)/usr/lib/lua/luci/model/cbi/njitclient.lua
41     $(INSTALL_DATA) ./files/root/usr/lib/lua/luci/controller/njitclient.lua $(1)/usr/lib/lua/luci/controller/njitclient.lua
42 endef
43
44 $(eval $(call BuildPackage,luci-app-njitclient))

时间: 2024-12-30 00:22:10

开发OpenWrt路由器上LuCI的模块的相关文章

Openwrt路由器上开发微信公众号应用

利用nohup命令创建启动服务 nohup, /dev/null 2>&1,输出重定向 http://www.cnblogs.com/taosim/articles/2610170.html Linux 技巧:让进程在后台可靠运行的几种方法 https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/ [[email protected]:/mnt/sda1/projects/openwrtpytest/utils]#opkg -d usb

Openwrt 路由器上 安装 svn server

Openwrt 上也可以搭建 svn 服务了,这样就不用开着 ubuntu 了,省电. 在后台打开 ssh 服务,或者使用 telnet 服务,使用 putty 登录路由器. 如下图所示,这里刷的是 潘多拉. 先更新一下包 opkg update 安装svnserver opkg install subversion-server 最好是插入usb 因为自带的 25q64 太小.查看usb 挂载地址 cat /proc/mounts 在 /mnt/mmcblk0/ 中建立svn版本库 cd /m

基于OpenWRT,实现360 P1路由器上的朋友专享网络 功能

笔者分析了360 P1路由器上的朋友专享网络功能,发现其主要由如下子功能组成: 1. APP点击“立即开启”,则路由器会多出一个新的SSID:360朋友专享网络-8463.此SSID不加密:同时,原有的主SSID不变 2. STA接入此新SSID后 u  可以获得IP地址,且获得的IP地址与接入主SSID设备获取的IP地址在同一个网段: u 可以访问外网: u 不可以访问360路由器的Web, u 无法ping通360路由器的ip地址 u 无法ping通其他连入此路由器的其他客户端(包括连入36

MIPS平台OpenWrt路由器系统内的Rust应用程序开发

作者:Liigo(庄晓立) 日期:2014年9月17日 原创链接:http://blog.csdn.net/liigo/article/details/39347541 版权所有,转载请注明出处:http://blog.csdn.net/liigo 目标 使用 Rust 语言,交叉编译开发 MIPS(el) + OpenWrt 路由器平台下的应用软件. 编译rustc 首先自行编译Rust编译器源代码,生成支持 mipsel-linux 平台的交叉编译器rustc ./configure --t

Window上python开发--4.Django的用户登录模块User

在搭建网站和web的应用程序时,用户的登录和管理是几乎是每个网站都必备的.今天主要从一个实例了解以下django本身自带的user模块.本文并不对user进行扩展. 主要使用原生的模块. 1.User模块基础: 在使用user 之前先import到自己的iew中.相当与我们自己写好的models.只不过这个是系统提供的models. from django.contrib.auth.models import User # 导入user模块 1.1User对象属性 User 对象属性:usern

openwrt开源系统LUCI配置界面

转自:http://www.right.com.cn/forum/thread-131035-1-1.html 本人菜鸟,最近在学习这方面的知识,在参考资料的基础上总结如下内容.这篇文章针对如何对openwrt开源系统的LUCI界面进行配置! 主要如下三点: 第一,主要介绍了该如何修改luci源代码,在哪里进行修改: 第二,在LuCI里如何写一个自己的模块: 第三,LuCI实现启动应用程序等脚本命令. 一.如何修改LUCI源代码    如何修改该LuCI的源代码,你首先需要了解一下LuCI基本知

0 openwrt路由器入门 远程命令行+文件系统

如图,拿到一个openwrt路由器我们第一步要远程控制. 这里在买了两块wifi-robots  wifi视频模块. 0首先说下这个WIIF的信息 淘宝购买链接 https://item.taobao.com/item.htm?spm=a312a.7700824.w5001-18055431271.3.18644705m9g8Qz&id=555120245987&scene=taobao_shop GL.iNet 刷的系统 OpenWrt Barrier Breaker r38451 /

Openwrt 路由器挂载摄像头教程

一.准备工作 首先就是要有一个刷了openwrt的路由器,固伯里至少包括下面两个摄像头相关模块 kmod-video-core, kmod-video-uvc 以及mjpeg-streamer软件,一个免驱并支持MJPEG输出的摄像头,本人使用HD5000,建议使用HD3000,差别不大 二.测试摄像头 将摄像头插到路由器上,然后SSH到路由器上,执行logread命令,会打印出路由器开机后的的终端log.在里面寻找 "usbcore:registered new interface drive

drcom运行在路由器上

上篇介绍了drcom运行在Linux或Mac平台下,这篇会介绍如何将drcom运行在路由器上. 在解决了自己电脑如何使用drcom的问题后,突然发现drcom使用代理软件会掉线,不允许将网络共享,但是现在这个年代怎么可以不用路由器. 因为学的是计算机网络技术,专业是学思科设备,平时会很关注各种厂商的路由器,遇到这个问题的时候,首先想到的还是Linux环境配合python,Linux是万能的.于是发现openwrt这个路由器系统真的很强大,可以理解为是一个小型的Linux系统,于是找了几种国内的路