• 20-2 树莓派搭建服务器 Tornado Web服务器


    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

  • 相关阅读:
    【Unity3D】3D游戏学习
    风投小观之敢于冒高风险,方能收高回报
    同步请求和异步请求的区别
    IOS开发UI基础学习-------总结
    我的哲学观-1000字例文
    Uva11292--------------(The Dragon of Loowater)勇者斗恶龙 (排序后贪心)
    学习笔记之vector向量容器
    欧几里得算法求最大公约数+最小公倍数
    二叉树的遍历规则(前序遍历、后序遍历、中序遍历)
    《winform窗体应用程序》----------简易记事本
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/11267389.html
Copyright © 2020-2023  润新知