projekt:python_fastapi
Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
GPIO mit FastAPI (Websteuerung)
Ziel
- Klare Trennung: Hardware / Web / HTML
- Keine Template-Engine
- HTML als eigene Datei
- LED + DS18B20 Temperatur
- Apache bleibt Hauptserver
- Reboot-fest über systemd
- VENV: ~/devel/projects/course_env
1. Projektordner
cd /home/pi/devel/projects mkdir -p python_web/src/core mkdir -p python_web/src/static cd python_web/src/core touch __init__.py
2. VENV
source ~/devel/projects/course_env/bin/activate pip install fastapi uvicorn RPi.GPIO which uvicorn
Erwartet:
/home/pi/devel/projects/course_env/bin/uvicorn
3. Hardware-Schicht
Datei:
/home/pi/devel/projects/python_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): if value == 1: GPIO.output(pin, GPIO.HIGH) else: GPIO.output(pin, 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(): r = GPIO.input(PIN_R) y = GPIO.input(PIN_Y) g = GPIO.input(PIN_G) return r, y, g def cleanup(): GPIO.cleanup() # ----------------------------- # API-Funktionen ds18b20 # ----------------------------- SENSOR_TIMEOUT = 1 # Sekunden def is_sensor(): sensors = glob.glob("/sys/bus/w1/devices/28-*") return len(sensors) > 0 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
4. HTML
Datei:
/home/pi/devel/projects/python_web/src/static/index.html
<!DOCTYPE html> <html> <head> <title>Python Web</title> </head> <body> <h1>LED Steuerung</h1> <h2>Rot (Status: {{R}})</h2> <a href="/web/led/r/1">ON</a> <a href="/web/led/r/0">OFF</a> <h2>Gelb (Status: {{Y}})</h2> <a href="/web/led/y/1">ON</a> <a href="/web/led/y/0">OFF</a> <h2>Grün (Status: {{G}})</h2> <a href="/web/led/g/1">ON</a> <a href="/web/led/g/0">OFF</a> <hr> <h1>Temperatur</h1> <p>Temperatur: {{T}} °C</p> </body> </html>
5. Web-Schicht
Datei:
/home/pi/devel/projects/python_web/src/app.py
from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse, RedirectResponse from core import hardware app = FastAPI(root_path="/web") @app.on_event("startup") def startup(): hardware.init() def load_html(r, y, g, t): with open("static/index.html", "r") as f: html = f.read() html = html.replace("{{R}}", str(r)) html = html.replace("{{Y}}", str(y)) html = html.replace("{{G}}", str(g)) if t is None: html = html.replace("{{T}}", "Sensorfehler") else: html = html.replace("{{T}}", f"{t:.2f}") return html @app.get("/", response_class=HTMLResponse) def index(): r, y, g = hardware.status() t = hardware.get_temperature() return HTMLResponse(load_html(r, y, g, t)) @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="/web", status_code=303)
6. Apache
In:
/etc/apache2/sites-available/000-default.conf
ProxyPreserveHost On ProxyPass /web http://127.0.0.1:8000/ ProxyPassReverse /web http://127.0.0.1:8000/
sudo a2enmod proxy sudo a2enmod proxy_http sudo systemctl reload apache2
7. 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/python_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
8. Test
9. Reboot
sudo reboot
Reboot-fest. Hardware wird einmal initialisiert. Struktur entspricht den ursprünglichen Prinzipien.
projekt/python_fastapi.1771613595.txt.gz · Zuletzt geändert: von torsten.roehl
