projekt:python_fastapi
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen RevisionVorhergehende ÜberarbeitungNächste Überarbeitung | Vorhergehende Überarbeitung | ||
| projekt:python_fastapi [2026/02/20 19:18] – torsten.roehl | projekt:python_fastapi [2026/02/23 07:26] (aktuell) – [Systemd] torsten.roehl | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | ====== | + | ====== Python FASTAPI |
| [[raspberry_pi: | [[raspberry_pi: | ||
| - | ===== 0. ENV (VENV) ===== | + | //In diesem Projekt wird auf dem Raspberry Pi eine Weboberfläche mit FastAPI erstellt, über die eine LED-Ampel geschaltet und die Temperatur eines DS18B20 angezeigt werden kann. Die Anwendung ist im lokalen Netzwerk erreichbar, sodass LEDs und Temperatursensor bequem über einen Webbrowser im LAN gesteuert und überwacht werden können.// |
| - | < | + | |{{ : |
| + | |Die LED-Ampel kann nun über den Webbrowser gesteuert und die Temperatur ausgelesen werden.| | ||
| + | ====== Überblick ====== | ||
| + | * Voraussetzungen | ||
| + | * Software | ||
| + | * Konfiguration | ||
| + | |||
| + | ====== Details ====== | ||
| + | |||
| + | ===== Voraussetzungen ===== | ||
| + | |||
| + | ==== ENV ==== | ||
| + | |||
| + | <note important> | ||
| + | **Aktivierung der Python-Environment: | ||
| + | |||
| + | Alle weiteren Schritte erfolgen mit der aktivierten Python-Umgebung. | ||
| + | |||
| + | < | ||
| source ~/ | source ~/ | ||
| - | pip install fastapi uvicorn RPi.GPIO | ||
| - | which uvicorn | ||
| </ | </ | ||
| - | Erwartet: | + | </ |
| - | / | + | Anschließend werden FastAPI und Uvicorn installiert: |
| + | <code bash> | ||
| + | pip install fastapi uvicorn | ||
| + | </ | ||
| + | < | ||
| + | **FastAPI / Uvicorn** | ||
| - | ===== 1. PROJEKTORDNER ===== | + | * **FastAPI** |
| + | * stellt das Web-Framework bereit, mit dem die Webseiten und Routen programmiert werden. | ||
| + | * **Uvicorn** | ||
| + | * startet die Anwendung und sorgt dafür, dass sie im Browser erreichbar ist. | ||
| + | </ | ||
| + | ==== Projektstruktur ==== | ||
| + | |||
| + | '' | ||
| + | < | ||
| + | course_web/ | ||
| + | └── src/ | ||
| + | ├── app.py | ||
| + | ├── core/ | ||
| + | │ | ||
| + | │ | ||
| + | └── html/ | ||
| + | ├── led.html | ||
| + | └── temp.html | ||
| + | |||
| + | </ | ||
| + | ==== Apache2 Startseite ==== | ||
| + | Im Verzeichnis des Apache2-Webservers (''/ | ||
| + | Beim Aufruf der **IP-Adresse des Raspberry Pi im Browser** wird diese Startseite geladen, über die anschließend das gewünschte Projekt ausgewählt werden kann. | ||
| + | |||
| + | <note tip> **Tip** | ||
| + | |||
| + | Bevor die neue '' | ||
| <code bash> | <code bash> | ||
| - | cd /home/pi/devel/projects | + | sudo mv /var/www/html/index.html |
| - | mkdir -p python_web/src/core | + | |
| - | cd python_web/src/core | + | |
| - | touch __init__.py | + | |
| </ | </ | ||
| + | </ | ||
| + | <code html / | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| - | ===== 2. HARDWARE (LED + DS18B20) | + | < |
| + | |||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | ==== Hardware | ||
| + | Die Hardware, also die LED-Ampel und der Temperatursensor, | ||
| - | Datei: | + | ===== Software ===== |
| - | / | + | Im folgenden Abschnitt werden die für die Webanwendung benötigten Python- und HTML-Dateien vorgestellt. Dazu gehören die Hardware-Anbindung über GPIO und den Temperatursensor, |
| + | ==== API ==== | ||
| - | <code python> | + | <code python |
| import RPi.GPIO as GPIO | import RPi.GPIO as GPIO | ||
| import glob | import glob | ||
| import time | import time | ||
| - | |||
| # ----------------------------- | # ----------------------------- | ||
| Zeile 46: | Zeile 110: | ||
| _initialized = False | _initialized = False | ||
| - | |||
| def init(): | def init(): | ||
| Zeile 64: | Zeile 127: | ||
| def setLED(pin, value): | def setLED(pin, value): | ||
| - | | + | GPIO.output(pin, |
| - | | + | |
| - | | + | |
| - | GPIO.output(pin, | + | |
| Zeile 83: | Zeile 143: | ||
| def status(): | def status(): | ||
| - | | + | |
| - | y = GPIO.input(PIN_Y) | + | int(GPIO.input(PIN_R)), |
| - | g = GPIO.input(PIN_G) | + | int(GPIO.input(PIN_Y)), |
| - | return r, y, g | + | int(GPIO.input(PIN_G)), |
| - | + | ) | |
| - | + | ||
| - | def cleanup(): | + | |
| - | | + | |
| Zeile 97: | Zeile 154: | ||
| # ----------------------------- | # ----------------------------- | ||
| - | SENSOR_TIMEOUT = 1 # Sekunden | + | SENSOR_TIMEOUT = 1 |
| - | + | ||
| - | + | ||
| - | def is_sensor(): | + | |
| - | sensors = glob.glob("/ | + | |
| - | return len(sensors) > 0 | + | |
| def get_sensor(): | def get_sensor(): | ||
| Zeile 137: | Zeile 188: | ||
| - | ===== 3. FASTAPI APP ===== | + | ==== |
| - | Datei: | + | === LED === |
| - | / | + | |
| - | <code python> | ||
| - | from fastapi import FastAPI, HTTPException | ||
| - | from fastapi.responses import HTMLResponse, | ||
| - | from core import hardware | ||
| - | app = FastAPI() | + | <code html / |
| - | + | ||
| - | + | ||
| - | @app.on_event(" | + | |
| - | def startup(): | + | |
| - | hardware.init() | + | |
| - | + | ||
| - | + | ||
| - | @app.get(" | + | |
| - | def led_page(): | + | |
| - | r, y, g = hardware.status() | + | |
| - | return HTMLResponse(f""" | + | |
| < | < | ||
| < | < | ||
| - | < | + | < |
| + | | ||
| + | </ | ||
| < | < | ||
| < | < | ||
| - | < | + | < |
| + | <p>Status: {{R}}</p> | ||
| <a href="/ | <a href="/ | ||
| <a href="/ | <a href="/ | ||
| - | < | + | < |
| + | <p>Status: {{Y}}</p> | ||
| <a href="/ | <a href="/ | ||
| <a href="/ | <a href="/ | ||
| - | < | + | < |
| + | <p>Status: {{G}}</p> | ||
| <a href="/ | <a href="/ | ||
| <a href="/ | <a href="/ | ||
| Zeile 183: | Zeile 223: | ||
| </ | </ | ||
| </ | </ | ||
| - | """ | + | </ |
| + | |||
| + | === Temperature === | ||
| + | |||
| + | |||
| + | <code html / | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | </ | ||
| + | < | ||
| + | |||
| + | < | ||
| + | |||
| + | < | ||
| + | |||
| + | <br> | ||
| + | <a href="/"> | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== FASTAPI APP ==== | ||
| + | |||
| + | |||
| + | <code python / | ||
| + | |||
| + | |||
| + | from fastapi import FastAPI, HTTPException | ||
| + | from fastapi.responses import HTMLResponse, | ||
| + | from core import hardware | ||
| + | |||
| + | app = FastAPI() | ||
| + | |||
| + | |||
| + | @app.on_event(" | ||
| + | def startup(): | ||
| + | hardware.init() | ||
| + | |||
| + | |||
| + | def load_template(name, | ||
| + | try: | ||
| + | with open(f" | ||
| + | html = f.read() | ||
| + | except FileNotFoundError: | ||
| + | raise HTTPException(status_code=500, | ||
| + | |||
| + | for key, value in replacements.items(): | ||
| + | html = html.replace(key, | ||
| + | |||
| + | return html | ||
| + | |||
| + | @app.get("/ | ||
| + | def led_page(): | ||
| + | r, y, g = hardware.status() | ||
| + | |||
| + | return HTMLResponse( | ||
| + | load_template(" | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | }) | ||
| + | ) | ||
| @app.get("/ | @app.get("/ | ||
| def set_led(color: | def set_led(color: | ||
| + | |||
| if value not in (0, 1): | if value not in (0, 1): | ||
| raise HTTPException(status_code=400) | raise HTTPException(status_code=400) | ||
| Zeile 206: | Zeile 315: | ||
| def temp_page(): | def temp_page(): | ||
| t = hardware.get_temperature() | t = hardware.get_temperature() | ||
| + | |||
| if t is None: | if t is None: | ||
| value = " | value = " | ||
| else: | else: | ||
| - | value = f" | + | value = f" |
| - | return HTMLResponse(f""" | + | return HTMLResponse( |
| - | < | + | load_template("temp.html", { |
| - | < | + | |
| - | < | + | }) |
| - | <body> | + | ) |
| + | </code> | ||
| - | < | ||
| - | < | ||
| - | <br> | ||
| - | <a href="/"> | ||
| - | </ | ||
| - | </ | ||
| - | """ | ||
| - | </ | ||
| + | ===== Konfiguration ===== | ||
| + | In diesem Abschnitt wird die Einbindung der **FastAPI-Anwendung** in den Apache-Webserver sowie die Einrichtung als '' | ||
| + | ==== Apache Proxy ==== | ||
| - | ===== 4. APACHE STARTSEITE ===== | + | === Konfiguration |
| - | Datei: | + | In der Datei '' |
| - | | + | innerhalb von ''< |
| - | <code html> | ||
| - | < | ||
| - | < | ||
| - | < | ||
| - | < | ||
| - | </ | ||
| - | < | ||
| - | <h1> | + | <note tip> **Tip** |
| - | < | + | Bevor die Datei '' |
| - | < | + | sollte die vorhandene Konfiguration gesichert werden. |
| - | < | + | |
| - | < | + | |
| - | </ul> | + | |
| - | </body> | + | <code bash> |
| - | </html> | + | cd |
| + | sudo cp 000-default.conf 000-default.conf.course_backup | ||
| </ | </ | ||
| + | </ | ||
| - | ===== 5. APACHE PROXY ===== | ||
| - | Datei: | + | <code bash / |
| - | | + | |
| - | + | ||
| - | Innerhalb von < | + | |
| - | + | ||
| - | <code> | + | |
| ProxyPreserveHost On | ProxyPreserveHost On | ||
| Zeile 272: | Zeile 364: | ||
| </ | </ | ||
| - | Module | + | === Aktivieren === |
| + | Damit die Weiterleitung an die FastAPI-Anwendung funktioniert, | ||
| <code bash> | <code bash> | ||
| sudo a2enmod proxy | sudo a2enmod proxy | ||
| sudo a2enmod proxy_http | sudo a2enmod proxy_http | ||
| - | sudo systemctl | + | sudo systemctl |
| </ | </ | ||
| + | ==== Systemd ==== | ||
| - | ===== 6. SYSTEMD (AUTOSTART) ===== | + | Die Service-Datei muss unter ''/ |
| + | === Service | ||
| - | Datei: | ||
| - | / | ||
| - | < | + | < |
| [Unit] | [Unit] | ||
| Description=Python Web FastAPI | Description=Python Web FastAPI | ||
| Zeile 294: | Zeile 387: | ||
| [Service] | [Service] | ||
| User=pi | User=pi | ||
| - | WorkingDirectory=/ | + | WorkingDirectory=/ |
| ExecStart=/ | ExecStart=/ | ||
| Restart=always | Restart=always | ||
| Zeile 302: | Zeile 395: | ||
| </ | </ | ||
| - | Aktivieren: | + | === Registrierung === |
| + | Damit die neu erstellte Service-Datei von '' | ||
| <code bash> | <code bash> | ||
| sudo systemctl daemon-reload | sudo systemctl daemon-reload | ||
| - | sudo systemctl enable | + | sudo systemctl enable |
| - | sudo systemctl start python_web | + | sudo systemctl start course_web |
| </ | </ | ||
| - | + | Nützlich: | |
| - | ===== 7. TEST ===== | + | |
| - | + | ||
| - | * http:// | + | |
| - | * http:// | + | |
| - | * http:// | + | |
| - | * http:// | + | |
| - | + | ||
| - | + | ||
| - | ===== 8. REBOOT TEST ===== | + | |
| <code bash> | <code bash> | ||
| - | sudo reboot | + | sudo systemctl restart course_web |
| + | sudo systemctl status course_web | ||
| </ | </ | ||
| - | |||
| - | Nach Neustart erneut prüfen: | ||
| - | |||
| - | * http:// | ||
| - | * http:// | ||
| - | * http:// | ||
| - | * http:// | ||
| - | |||
| - | |||
| - | |||
projekt/python_fastapi.1771615091.txt.gz · Zuletzt geändert: von torsten.roehl
