OpenWrt路由器开发

标签: openwrt | 发表时间:2015-04-30 23:41 | 作者:夏日小草
出处:http://segmentfault.com/blogs

http://homeway.me

OpenWrt




0x01.About

第一次尝试开发路由器,发现并不是想象中那么难,和普通嵌入式开发一样,也是一块ARM板刷上Linux系统。

OpenWrt有很多好用的软件,附带流量监测。

OpenWrt主要开发语言为Python、Lua、Shell,还可以做深入研究写ipk软件包。

写了几个脚本,主要实现了openwrt下面GPIO控制、系统信息获取、wifi扫描器、定时发送邮件系统报警等功能,下面会介绍。

代码已经在Github开源: https://github.com/grasses/OpenWRT-Util



0x02.About OpenWrt

刷OpenWrt先要去 https://downloads.openwrt.org/下载你想要的版本,包含aa型和bb型。

然后用Linux烧入命令烧入系统。

早MAC下面,先现将U盘插入电脑格式化,然后运行命令查看U盘编号:

diskUtil list

注意查看U盘编号,选择你的U盘,解除挂载:

diskUtil unmountDisk /dev/disk2

然后烧入系统:

dd if=/path/to/openwrt.img of=/dev/disk2 bs=2m

等待几分钟后烧入成功。

关于痛点:

  第一次是在树莓派上安装OpenWrt,装好后,用有线把连进上级路由器的Lan口

然后,上级路由的包开始乱了,上级路由把OpenWrt当成路由器,OpenWrt把路由器当成上级路由器,然后就GG了。



0x03.About WRTnode

WRTnode是OpenWrt系统一个硬件解决方案,预先安装了OpenWrt相关软件包,并且内置两块无线网卡。

关于WRTnode,官方wiki已经介绍的很详细了: http://wiki.wrtnode.com/index.php?title=Main_Page/zh-cn

解析来的代码基本上是在WRTnode环境上开发的,主要包含了:

目前只能想起这3个,如果报错,该装什么再装好了。



0x04.WRTnode控制GPIO

GPIO控制可以很好地实现软件硬件之间的交互。

WRTnode GPIO

GPIO的控制也不难,wiki讲得很清晰了,就是文件输入输出 http://wiki.wrtnode.com/index.php?title=The_user_space_gpio_calls/zh-c...

这里我写了一个Lua版的GPIO控制模块,文件保存为gpio.lua:

  #!/usr/bin/lua
--[[
Copyright 2015 http://homeway.me
@author homeway
@version 15.04.29
@link http://homeway.me
@function OpenWRT gpio module
-- ]]--

local M = {}
M.id = ""
M.path = "/sys/class/gpio/gpio"
M.router = "/sys/class/gpio"

M.check = function(where)
    print("check path => "..where)
    local f=io.open(where, "r")
    if f~=nil then io.close(f) return true else return false end
end
-- set mode && check type
M.mode = function(id, mtype)
    M.id = id
    where = M.path..M.id
    -- if id not use
    if false==M.check(M.path..id..'/direction') then
        --M.writeFile(M.router.."/unexport",id)
        M.writeFile(M.router.."/export", id)
    end
    -- if type different 
    if mtype ~= M.readFile(M.path..id..'/direction') then
        print("type =>"..mtype.." direction=>"..M.readFile(M.path..id..'/direction').." different")
        M.writeFile(M.path..id..'/direction', mtype)
    end
end
-- file write
M.writeFile = function(where, what)
    print("write path => "..where.." data =>"..what)
    local fp=io.open(where, 'w')
    fp:write(what)
    fp:close()  
end
-- file read
M.readFile = function(where)
    print("read path => "..where)
    local fp=io.open(where, 'r')
    if fp~=nil then
        data = fp:read("*all")
        fp:close()
        return data
    end
    return nil
end
M.set = function(id)
    M.id = id
end
M.read = function()
    res = M.readFile(M.path..M.id..'/value')
    return res
end
M.write = function(value)
    res = M.writeFile(M.path..M.id..'/value', value)
end
M.close = function()
    print("sleep io => "..M.id)
    os.execute("sleep " .. tonumber(M.id))
end

return M

API很简单,先设置设置模式,GPIO.mode(id, "out/in")两种模式之一

如果为'out'即可调用GPIO.write(value)函数,写入当然id端口,如果为'in'模式,只能调用GPIO.read()读取数值。

这里数值只能是0或1,非0即为1.

