【问题标题】:Refreshing GPIO Pin Status Automatically On a Flask Server在 Flask 服务器上自动刷新 GPIO 引脚状态
【发布时间】:2022-01-03 18:48:26
【问题描述】:

我正在使用带有 Flask 服务器的 Raspberry Pi 构建车库控制器。一切都按预期工作,除了我仍然需要弄清楚如何自动更新 GPIO 引脚状态并刷新 html 页面以自动打开/关闭。

我在下面附上了我的代码,任何帮助将不胜感激。

您现在看到的刷新状态按钮是我创建的用于刷新页面的解决方法。但我正在寻找可以根据 PIN 状态更改自动刷新页面的内容。

烧瓶代码

import time
from datetime import datetime
from flask import Flask, render_template, request
import RPi.GPIO as GPIO
import logging

app = Flask(__name__)

GPIO.setmode(GPIO.BOARD)
GPIO.setup(16, GPIO.IN, GPIO.PUD_UP)
GPIO.setup(7, GPIO.OUT)


@app.route("/", methods=['GET', 'POST'])
def Status():
    if GPIO.input(16) == GPIO.LOW:
        app.logger.info('Gate is Closed')
        return render_template('Closed.html')
    elif GPIO.input(16) == GPIO.HIGH:
        app.logger.info('Gate is Open')
        return render_template('Open.html')


@app.route("/Open", methods=['GET', 'POST'])
def Open():
    GPIO.output(7, True)
    app.logger.info('Gate is Opening')
    return render_template('Open.html')


@app.route("/Closed", methods=['GET', 'POST'])
def Closed():
    GPIO.output(7, False)
    app.logger.info('Gate is Closing')
    return render_template('Closed.html')


if __name__ == "__main__":
    app.run()

关闭的 HTML 代码

<html>

<head>
    <meta name="viewport" content="width=device-width">
    <!--<meta http-equiv="refresh" 
        content="1; url = /" />-->
    <!--<link rel="stylesheet" type="text/css" href="stylesheet.css">-->
    <style>
        .switch {
          vertical-align: middle;
          position: relative;
          display: inline-block;
          width: 60px;
          height: 34px;
        }
        
        .switch input { 
          opacity: 0;
          width: 0;
          height: 0;
        }
        
        .slider {
          position: absolute;
          cursor: pointer;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background-color: #ccc;
          -webkit-transition: .4s;
          transition: .4s;
        }
        
        .slider:before {
          position: absolute;
          content: "";
          height: 26px;
          width: 26px;
          left: 4px;
          bottom: 4px;
          background-color: white;
          -webkit-transition: .4s;
          transition: .4s;
        }
        
        input:checked + .slider {
          background-color: #2196F3;
        }
        
        input:focus + .slider {
          box-shadow: 0 0 1px #2196F3;
        }
        
        input:checked + .slider:before {
          -webkit-transform: translateX(26px);
          -ms-transform: translateX(26px);
          transform: translateX(26px);
        }
        
        /* Rounded sliders */
        .slider.round {
          border-radius: 34px;
        }
        
        .slider.round:before {
          border-radius: 50%;
        }

        .button {
            color: #fff !important;
            text-transform: uppercase;
            text-decoration: none;
            background: #000;
            padding: 10px;
            border-radius: 5px;
            display: inline-block;
            border: none;
            transition: all 0.4s ease 0s;
        }

        .sliderWrapper{display: inline-block;margin:24px 24px 24px 24px;position:relative;}
        .sliderWrapper div{display: inline-block;line-height:60px;}
        </style>

      <script type="text/javascript">
            setTimeout (
                function() { window.location.reload(); },
                500
            )
      </script>
</head>

<body bgcolor="#ff5c33">
    <center>
        <br>
        <h1>Gate Control</h1>
        <br><br> <br> <br>

        <h3>Use the toggle to Open/Close the Relay!</h3>
        <form action="/Open">
          <div class="sliderWrapper">
            <div>Close&nbsp;&nbsp;</div>
            <label class="switch">
                <input type="checkbox" onclick="submit();">
                <span class="slider round"></span>
            </label>
            <div>&nbsp;&nbsp;Open&nbsp;&nbsp;</div>
          </div>
        </form>
        <div class="refresh">
        <br><br>

        <h3>Use the button to Refresh the Page/Status!</h3>
        <a href="/" class="button">Refresh</a>
        </div>
        
    </center>
