转载

OpenWrt路由器开发

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环境上开发的,主要包含了:

  • luci(WRTnode自带,非WRTnode用opkg安装即可)

  • python(WRTnode自带,非WRTnode用opkg安装即可)

  • luasocket( http://see.sl088.com/wiki/Luasocket )

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

0x04.WRTnode控制GPIO

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

OpenWrt路由器开发

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 :

OpenWrt路由器开发

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"]="sender@gmail.com", ["to"]="receiver@gmail.com", ["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

正文到此结束
Loading...