调用方式如下,这个存在一个可忽略的问题,一旦调用mode,数值将被置为默认数值,即0:

  #!/usr/bin/lua
x=require("gpio")
print("Please input io id =>")
id = io.read("*num")
x.mode(id, "out")-- 设置io的模式为输入还是输出 [in/out]
function readGPIO(id)
    value = x.read()
    print("read data from => `"..id.."` =>"..value)
end
function writeGPIO(id, data)
    x.write(data)
    print("write data to => `"..id.."` =>"..data)
end

count=1
repeat
    count=count+1
    print("Please input value =>")
    data = io.read("*num")
    writeGPIO(id, data)
    readGPIO(id)
until count>3



0x05.WRTnode获取系统信息

其实获取系统信息不属于WRTnode范围,因为这部分主要是调用Linux Shell获取系统信息,做个反馈。

这里我也写了个python脚本,主要检查系统信息,这个脚本在树莓派那里面也有: http://homeway.me/2014/10/09/raspberry-the-current-status-and-data/

这里我做了部分修改,添加系统ip、连接的ssid等信息:

  #!/usr/bin/python
'''
    @author homeway
    @version 15.04.29
    @link http://homeway.me
    @function python get OpenWRT system info
'''
import os
# Return CPU temperature as a character string                                     
def getCPUtemperature():
    res = os.popen('vcgencmd measure_temp').readline()
    return(res.replace("temp=","").replace("'C\n",""))
# Return RAM information (unit=kb) in a list                                      
# Index 0: total RAM                                                              
# Index 1: used RAM                                                                
# Index 2: free RAM                                                                
def getRAMinfo():
    p = os.popen('free')
    i = 0
    while 1:
        i = i + 1
        line = p.readline()
        if i==2:
            return(line.split()[1:4])
# Return % of CPU used by user as a character string                               
def getCPUuse():
    return(str(os.popen("top -n1 | awk '/Cpu\(s\):/ {print $2}'").readline().strip()))

# Return information about disk space as a list (unit included)                    
# Index 0: total disk space                                                        
# Index 1: used disk space                                                        
# Index 2: remaining disk space                                                    
# Index 3: percentage of disk used                                                 
def getDiskSpace():
    p = os.popen("df -h /")
    i = 0
    while 1:
        i = i +1
        line = p.readline()
        if i==2:
            return(line.split()[1:5])
def getSystem():
    p = os.popen("uname -amnrspv")
    while 1:
        line = p.readline()
        return(line)
def getExtranetIp():
    p = os.popen('wget "http://www.ip138.com/ips1388.asp" -q -O - | sed -nr \'s/.*\[(([0-9]+\.){3}[0-9]+)\].*/\1/p\'')
    while 1:
        line = p.readline()
        print line
        return(line)
def getIntranetIp():
    p = os.popen('ifconfig apcli0 | grep inet\ addr')
    while 1:
        line = p.readline()
        return(line)
def getSsid():
    p = os.popen('uci get wireless.@wifi-iface[0].ApCliSsid')
    while 1:
        line = p.readline()
        return(line)
# CPU informatiom
CPU_temp = getCPUtemperature()
CPU_usage = getCPUuse()
# RAM information
# Output is in kb, here I convert it in Mb for readability
RAM_stats = getRAMinfo()
RAM_total = round(int(RAM_stats[0]) / 1000,1)
RAM_used = round(int(RAM_stats[1]) / 1000,1)
RAM_free = round(int(RAM_stats[2]) / 1000,1)
# Disk information
DISK_stats = getDiskSpace()
DISK_total = DISK_stats[0]
DISK_used = DISK_stats[1]
DISK_perc = DISK_stats[3]
# system info
SYSTEM_info = getSystem()
# NET infomation
NET_extranet_ip = getExtranetIp()
NET_internet_ip = getIntranetIp().lstrip('')
NET_connect_ssid = getSsid()

if __name__ == '__main__':
    print('-------------------------------------------')
    print("System info ="+str(SYSTEM_info))
    print('-------------------------------------------')
    print('RAM Total = '+str(RAM_total)+' MB')
    print('RAM Used = '+str(RAM_used)+' MB')
    print('RAM Free = '+str(RAM_free)+' MB')
    print('-------------------------------------------')
    print('DISK Total Space = '+str(DISK_total)+'B')
    print('DISK Used Space = '+str(DISK_used)+'B')
    print('DISK Used Percentage = '+str(DISK_perc))
    print('-------------------------------------------')
    print('NET Extranet Ip ='+str(NET_extranet_ip))
    print('NET Connect Ssid ='+str(NET_connect_ssid))
    print('NET Internet Wan Ip ='+str(NET_internet_ip))

