Howto:如何写Module(模块)-----------------这一部分主要是翻译github上的document

注意:如果您打算将模块加入LUCI整合之前,您应该阅读Module参考

本教程介绍如何编写自己的LUCI WebUI中的模块。在本教程中,我们假设您的luci安装目录lucidir(如果您目前使用的是安装版/usr/lib/LUA/LUCI),并假设你的luci安装经由/cgi-bin/LUCI访问您的Web服务器。
方法路线(针对调度过程)

要编写模块,您需要了解LUCI调度过程的基础知识。 LUCI使用,将通过执行每个可供使用的controller的索引功能建立一个调度树。在CGI环境变量PATH_INFO将作为在这个调度树,例如: /cgi-bin/luci/foo/bar/baz将被解析为foo.bar.baz

要注册在调度树中的功能,你可以使用luci.dispatcher的入口函数(Entry function)。进入需要4参数(其中的2个是可选的):

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

  • path 是一个table结构,描述了在调度树的的位置: 例如, {"foo", "bar", "baz"}的path 将被插入到 foo.bar.baz.
  • target 描述当用户请求该节点时将要采取的行动. 其中有三个预定义的对象是最重要的 (call, template, cbi) ,他们将在本页的后边描述
  • title 定义了在可见的菜单中的选项,也就是最终luci界面中可以看到的标题内容(可选)
  • order 主要依据这个数字来使同一水平上的节点在菜单上的排序 (可选)

你可以通过操作节点表的返回值来给entry function赋更多的参数。一些典型的参数例子:

  • i18n 定义了当页面被请求时,自动加载的解释程序(文件)
  • dependent 防止插件在其父节点的确实,也就是添加插件的依赖
  • leaf 停止解析该节点的请求,并没有更进一步的调度树
  • sysauth 要求用户与给定系统的用户帐户进行认证

下边就是命名与使用过程

既然你已经了解了调度的基础知识,现在,我们可以开始写module了。但是在这之前,我们必须先选择目录并且命名属于你自己的新节点。

我们假设你想要创建一个新叫做myapp的应用,而且myapp的module是mymodule。

因此你必须创建一个子文件夹lucidir/controller/myapp,在该文件夹下创建一个mymodule.lua的文件,文件内容如下:

 module("luci.controller.myapp.mymodule", package.seeall) 

 function index()

 end

第一行要求lua正确识别模块,并建立它的范围。该index function将用于注册在调度树中的动作。

到目前为止,你就已经有了一个新的节点,只不过是该节点中没有任何的功能。

我们假设你想要复用你的myapp.mymodule 模块,那么你就必须开始最后一个步骤。

Actions

重新打开lucidir/controller/myapp/mymodule.lua并且添加一个函数类似下边的内容:

 module("luci.controller.myapp.mymodule", package.seeall)

 function index()
entry({"click", "here", "now"}, call("action_tryme"), "Click here", ).dependent=false end function action_tryme()
luci.http.prepare_content("text/plain")
luci.http.write("Haha, rebooting now...")
luci.sys.reboot()
end