</body>

</html>

用于打开的 HTML 代码

<html>

<head>
    <meta name="viewport" content="width=device-width">
    <!--<meta http-equiv="refresh" 
        content="1; url = /" />-->
    <!--<link rel="stylesheet" type="text/css" href="stylesheet.css">-->
    <style>
        .switch {
          vertical-align: middle;
          position: relative;
          display: inline-block;
          width: 60px;
          height: 34px;
        }
        
        .switch input { 
          opacity: 0;
          width: 0;
          height: 0;
        }
        
        .slider {
          position: absolute;
          cursor: pointer;
          top: 0;
          left: 0;
          right: 0;
          bottom: 0;
          background-color: #ccc;
          -webkit-transition: .4s;
          transition: .4s;
        }
        
        .slider:before {
          position: absolute;
          content: "";
          height: 26px;
          width: 26px;
          left: 4px;
          bottom: 4px;
          background-color: white;
          -webkit-transition: .4s;
          transition: .4s;
        }
        
        input:checked + .slider {
          background-color: #2196F3;
        }
        
        input:focus + .slider {
          box-shadow: 0 0 1px #2196F3;
        }
        
        input:checked + .slider:before {
          -webkit-transform: translateX(26px);
          -ms-transform: translateX(26px);
          transform: translateX(26px);
        }
        
        /* Rounded sliders */
        .slider.round {
          border-radius: 34px;
        }
        
        .slider.round:before {
          border-radius: 50%;
        }

        .button {
            color: #fff !important;
            text-transform: uppercase;
            text-decoration: none;
            background: #000;
            padding: 10px;
            border-radius: 5px;
            display: inline-block;
            border: none;
            transition: all 0.4s ease 0s;
        }
        .sliderWrapper{display: inline-block;margin:24px 24px 24px 24px;position:relative;}
        .sliderWrapper div{display: inline-block;line-height:60px;}
      </style>

      <script type="text/javascript">
            setTimeout (
                function() { window.location.reload(); },
                500
            )
      </script>
</head>

<body bgcolor="lightgreen">
    <center>
        <br>
        <h1>Gate Control</h1>
        <br><br> <br> <br>

        <h3>Use the toggle to Open/Close the Relay!</h3>
        <form action="/Closed">
          <div class="sliderWrapper">
            <div>Close&nbsp;&nbsp;</div>
            <label class="switch">
                <input type="checkbox" checked onclick="submit();">
                <span class="slider round"></span>
            </label>
            <div>&nbsp;&nbsp;Open&nbsp;&nbsp;</div>
          </div>
        </form>
        <div class="refresh">
        <br><br>

        <h3>Use the button to Refresh the Page/Status!</h3>
        <a href="/" class="button">Refresh</a>
        </div>
    </center>
</body>

</html>

【问题讨论】:

    标签: python html python-3.x flask raspberry-pi


    【解决方案1】:

    您正在了解 HTTP 在经典客户端服务器方式中的工作方式。

    • 您的前端客户端向您的服务器请求某些内容
    • 如果请求的资源/页面可用,服务器会做出响应。并将其发送回客户。
    • 完成

    上述请求/响应周期解释了为什么需要刷新按钮。

    过去解决此问题的一种方法是在前端运行一些 javascript/JQuery 并定期刷新页面(AJAX/长轮询),这仍然有效。

    现在还有其他方法,例如使用(网络)套接字创建一个双向通道,服务器可以在其中将数据推送到客户端。解决经典请求/响应的问题。 (以 Flask Socket IO 为例)

    这两种方法都值得研究,但定期轮询的 javascript 可能是最快的,如果不是最漂亮的修复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-03
      • 2016-09-25
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-22
      • 2014-12-26
      相关资源
      最近更新 更多