直接调用 python sysinfo.py:

系统信息



0x06.WRTnode发送邮件

好了,系统信息有了,GPIO信息有了,接下来就试试发送邮件了。

发送邮件3中法案都可以,Lua,Python,Shell,找了找资料,Python写了,但是缺少了一个包,Lua缺少Luasocket模块,Shell要安装模块。

最后,懵了,全都要依赖,尼玛,看了看,好像Lua安装个Luasocket最简单,一个包轻松: http://see.sl088.com/wiki/Luasocket

安装也不难,接下来就写写吧。

Lua发送邮件源码模块,设置文件名为 email.lua

  #!/usr/bin/lua
--[[
Copyright 2015 http://homeway.me
@author homeway
@version 15.04.29
@link http://homeway.me
@function lua email module
-- ]]--
local smtp = require("socket.smtp")
local M ={}
M.user = {["from"]="", ["to"]="", ["password"]=""}
M.mail = {["subject"]="", ["body"]=""}
M.sys = {["server"]=""}
M.set = function(data)
    M.user = data.user
    M.mail = data.mail
    M.sys = data.sys    
end
M.send = function()
    rcpt = {
        M.user["to"]
    }
    mesgt = {
        headers = {
            from = M.user["from"],
            to = M.user["to"], --收件人
            cc = "", --抄送 
            subject = M.mail["subject"] --主题
        },
        body = M.mail["body"]
    }
    r, e = smtp.send{
        from = M.user["from"],
        rcpt = rcpt,
        source = smtp.message(mesgt),
        server = M.sys["server"],
        port = M.sys["port"],
        user = M.user["from"],
        password = M.user["password"],
    }
    if not r then
        print(e)
    else
        print("send ok!")
    end
end
return M

下面是调用方式:

  #!/usr/bin/lua
local mail = require("email")
local data = {}
data.user = {["from"]="[email protected]", ["to"]="[email protected]", ["password"]="password"}
data.mail = {["subject"]="测试邮件模块", ["body"]="这是主体内容..."}
data.sys = {["server"]="smtp.gmail.com", ["port"]=587}

mail.set(data)
mail.send()

测试下,是可以接收到邮件的,注意GFW,还是别用非法gmail好了,别等半天收不到。



0x07.重要的东西放后面

嗯!看到这里,估计菊花也有点疼了,再看最后一点看完就擦洗擦洗去吧。

最后就是,设置定时器,让路由器定时发送系统信息给指定邮箱。

嗯...定时器,Linux的一个模块crontab命令,看看功能吧 crontab --help

关于定时器语法,看看这里吧 http://kvz.io/blog/2007/07/29/schedule-tasks-on-linux-using-crontab/

这里,我只做简单地,每隔10分钟发送一次系统信息给我邮箱。

具体怎么做,去下载这个脚本吧: https://github.com/grasses/OpenWRT-Util/blob/master/lua/crontab.lua

我的目录是这样的,用户是root:

  ~|--script
    |--schedule
    |--send
|--log
    |--sys.log
    |--crontab.log

先开一个定时器,定时跑Lua,Lua调用python读取系统信息,生成日志文件,Lua读取日志文件,发送邮箱。

how to use:
step1: configure you email information in this script
step2: mkdir /root/log && mkdir /root/script
step3: mv /path/to/crontab.lua /root/script/send
step4: chmod +x /root/script/send
step5: echo 10,20,30,40,50 * * * * /root/script/send > /root/script/schedule
step6: crontab /root/script/schedule

东西有点多,都是散乱的部件,这篇主要介绍细节信息,接下来会做大得模块。

如果打通路由器,各种嵌入式开发的联网问题就都解决了,所以路由器系统还是很重要的。




本文出自 夏日小草,转载请注明出处: http://homeway.me/2015/04/29/openwrt-develop-base-util/

by 小草

2015-04-30 23:59:20

相关 [openwrt 路由器 开发] 推荐:

OpenWrt路由器开发

- - SegmentFault 最新的文章
第一次尝试开发路由器,发现并不是想象中那么难,和普通嵌入式开发一样,也是一块ARM板刷上Linux系统. OpenWrt有很多好用的软件,附带流量监测. OpenWrt主要开发语言为Python、Lua、Shell,还可以做深入研究写ipk软件包. 写了几个脚本,主要实现了openwrt下面GPIO控制、系统信息获取、wifi扫描器、定时发送邮件系统报警等功能,下面会介绍.