现在在浏览器中输入/cgi-bin/luci/click/here/now(http://192.168.1.1/luci/click/here/now 在你的openwrt系统上应该是)

你可以发现这些动作已经被添加到了调度树上。

正如你可能会或可能不知道的:CGI规范要求您发送您的内容头之前,首先发送Content-Type。你会发现几个快捷方式(如上面所使用的),以及在模块luci.http重定向功能

Views

如果你仅仅是想展现给用户一行字符或者一些有意思的家庭图片,那么使用HTML-template就足够了。这些template也可以包含lua代码,但是你必须了解到仅仅使用template可以会写入脏代码。

现在让我们来创建一个小的lucidir/view/myapp-mymodule/helloworld.htm,内容如下:

 <%+header%>
<h1><%:Hello World%></h1>
<%+footer%>

然后添加下边的一行index-function 到你的module文件中去。

entry({"my", "new", "template"}, template("myapp-mymodule/helloworld"), "Hello world", 20).dependent=false

现在在你的浏览器中输入 /cgi-bin/luci/my/new/template (在你的openwrt系统上是http://192.168.1.1/luci/my/new/template ) 。

你也许注意到了这些奇怪的标签, 这些是被LuCI的template处理程序使用的标记. 在标准设计中使用header和footer,是个好的选择.

CBI models

CBI是LuCI中最酷的功能. 它创建一个标准的用户接口并且将内容保存在一个特定的UCI config文件中。.你只需要描述配置文件的结构,然后CBI程序会帮你完成剩下的部分。 这包括生成,解析和验证HTML表单和读取和写入UCI文件。

所以我们必须认真的创建一个实例 lucidir/model/cbi/myapp-mymodule/netifaces.lua  其内容如下:

 m = Map("network", "Network") -- We want to edit the uci config file /etc/config/network
s = m:section(TypedSection, "interface", "Interfaces") -- Especially the "interface"-sections
s.addremove = true -- Allow the user to create and remove the interfaces
function s:filter(value)
return value ~= "loopback" and value -- Don't touch loopback
end s:depends("proto", "static") -- Only show thosewith"static"
s:depends("proto", "dhcp") -- or "dhcp" as protocol and leave PPPoE and PPTP alone p = s:option(ListValue, "proto", "Protocol") -- Creates an element list (select box)
p:value("static", "static") -- Key and value pairs
p:value("dhcp", "DHCP")
p.default = "static" s:option(Value, "ifname", "interface", "the physical interface to be used") -- This will give a simple textbox s:option(Value, "ipaddr", translate("IP Address")) -- Ja, das ist eine i18n-Funktion ;-) s:option(Value, "netmask", "Netmask"):depends("proto", "static") -- You may remember this "depends" function from above mtu = s:option(Value, "mtu", "MTU")
mtu.optional = true -- This one is very optional
dns = s:option(Value, "dns", "DNS-Server")
dns:depends("proto", "static")
dns.optional = true
function dns:validate(value) -- Now, that's nifty, eh?
return value:match("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") -- Returns nil if it doesn't match otherwise returns match
end gw = s:option(Value, "gateway", "Gateway")
gw:depends("proto", "static")
gw.rmempty = true -- Remove entry if it is empty return m -- Returns the map

当然,别忘记添加你自己的index-function函数。

 entry({"admin", "network", "interfaces"}, cbi("myapp-mymodule/netifaces"), "Network interfaces", ).dependent=false

如何编写一个路由器的界面1-Luci开发入门的更多相关文章

  1. 使用Java语言编写一个五子棋UI界面并实现网络对战功能(非局域网)

    使用Java语言编写一个五子棋UI界面并实现网络对战功能(非局域网) 一,前期准备 1,Java IDE(Eclipse)与JDK的安装与配置jdk-15.0.1-免配置路径版提取码:earu免安装版 ...

  2. 二、Django用Eclipse编写一个登录界面

    一.Django用Eclipse编写一个登录界面 二.Django用Eclipse编写一个登录界面Ajax和Django交互 各软件版本:Python 2.7.14,django 1.6.11 原来已 ...

  3. 一、Django用Eclipse编写一个登录界面

    一.Django用Eclipse编写一个登录界面 二.Django用Eclipse编写一个登录界面Ajax和Django交互 Eclipse安装Python插件和Django的步骤直接省略. 创建de ...

  4. MFC+WinPcap编写一个嗅探器之二(界面)

    选择新建->项目->MFC应用程序->基于对话框完成,这里文件名为sniffer 打开资源视图中的Dialog列表,打开项目总默认创建的话框,将对话框中的所有控件删除,之后按照最终效 ...

  5. android#编写一个聊天界面

    摘自<第一行代码>——郭霖 既然是要编写一个聊天界面,那就肯定要有收到的消息和发出的消息.上一节中我们制作的message_left.9.png可以作为收到消息的背景图,那么毫无疑问你还需 ...

  6. 用Java语言编写一个简易画板

    讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目 ...

  7. 用java写一个用户登陆界面

    一.课堂测试源代码及其结果截图 用java的swing写一个用户登录界面,采用网格布局.源代码如下: /** * */package LiuLijia; import java.awt.CardLay ...

  8. 第二次作业:编写一个四则运算的"软件"

    - 题目: 请编写一个能自动生成小学四则运算题目的 “软件”. 让程序能接受用户输入答案,并判定对错. 最后给出总共 对/错 的数量. 需求分析: ●基本功能 ●实现100以内的加法 ●实现100以内 ...

  9. 如何编写一个稳定的网络程序(TCP)

    本节我们看一下怎样才能编写一个基于TCP稳定的客户端或者服务器程序,主要以试验抓包的方式观察数据包的变化,对网络中出现的多种情况进行分析,分析网络程序中常用的技术及它们出现的原因,在之后的编程中能早一 ...

随机推荐

  1. leetcode-hard-array-454 4sum II-NO

    mycode   过不了...我也不知道为什么... class Solution(object): def fourSumCount(self, A, B, C, D): ""& ...

  2. 开源运维自动化平台-opendevops

    开源运维自动化平台-opendevops 简介 官网 | Github|  在线体验 CODO是一款为用户提供企业多混合云.自动化运维.完全开源的云管理平台. CODO前端基于Vue iview开发. ...

  3. Spring AOP增强(Advice)

    Sring AOP通过PointCut来指定在那些类的那些方法上织入横切逻辑,通过Advice来指定在切点上具体做什么事情.如方法前做什么,方法后做什么,抛出异常做什么. Spring中有两种方式定义 ...

  4. selenium爬虫使用

    1. 网页的打开 from selenium import webdriver import time driver = webdriver.Chrome(executable_path=r" ...

  5. DP&图论 DAY 1 下午

    DP&图论  DAY 1  下午  区间和序列上的DP 序列上的DP >序列上的dp状态设计最基本的形式 F[i]表示以 i 结尾的最优值或方案数.◦ F[i][k]表示以 i 结尾附加 ...

  6. ROC和AUC————摘在网络

    ROC曲线 对于0,1两类分类问题,一些分类器得到的结果往往不是0,1这样的标签,如神经网络,得到诸如0.5,0,8这样的分类结果.这时,我们人为取一个阈值,比如0.4,那么小于0.4的为0类,大于等 ...

  7. SSH2配置

    Ubuntu14.04配置openSSH-server时报错,很有可能是因为如下的报错原因 这个问题大概应该是你的/etc/apt/的源有问题,但大概可以这么解决:1.sudo apt-get pur ...

  8. 阶段3 3.SpringMVC·_06.异常处理及拦截器_4 SpringMVC拦截器之介绍和搭建环境

    拦截器可以有多个 搭建环境 不用改,直接finish 复制原来项目的 依赖的包也复制过来 web.xml配置前端控制器 springmvc的配置文件 先创建对应的文件夹 分别创建java和resour ...

  9. httpClient模仿Basic Auth

    httpclient代码调用如下: @GetMapping("loginTest") public String httpClientWithBasicAuth() { Strin ...

  10. 【转】zookeeper之 zkServer.sh命令、zkCli.sh命令、四字命令

    [FROM]https://www.cnblogs.com/andy6/p/7674028.html 一.zkServer.sh 1.查看 zkServer.sh 帮助信息 [root@bigdata ...