Flask - 通过网页调用和停止函数 (raspberry pi)
Flask - Calling and stopping functions via webpage (raspberry pi)
我正在尝试设置一个简单的 flask 网页来控制 运行 在 raspberry pi 上的 3d 圣诞树 运行。我已经发布了应用程序的代码和下面的模板。到目前为止,它的工作原理是我可以 运行 一个单一的功能,例如 Flicker,然后执行 Reset 或 Off 功能。但是,之后我无法调用其他函数。如果我 运行 闪烁,然后是随机或全闪,它们就会混合在一起。我的目标是能够通过重置或关闭功能完全停止 GPIO 输出,并通过网页的按钮或链接调用每个相应的功能。
app2.py
import RPi.GPIO as GPIO
import random
from random import randint
from gpiozero.tools import random_values
from flask import Flask, render_template, request
from gpiozero import LEDBoard
from time import sleep
from signal import pause
app = Flask(__name__)
GPIO.setmode(GPIO.BCM)
tree = LEDBoard(*range(2,28),pwm=True)
@app.route("/")
def home2():
return render_template("home2.html")
@app.route("/flicker/", methods=['POST', 'GET'])
def flicker():
# GPIO.cleanup()
for led in tree:
led.source_delay = random.uniform(0.1, 0.9)
led.source = random_values()
sleep(1)
pause()
return render_template("home2.html")
@app.route("/randomOnOff/", methods=['POST', 'GET'])
def randomOnOff():
while True:
for led in tree:
s = randint(0,1)
if (s==1):
led.on()
else:
led.off()
sleep(1)
return render_template("home2.html")
@app.route("/allFlash/", methods=['POST', 'GET'])
def allFlash():
while True:
tree.on()
sleep(1)
tree.off()
sleep(1)
return render_template("home2.html")
@app.route("/upAndDown/", methods=['POST', 'GET'])
def upAndDown():
while True:
tree.off()
order = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0]
for item in order:
tree[item].on()
sleep(0.1)
order.reverse()
sleep(0.5)
for item in order:
tree[item].off()
sleep(0.1)
return render_template("home2.html")
@app.route("/reset/", methods=['POST', 'GET'])
def tree_reset():
GPIO.cleanup()
return render_template("home2.html")
@app.route("/off/", methods=['POST', 'GET'])
def tree_off():
tree.off()
return render_template("home2.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Raspberry Pi Xmas Tree</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">Raspberry Pi Christmas Tree</h1>
<strong><nav>
<a href="/" class="button">Home</a>
<br/>
<br/>
<ul class="menu">
<form action="/flicker/" method="post">
<button name="flicker" type="submit">Flicker Lights</button>
</form>
<br/>
<form action="/randomOnOff/" method="post">
<button name="randomOnOff" type="submit">Random Lights</button>
</form>
<br/>
<form action="/allFlash/" method="post">
<button name="allFlash" type="submit">Flash All Lights</button>
</form>
<br/>
<form action="/upAndDown/" method="post">
<button name="upAndDown" type="submit">Up and Down</button>
</form>
<br/>
<form action="/reset/" method="post">
<button name="reset" type="submit">Reset</button>
</form>
<br/>
<form action="/off/" method="post">
<button name="off" type="submit">Turn Off</button>
</form>
</ul>
</nav></strong>
</div>
</header>
{% block content %}
{% endblock %}
</body>
</html>
我对如何按预期工作有点迷茫。我读过与线程和多线程相关的类似帖子,但我认为这不是问题所在。我不确定我是否错误地获取和发布了呼叫。我在模板中使用 ajax 阅读过类似的帖子,但我认为这也不是问题,因为 工作 但可能效率不高。
感谢任何帮助、见解或指导。
您好,我没有您的设置,所以无法进行全面测试。但我认为你想要一个后台循环,并使用全局状态来管理与树的交互(因为实际上只有一棵树。)
from enum import Enum
from random import randint, uniform
from threading import Thread
from time import sleep
from flask import Flask, render_template, request, redirect, url_for
from gpiozero import LEDBoard
from gpiozero.tools import random_values
import RPi.GPIO as GPIO
class TreeState(Enum):
OFF = 1
FLICKER = 2
RANDOM_ON_OFF = 3
ALL_FLASH = 4
UP_AND_DOWN = 5
TERMINATE = 6
def main_loop():
while True:
if state == TreeState.TERMINATE:
tree.off()
GPIO.cleanup()
quit()
if state == TreeState.ALL_FLASH:
tree.on()
sleep(1)
tree.off()
# to prevent you could set looping state = TreeState.OFF
# state = TreeState.OFF
if state == TreeState.RANDOM_ON_OFF:
tree.off()
for led in tree:
s = randint(0,1)
if s == 1:
led.on()
else:
led.off()
# state = TreeState.OFF
if state == TreeState.UP_AND_DOWN:
tree.off()
order = list(range(1, 25)) + [0]
for item in order:
tree[item].on()
sleep(0.1)
order.reverse()
sleep(0.5)
for item in order:
tree[item].off()
sleep(0.1)
# state = TreeState.OFF
# I have been unable to test this
if state == TreeState.FLICKER:
for led in tree:
led.source_delay = random.uniform(0.1, 0.9)
led.source = random_values()
sleep(1)
# after a second repeat the loop
sleep(1)
app = Flask(__name__)
state = TreeState.OFF
GPIO.setmode(GPIO.BCM)
tree = LEDBoard(*range(2, 28), pwm=True)
@app.route("/")
def home2():
return render_template("home2.html", state=str(state))
# post-redirect-get
@app.route("/setState/<new_state>", methods=["POST"])
def setState(new_state):
new_state = TreeState[new_state]
global state
state = new_state
return redirect(url_for('home2'))
if __name__ == "__main__":
Thread(name="backgroundLoop", target=main_loop).start()
app.run(host='0.0.0.0', port=5000, debug=True)
注意新的 POST 端点:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Raspberry Pi Xmas Tree</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">Raspberry Pi Christmas Tree</h1>
<h2 class="status">The tree is {{state}}</h2>
<strong><nav>
<a href="/" class="button">Home</a>
<br/>
<br/>
<ul class="menu">
<form action="/setState/FLICKER" method="post">
<button name="flicker" type="submit">Flicker Lights</button>
</form>
<br/>
<form action="/setState/RANDOM_ON_OFF" method="post">
<button name="randomOnOff" type="submit">Random Lights</button>
</form>
<br/>
<form action="/setState/ALL_FLASH" method="post">
<button name="allFlash" type="submit">Flash All Lights</button>
</form>
<br/>
<form action="/setState/UP_AND_DOWN" method="post">
<button name="upAndDown" type="submit">Up and Down</button>
</form>
<br/>
<form action="/setState/OFF" method="post">
<button name="reset" type="submit">Reset</button>
</form>
<br/>
<form action="/setState/TERMINATE" method="post">
<button name="off" type="submit">Shut down server</button>
</form>
</ul>
</nav></strong>
</div>
</header>
{% block content %}
{% endblock %}
</body>
</html>
我正在尝试设置一个简单的 flask 网页来控制 运行 在 raspberry pi 上的 3d 圣诞树 运行。我已经发布了应用程序的代码和下面的模板。到目前为止,它的工作原理是我可以 运行 一个单一的功能,例如 Flicker,然后执行 Reset 或 Off 功能。但是,之后我无法调用其他函数。如果我 运行 闪烁,然后是随机或全闪,它们就会混合在一起。我的目标是能够通过重置或关闭功能完全停止 GPIO 输出,并通过网页的按钮或链接调用每个相应的功能。
app2.py
import RPi.GPIO as GPIO
import random
from random import randint
from gpiozero.tools import random_values
from flask import Flask, render_template, request
from gpiozero import LEDBoard
from time import sleep
from signal import pause
app = Flask(__name__)
GPIO.setmode(GPIO.BCM)
tree = LEDBoard(*range(2,28),pwm=True)
@app.route("/")
def home2():
return render_template("home2.html")
@app.route("/flicker/", methods=['POST', 'GET'])
def flicker():
# GPIO.cleanup()
for led in tree:
led.source_delay = random.uniform(0.1, 0.9)
led.source = random_values()
sleep(1)
pause()
return render_template("home2.html")
@app.route("/randomOnOff/", methods=['POST', 'GET'])
def randomOnOff():
while True:
for led in tree:
s = randint(0,1)
if (s==1):
led.on()
else:
led.off()
sleep(1)
return render_template("home2.html")
@app.route("/allFlash/", methods=['POST', 'GET'])
def allFlash():
while True:
tree.on()
sleep(1)
tree.off()
sleep(1)
return render_template("home2.html")
@app.route("/upAndDown/", methods=['POST', 'GET'])
def upAndDown():
while True:
tree.off()
order = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,0]
for item in order:
tree[item].on()
sleep(0.1)
order.reverse()
sleep(0.5)
for item in order:
tree[item].off()
sleep(0.1)
return render_template("home2.html")
@app.route("/reset/", methods=['POST', 'GET'])
def tree_reset():
GPIO.cleanup()
return render_template("home2.html")
@app.route("/off/", methods=['POST', 'GET'])
def tree_off():
tree.off()
return render_template("home2.html")
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Raspberry Pi Xmas Tree</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">Raspberry Pi Christmas Tree</h1>
<strong><nav>
<a href="/" class="button">Home</a>
<br/>
<br/>
<ul class="menu">
<form action="/flicker/" method="post">
<button name="flicker" type="submit">Flicker Lights</button>
</form>
<br/>
<form action="/randomOnOff/" method="post">
<button name="randomOnOff" type="submit">Random Lights</button>
</form>
<br/>
<form action="/allFlash/" method="post">
<button name="allFlash" type="submit">Flash All Lights</button>
</form>
<br/>
<form action="/upAndDown/" method="post">
<button name="upAndDown" type="submit">Up and Down</button>
</form>
<br/>
<form action="/reset/" method="post">
<button name="reset" type="submit">Reset</button>
</form>
<br/>
<form action="/off/" method="post">
<button name="off" type="submit">Turn Off</button>
</form>
</ul>
</nav></strong>
</div>
</header>
{% block content %}
{% endblock %}
</body>
</html>
我对如何按预期工作有点迷茫。我读过与线程和多线程相关的类似帖子,但我认为这不是问题所在。我不确定我是否错误地获取和发布了呼叫。我在模板中使用 ajax 阅读过类似的帖子,但我认为这也不是问题,因为 工作 但可能效率不高。
感谢任何帮助、见解或指导。
您好,我没有您的设置,所以无法进行全面测试。但我认为你想要一个后台循环,并使用全局状态来管理与树的交互(因为实际上只有一棵树。)
from enum import Enum
from random import randint, uniform
from threading import Thread
from time import sleep
from flask import Flask, render_template, request, redirect, url_for
from gpiozero import LEDBoard
from gpiozero.tools import random_values
import RPi.GPIO as GPIO
class TreeState(Enum):
OFF = 1
FLICKER = 2
RANDOM_ON_OFF = 3
ALL_FLASH = 4
UP_AND_DOWN = 5
TERMINATE = 6
def main_loop():
while True:
if state == TreeState.TERMINATE:
tree.off()
GPIO.cleanup()
quit()
if state == TreeState.ALL_FLASH:
tree.on()
sleep(1)
tree.off()
# to prevent you could set looping state = TreeState.OFF
# state = TreeState.OFF
if state == TreeState.RANDOM_ON_OFF:
tree.off()
for led in tree:
s = randint(0,1)
if s == 1:
led.on()
else:
led.off()
# state = TreeState.OFF
if state == TreeState.UP_AND_DOWN:
tree.off()
order = list(range(1, 25)) + [0]
for item in order:
tree[item].on()
sleep(0.1)
order.reverse()
sleep(0.5)
for item in order:
tree[item].off()
sleep(0.1)
# state = TreeState.OFF
# I have been unable to test this
if state == TreeState.FLICKER:
for led in tree:
led.source_delay = random.uniform(0.1, 0.9)
led.source = random_values()
sleep(1)
# after a second repeat the loop
sleep(1)
app = Flask(__name__)
state = TreeState.OFF
GPIO.setmode(GPIO.BCM)
tree = LEDBoard(*range(2, 28), pwm=True)
@app.route("/")
def home2():
return render_template("home2.html", state=str(state))
# post-redirect-get
@app.route("/setState/<new_state>", methods=["POST"])
def setState(new_state):
new_state = TreeState[new_state]
global state
state = new_state
return redirect(url_for('home2'))
if __name__ == "__main__":
Thread(name="backgroundLoop", target=main_loop).start()
app.run(host='0.0.0.0', port=5000, debug=True)
注意新的 POST 端点:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>Raspberry Pi Xmas Tree</title>
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
</head>
<body>
<header>
<div class="container">
<h1 class="logo">Raspberry Pi Christmas Tree</h1>
<h2 class="status">The tree is {{state}}</h2>
<strong><nav>
<a href="/" class="button">Home</a>
<br/>
<br/>
<ul class="menu">
<form action="/setState/FLICKER" method="post">
<button name="flicker" type="submit">Flicker Lights</button>
</form>
<br/>
<form action="/setState/RANDOM_ON_OFF" method="post">
<button name="randomOnOff" type="submit">Random Lights</button>
</form>
<br/>
<form action="/setState/ALL_FLASH" method="post">
<button name="allFlash" type="submit">Flash All Lights</button>
</form>
<br/>
<form action="/setState/UP_AND_DOWN" method="post">
<button name="upAndDown" type="submit">Up and Down</button>
</form>
<br/>
<form action="/setState/OFF" method="post">
<button name="reset" type="submit">Reset</button>
</form>
<br/>
<form action="/setState/TERMINATE" method="post">
<button name="off" type="submit">Shut down server</button>
</form>
</ul>
</nav></strong>
</div>
</header>
{% block content %}
{% endblock %}
</body>
</html>