Drive.google.com/drive/folders/1ahbeoEHkjxoo4NV1wReOmpoRWbl448z-
1.Tornado简介
Tornado一款使用 Python 编写的,相对简单的 非阻塞式 Web 服务器,它是非阻塞式服务器,而且速度相当快。得利于其 非阻塞的方式和对 epoll 的运用,Tornado 每秒可以处理数以千计的连接,因此 Tornado 是实时 Web 服务的一个 理想框架。
官方网站:http://www.tornadoweb.cn
官方文档:http://www.tornadoweb.cn/documentation
整个文档就一个网页,把http服务器常用的功能都讲述了一遍,如果有编程基础,应该很快就能上手。
2.Tornado安装
方式1:pip 安装:
sudo pip install tornado
方式2:源代码安装:
wget https://pypi.python.org/packages/source/t/tornado/tornado-4.3.tar.gz
tar xvzf tornado-4.3.tar.gz
cd tornado-4.3
python setup.py build
sudo python setup.py install
二、基本原理
借用Tornado官方的Hello World例子:
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") application = tornado.web.Application([ (r"/", MainHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.instance().start()
大致的思路是:通过Tornado开启http端口侦听,预设好路由规则,当有请求符合路由规则时,调用对应的Handler进行处理,这也是大部分Web服务器的处理方式。支持get和post请求。
扩展一下,利用Tornado搭建一个http服务器,上面放一个网页,网页端传入需要控制的GPIO针脚编号和状态,服务器端接收到传入的参数,做相应的处理,即可实现控制GPIO针脚电平的输出了。
三、实现步骤
1.前端html页面
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>树莓派Web控制中心</title> <script src="static/js/jquery-3.2.1.min.js" type="text/javascript"></script> <script src="static/js/bootstrap.min.js" type="text/javascript"></script> <link href="static/css/bootstrap.css" rel="stylesheet" type="text/css" /> <link href="static/css/font-awesome-4.7.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /> <style type="text/css"> .page-header { margin: 20px 0; border-bottom: 1px solid #eee; padding-bottom: 0; text-align: center; } .btn-item { text-align: center; } i { margin-right: 3px; display: inline-block; } h1 { text-align: center; } .tip { font-weight: bold; color: black; } .lead { font-size: small; } .gpio-item { text-align: center; } .btn-gnd, .btn-gpio { padding: 10px 5px; margin-bottom: 5px; 100%; font-size: small; } .gpio .row { margin-top: 5px; } </style> </head> <body> <div class="container"> <div class="page-header"> <h3> 树莓派Web控制中心</h3> <p class="lead"> 用于控制连接到树莓派的各种传感器 </p> </div> <div class="panel panel-default"> <div class="panel-heading"> 设备</div> <div class="panel-body"> <div class="row"> <div class="col-xs-3 btn-item"> </div> <div class="col-xs-3 btn-item"> <a class="btn btn-danger btn-trigger"><i class="fa fa-power-off"></i>关机</a> </div> <div class="col-xs-3 btn-item"> <a class="btn btn-primary btn-trigger"><i class="fa fa-refresh"></i>重启</a> </div> <div class="col-xs-3 btn-item"> </div> <script type="text/javascript"> var url = "/"; $(function () { $(".btn-trigger").click(function () { var text = $(this).text().replace(/ /g, "").replace(/ /g, "").replace(/ /g, "").replace(/ /g, ""); var cmd = ""; switch (text) { case "关机": cmd = "sudo shutdown -h now"; break; case "重启": cmd = "sudo reboot"; break; } if (confirm("确定要执行该命令吗?")) { $.ajax({ type: "POST", url: url, data: { action: "run-shell-cmd", cmd: cmd }, success: function (result) { //$(".tip").html(result); } }); } }); }); </script> </div> </div> </div> <div class="panel panel-default"> <div class="panel-heading"> GPIO (蓝色->低电平,红色->高电平)</div> <div class="panel-body gpio"> <div class="row"> <div class="col-xs-6 gpio-item"> 左侧 </div> <div class="col-xs-6 gpio-item"> 右侧 </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (9) 左05</button> </div> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (6) 右03</button> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="17">17 (11) 左06</a> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="18">18 (12) 右06</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="27">27 (13) 左07</a> </div> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (14) 右07</button> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="22">22 (15) 左08</a> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="23">23 (16) 右08</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (25) 左13</button> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="24">24 (18) 右09</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="5">05 (29) 左15</a> </div> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (20) 右10</button> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="6">06 (31) 左16</a> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="25">25 (22) 右11</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="13">13 (33) 左17</a> </div> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (30) 右15</button> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="19">19 (35) 左18</a> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="12">12 (32) 右16</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="26">26 (37) 左19</a> </div> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (34) 右17</button> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="20">20 (37) 右19</a> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="16">16 (36) 右18</a> </div> </div> <div class="row"> <div class="col-xs-6 gpio-item"> <button disabled="disabled" class="btn btn-info btn-gnd"> GND (39) 右20</button> </div> <div class="col-xs-6 gpio-item"> <a class="btn btn-primary btn-gpio" pin="21">21 (40) 右20</a> </div> </div> <script type="text/javascript"> $(function () { $(".btn-gpio").click(function () { var gpio = $(this).attr("pin"); if ($(this).hasClass("btn-danger")) { $(this).removeClass("btn-danger").addClass("btn-primary"); } else { $(this).removeClass("btn-primary").addClass("btn-danger"); } var status = $(this).hasClass("btn-danger") ? 1 : 0; $.ajax({ type: "POST", url: url, data: { action: "set-gpio-pin", pin: gpio, status: status }, success: function (result) { //$(".tip").html(result); } }); }); }) </script> </div> </div> </div> </body> </html>
2.Python脚本
#coding: utf8 import sys import RPi.GPIO as GPIO import time import os import tornado.ioloop import tornado.web import tornado.httpserver import tornado.options from tornado.options import define,options #初始化 def init(): GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) #设置GPIO针脚电平输出 def SetPinStatus(pin,status): GPIO.cleanup(int(pin)) GPIO.setup(int(pin),GPIO.OUT) if(int(status)==0): GPIO.output(int(pin),GPIO.LOW) else: GPIO.output(int(pin),GPIO.HIGH) #路由处理 class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("index.html") def post(self): init() action=self.get_argument('action') #设置GPIO针脚电平输出 if(action=="set-gpio-pin"): pin = self.get_argument('pin') status = self.get_argument('status') SetPinStatus(pin,status) self.write("true") #执行shell脚本,如:关机,重启 elif(action=="run-shell-cmd"): cmd = self.get_argument('cmd') os.system(cmd) if __name__ == '__main__': #控制台输出响应结果,正式环境可以不开启 #tornado.options.parse_command_line() settings={ "static_path":os.path.join(os.path.dirname(__file__),"static") } app = tornado.web.Application( handlers=[ (r"/",IndexHandler), (r"(apple-touch-icon.png)",tornado.web.StaticFileHandler,dict(path=settings['static_path'])) ],**settings) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8020) tornado.ioloop.IOLoop.instance().start() GPIO.cleanup()
3.目录结构
4.部署调试
在终端输入:python /var/www/html/pi/gpio/gpio.py (路径为我树莓派中文件路径,实际路径以你自己的环境为准。)
如果终端没报错,此时打开浏览器,输入地址:http://localhost:8020 即可访问到页面,8020是python脚本中侦听的端口,你可以自行设置。
5.运行结果
6.源码下载
http://download.csdn.net/download/a497785609/9990088