projekt:python_fastapi
Dies ist eine alte Version des Dokuments!
Inhaltsverzeichnis
GPIO mit FastAPI (Websteuerung)
GPIO Web – didaktisch sauber (FastAPI + Apache + systemd)
Ziel:
- Klare Trennung: Hardware / Web / HTML
- Keine Template-Engine
- HTML als eigene Datei
- Einmalige Initialisierung
- Reboot-fest über systemd
- VENV: ~/devel/projects/course_env
1. PROJEKTORDNER
cd /home/pi/devel/projects mkdir -p gpio_web/src/core mkdir -p gpio_web/src/static cd gpio_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/gpio_web/src/core/hardware.py
""" Hardware-Schicht. Kapselt alle GPIO-Zugriffe. """ import RPi.GPIO as GPIO PIN_R = 17 PIN_Y = 27 PIN_G = 22 _initialized = False def init(): """ Wird genau einmal beim Start des Servers aufgerufen. """ 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 setRedLED(value: int): GPIO.output(PIN_R, GPIO.HIGH if value == 1 else GPIO.LOW) def setYellowLED(value: int): GPIO.output(PIN_Y, GPIO.HIGH if value == 1 else GPIO.LOW) def setGreenLED(value: int): GPIO.output(PIN_G, GPIO.HIGH if value == 1 else GPIO.LOW) def status(): """ Liefert aktuellen Hardware-Zustand. """ return ( int(GPIO.input(PIN_R)), int(GPIO.input(PIN_Y)), int(GPIO.input(PIN_G)), )
4. HTML (GETRENNT, KEIN TEMPLATE-FRAMEWORK)
Datei:
/home/pi/devel/projects/gpio_web/src/static/index.html
<!DOCTYPE html> <html> <head> <title>GPIO 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> </body> </html>
5. WEB-SCHICHT
Datei:
/home/pi/devel/projects/gpio_web/src/app.py
""" Web-Schicht. Verantwortlich für HTTP. Keine GPIO-Logik hier. """ 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): 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)) return html @app.get("/", response_class=HTMLResponse) def index(): r, y, g = hardware.status() return HTMLResponse(load_html(r, y, g)) @app.get("/led/{color}/{value}") def set_led(color: str, value: int): if value not in (0, 1): raise HTTPException(status_code=400, detail="Value must be 0 or 1") if color == "r": hardware.setRedLED(value) elif color == "y": hardware.setYellowLED(value) elif color == "g": hardware.setGreenLED(value) else: raise HTTPException(status_code=400, detail="Invalid color") return RedirectResponse(url="/web", status_code=303)
6. APACHE
sudo a2enmod proxy sudo a2enmod proxy_http sudo systemctl restart apache2
In:
/etc/apache2/sites-available/000-default.conf
Einfügen:
ProxyPreserveHost On ProxyPass /web http://127.0.0.1:8000/ ProxyPassReverse /web http://127.0.0.1:8000/
sudo systemctl reload apache2
7. SYSTEMD
Datei:
/etc/systemd/system/gpio_web.service
[Unit] Description=GPIO Web FastAPI After=network-online.target Wants=network-online.target [Service] User=pi WorkingDirectory=/home/pi/devel/projects/gpio_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 gpio_web sudo systemctl start gpio_web
8. TEST
9. REBOOT
sudo reboot
Nach Neustart erneut aufrufen.
Eigenschaften:
- HTML sauber getrennt
- Hardware sauber getrennt
- Keine versteckte Reinitialisierung
- Für Anfänger klar strukturiert
- Reboot-fest über systemd
projekt/python_fastapi.1771613303.txt.gz · Zuletzt geändert: von torsten.roehl
