如何编写一个路由器的界面1-Luci开发入门

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的文件,文件内容如下:

1 module("luci.controller.myapp.mymodule", package.seeall)
2
3 function index()
4
5 end

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

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

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

Actions

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

 1 module("luci.controller.myapp.mymodule", package.seeall)
 2
 3 function index()
 4      entry({"click", "here", "now"}, call("action_tryme"), "Click here", 10).dependent=false
 5
 6 end
 7
 8 function action_tryme()
 9     luci.http.prepare_content("text/plain")
10     luci.http.write("Haha, rebooting now...")
11     luci.sys.reboot()
12 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,内容如下:

1 <%+header%>
2 <h1><%:Hello World%></h1>
3 <%+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  其内容如下:

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

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

1 entry({"admin", "network", "interfaces"}, cbi("myapp-mymodule/netifaces"), "Network interfaces", 30).dependent=false
时间: 2024-12-24 10:24:26

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

android#编写一个聊天界面

摘自<第一行代码>——郭霖 既然是要编写一个聊天界面,那就肯定要有收到的消息和发出的消息.上一节中我们制作的message_left.9.png可以作为收到消息的背景图,那么毫无疑问你还需要再制作一张message_right.9.png作为发出消息的背景图.图片都提供好了之后就可以开始编码了,首先还是编写主界面,修改activity_main.xml中的代码,如下所示: <LinearLayout xmlns:android="http://schemas.android.c

c语言:编写一个简易计算器,打印菜单界面,实现加减乘除运算,可以退出菜单界面

.编写一个简易计算器 程序: #include<stdio.h> enum  OP { EXIT,//0 ADD,//1 SUB,//2 MUL,//3 DIV//4 }; void menu()//menu表示菜单 { printf("**** 1.add  ****\n"); printf("**** 2.sub  ****\n"); printf("**** 3.mul  ****\n"); printf("**** 

c语言中如何设计和编写一个应用系统?

C程序中,如何设计和编写一个应用系统? 一. C语言文件的操作 1. 文件操作的基本方法: C语言将计算机的输入输出设备都看作是文件.例如,键盘文件.屏幕文件等. 向屏幕输出一个信息,例如"Hello"是 #include.h> int main() { printf("Hello\\n"); } 从键盘接收一个字符串然后显示是 #include.h> int main() { char a[10]; scanf("%s",&

5分钟编写一个PHP留言板程序

1.创建数据库 以下为sql代码,推荐采用phpmyadmin创建数据库. CREATE DATABASE IF NOT EXISTS db_liuyan; USE db_liuyan; CREATE TABLE ly( id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, username VARCHAR(20) NOT NULL, email VARCHAR(100) NOT NULL, content TEXT NOT NULL, date TIMEST

编写一个猜数字游戏

编写一个程序,实现猜数字游戏,计算机随机产生一个数,输入猜的数,与计算机随机产生的数进行比较,当猜的数大于随机产生的数,给出提示猜的数过大,反之,给出提示猜的数太小.下面是具体的程序: #include <stdio.h> #include <stdlib.h> #include <time.h> void fun()        //定义fun函数,说明游戏的具体操作 {     int a=0;     int ret=rand()%100;           

MFC+WinPcap编写一个嗅探器之六(分析模块)

这一节是程序的核心,也是最复杂的地方 首先需要明白的一点是,一般对于一个有界面的程序来说,往往需要多线程.本程序中除了界面线程外,抓包需要另外创建一个新的线程.在写抓包函数之前,首先要将前面两个模块的结果返回到主对话框界面对应的类实现中,在SnifferDlg.cpp中,修改之前增加的两个模块的触发函数如下: 1 void CSnifferDlg::OnAdp() 2 { 3 // TODO: 在此添加命令处理程序代码 4 CAdpDlg adpdlg; 5 if(adpdlg.DoModal(

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

讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目需要满足怎样的需求. 那么,画板需要满足怎样的需要呢?换句话说,在画板上,我们应该赋予它什么功能呢?从我们熟悉的画板来看,我们需要实现诸如铅笔.橡皮.喷枪.刷子的功能,我们可以画出一些规则的图形,比如直线.矩形.圆.最好我们还能调整画笔的颜色和粗细.以上,我们希望的是,当我们点击一个按钮的时候,我们

编写一个简单的javaEE加法程序

一 .javaEE的安装及环境配置 工具: 32位系统准备eclipse-jee-mars-2-win32.zip,64位系统准备eclipse-jee-mars-2-win32-x86_64.zip jdk1.7 maven3.3.9.rar m2.rar 环境配置: 1. 设置eclipse的配置文件eclipse.ini,修改虚拟机路径,在-vmargs之前添加 -vm E:\jee\jdk1.7\bin\javaw.exe 注意:用写字板打开修改,-vm有的电脑要换行,有的电脑不用换行

从头开始编写一个Orchard网上商店模块(6) - 创建购物车服务和控制器

原文地址: http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-6创建购物车服务和控制器 这是从头开始编写一个新的Orchard模块的教程的第6篇.对于本教程的概述,请参阅介绍. 在本篇,我们将使我们的用户可以添加商品到他们的购物车.要创建这样的功能,我们需要: 一个“添加到购物车”按钮,要被添加我们的产品目录上,将产品添加到购物车 某种购物车服务,以存储