Benutzer-Werkzeuge

Webseiten-Werkzeuge


projekt:python_fastapi

Dies ist eine alte Version des Dokuments!


Python FASTAPI

Überblick

  • Voraussetzungen
  • Software
  • Konfiguration

Details

Voraussetzungen

ENV

source ~/devel/projects/course_env/bin/activate
pip install fastapi uvicorn RPi.GPIO

Projektstruktur

cd ~/devel/course/

course_web/
└── src/
    ├── app.py
    ├── core/
    │   └── hardware.py
    └── html/
        ├── led.html
        └── temp.html

Hardware

Die Hardware, also die LED-Ampel und der Temperatursensor, wurden in den vorausgegangenen Projekten ausführlich behandelt und werden exakt so verwendet wie dort beschrieben.

Software

API

Datei:

''/home/pi/devel/projects/course_web/src/core/hardware.py''
import RPi.GPIO as GPIO
import glob
import time
 
# -----------------------------
# API-Funktionen GPIO LED Ampel
# -----------------------------
 
PIN_R = 17
PIN_Y = 27
PIN_G = 22
 
_initialized = False
 
def init():
    global _initialized
    if _initialized:
        return
 
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
 
    GPIO.setup(PIN_R, GPIO.OUT)
    GPIO.setup(PIN_Y, GPIO.OUT)
    GPIO.setup(PIN_G, GPIO.OUT)
 
    _initialized = True
 
 
def setLED(pin, value):
    GPIO.output(pin, GPIO.HIGH if value == 1 else GPIO.LOW)
 
 
def setRedLED(value):
    setLED(PIN_R, value)
 
 
def setYellowLED(value):
    setLED(PIN_Y, value)
 
 
def setGreenLED(value):
    setLED(PIN_G, value)
 
 
def status():
    return (
        int(GPIO.input(PIN_R)),
        int(GPIO.input(PIN_Y)),
        int(GPIO.input(PIN_G)),
    )
 
 
# -----------------------------
# API-Funktionen ds18b20
# -----------------------------
 
SENSOR_TIMEOUT = 1
 
def get_sensor():
    sensors = glob.glob("/sys/bus/w1/devices/28-*")
    if not sensors:
        return None
    return sensors[0] + "/w1_slave"
 
 
def get_temperature():
    sensor_file = get_sensor()
    if sensor_file is None:
        return None
 
    start_time = time.time()
 
    while True:
        with open(sensor_file, "r") as f:
            lines = f.readlines()
 
        if lines[0].strip().endswith("YES"):
            break
 
        if time.time() - start_time > SENSOR_TIMEOUT:
            return None
 
        time.sleep(0.1)
 
    temp_line = lines[1]
    temp_str = temp_line.split("t=")[1]
    return float(temp_str) / 1000.0

3. HTML – LED

Datei: /home/pi/devel/projects/course_web/src/html/led.html

<!DOCTYPE html>
<html>
<head>
    <title>LED Ampel</title>
</head>
<body>
 
<h1>LED Ampel</h1>
 
<h2>Rot (Status: {{R}})</h2>
<a href="/led/r/1">ON</a>
<a href="/led/r/0">OFF</a>
 
<h2>Gelb (Status: {{Y}})</h2>
<a href="/led/y/1">ON</a>
<a href="/led/y/0">OFF</a>
 
<h2>Grün (Status: {{G}})</h2>
<a href="/led/g/1">ON</a>
<a href="/led/g/0">OFF</a>
 
<br><br>
<a href="/">Zurück</a>
 
</body>
</html>

HTML

Datei:

''/home/pi/devel/projects/course_web/src/html/temp.html''
<!DOCTYPE html>
<html>
<head>
    <title>Temperatur</title>
</head>
<body>
 
<h1>Temperatur</h1>
 
<p>Temperatur: {{T}} °C</p>
 
<br>
<a href="/">Zurück</a>
 
</body>
</html>

FASTAPI APP

Datei:

''/home/pi/devel/projects/course_web/src/app.py''
from fastapi import FastAPI, HTTPException
from fastapi.responses import HTMLResponse, RedirectResponse
from core import hardware
 
app = FastAPI()
 
 
@app.on_event("startup")
def startup():
    hardware.init()
 
 
def load_template(name, replacements):
    with open(f"static/{name}", "r") as f:
        html = f.read()
 
    for key, value in replacements.items():
        html = html.replace(key, str(value))
 
    return html
 
 
@app.get("/led", response_class=HTMLResponse)
def led_page():
    r, y, g = hardware.status()
    return HTMLResponse(
        load_template("led.html", {
            "{{R}}": r,
            "{{Y}}": y,
            "{{G}}": g
        })
    )
 
 
@app.get("/led/{color}/{value}")
def set_led(color: str, value: int):
 
    if value not in (0, 1):
        raise HTTPException(status_code=400)
 
    if color == "r":
        hardware.setRedLED(value)
    elif color == "y":
        hardware.setYellowLED(value)
    elif color == "g":
        hardware.setGreenLED(value)
    else:
        raise HTTPException(status_code=400)
 
    return RedirectResponse(url="/led", status_code=303)
 
 
@app.get("/temp", response_class=HTMLResponse)
def temp_page():
    t = hardware.get_temperature()
 
    if t is None:
        value = "Sensorfehler"
    else:
        value = f"{t:.2f}"
 
    return HTMLResponse(
        load_template("temp.html", {
            "{{T}}": value
        })
    )

Apache2 Startseite

Datei:

''/var/www/html/index.html''
<!DOCTYPE html>
<html>
<head>
    <title>Projekt Auswahl</title>
</head>
<body>
 
<h1>Projekt Auswahl</h1>
 
<ul>
    <li><a href="/wiki">DokuWiki</a></li>
    <li><a href="/led">LED Ampel</a></li>
    <li><a href="/temp">Temperatur</a></li>
</ul>
 
</body>
</html>

Konfiguration

Apache Proxy

ProxyPreserveHost On

ProxyPass        /led   http://127.0.0.1:8000/led
ProxyPassReverse /led   http://127.0.0.1:8000/led

ProxyPass        /temp  http://127.0.0.1:8000/temp
ProxyPassReverse /temp  http://127.0.0.1:8000/temp

Systemd

Datei:

''/etc/systemd/system/python_web.service''
[Unit]
Description=Python Web FastAPI
After=network-online.target
Wants=network-online.target

[Service]
User=pi
WorkingDirectory=/home/pi/devel/projects/course_web/src
ExecStart=/home/pi/devel/projects/course_env/bin/uvicorn app:app --host 127.0.0.1 --port 8000
Restart=always

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable python_web
sudo systemctl start python_web
projekt/python_fastapi.1771658771.txt.gz · Zuletzt geändert: von torsten.roehl