智能路由器后面的英雄OpenWRT

- - 钛媒体网
【文/搜狐IT 丁丁】小米日前正式推出了小米 路由器,在业界又一次引发了关于“抢占客厅”讨论. 这两款小米路由使用的miWiFi系统,不出所料是基于开源OpenWRT(OpenWRT也基于Linux开发)系统的定制版本. 360安全路由360SOS,是与硬件厂商共同基于开源Linux系统的定制版本.

OpenWrt——适用于路由器的Linux系统

- - CSDN博客互联网推荐文章
好吧, OpenWrt是什么. 它是一个适用于路由器的Linux发行版. 和其他Linux发行版一样,它也内置了 包管理工具,你可以从一个软件仓库里直接安装软件. OpenWrt可以用在所有需要嵌入式Linux的地方,它有众多功能,比如SSH服务器,VPN,流量整形服务,甚至是BitTorrent客户端.

OpenWRT+Shadowsocks科学上网教程

- - 细节的力量
本文中将会出现以下密码概念,请先准备:. 1.原厂路由器管理用户名密码,一般印在路由背面贴纸上,若已修改请使用修改后的密码或复位路由使用默认用户名密码. 2.路由器型号一般印在路由背面贴纸上,若未发现请联系销售给你路由器的商家. 3.宽带拨号用户名密码,一般在宽带账号开通单上,若不记得请联系当地接入商索取或修改.

OpenWRT 路由系统上抓包

- - CSDN博客研发管理推荐文章
做路由器开发,难免会遇到抓包的情况,但是抓包需要有Hub或者无线抓包网卡,调试无线问题,且目前手中没有无线抓包网卡,怎么办. 那不能分析无线连接建立的过程,我们就来分析下,其传输的数据,肯定是从ra0无线接口来进行了. 编译tcpdump.ipk, libpcap.ipk并且安装到OpenWRT系统中.

为何OpenWrt能在这十年里脱颖而出?

- - 雷锋网
【编者按】本文首发于微信公众账号“WRTnode”. 如果不是为了写这篇文章,笔者还真没意识到OpenWrt这个项目已经10年了. 在这个重新强调人工智能、机器学习,重新重视物理机械交互的新兴智能机器人的时代,我们有理由相信因为其纯正的Linux味道,小型化、亲近物理交互的特征,身为Linux社区与物理交互的最佳桥梁,OpenWrt会迎来新一轮的发展.

WHR-G300N V2 上使用 OpenWrt 构建 WDS 无线网络扩展

- - LinuxTOY
Buffalo WHR-G300N V2 的硬件和 WHR-G301 一样,所以可以直接使用针对它的固件. 若是还没有在 Buffalo WHR-G300N V2 刷入 OpenWrt 或者更新至 15.05 的话,可以参照下面的方式操作:. 前往 OpenWrt 官网下载 WHR-G301 的固件: 从官方固件升级 或者.

软件路由器破速度记录

- flypen - 弯曲评论
韩国的研究人员们建立了一个由端台式电脑组件组成的网络路由器,可以以创记录的速度传输数据. 来自韩国高等科技研究院的团队创造的这款路由器,传输数据的 速度是每秒40千兆比特(gigabits ),比类似装置的前纪录快出许多倍. 研究人员们使用的技术可能会带来很多方面的突破,包括在高性能路由器中使用廉价的芯片——如英特尔和Nvidia制造 的——以代替定制的硬件.

有线+无线路由器设置

- - 博客园_iTech's Blog
有线路由器已经连接外网,新购买了无线路由器来扩充网络接口,且支持无线. 路由器的默认地址有可能为192.168.0.1 或者 192.168.1.1,用户名和密码也一般为admin:admin或admin+空. 以下假设有线路由器的IP为192.168.0.1. 有线路由器LAN口出来的网线连接无线路由器的WAN口,计算机再通过无线网络配置进行上网,无线路由器起到路由器的功能.

交换机和路由器的区别

- - CSDN博客互联网推荐文章
       交换机,又叫做交换式集线器,可以简单的理解为把一些电脑连接在一起组成一个局域网. 而路由器和交换机的区别很明显,它的作用在于连接不同的网段并且找到网络中数据传输最合适的路径,但二者也并不是完全无联系的. 下面来为大家解释交换机和路由器的区别. 路由器和交换机的区别一:交换机是一根网线上网,但是大家上网是分别拨号,各自使用自己的宽带,大家上网没有影响.