Benutzer-Werkzeuge

Webseiten-Werkzeuge


projekt:python_fastapi

Dies ist eine alte Version des Dokuments!


GPIO mit FastAPI (Websteuerung)

0. ENV (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

1. PROJEKTORDNER

cd /home/pi/devel/projects
mkdir -p python_web/src/core
cd python_web/src/core
touch __init__.py

2. HARDWARE (LED + DS18B20)

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

3. FASTAPI APP

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()
 
 
@app.on_event("startup")
def startup():
    hardware.init()
 
 
@app.get("/led", response_class=HTMLResponse)
def led_page():
    r, y, g = hardware.status()
    return HTMLResponse(f"""
<!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>
""")
 
 
@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} °C"
 
    return HTMLResponse(f"""
<!DOCTYPE html>
<html>
<head><title>Temperatur</title></head>
<body>
 
<h1>Temperatur</h1>
<p>{value}</p>
 
<br>
<a href="/">Zurück</a>
 
</body>
</html>
""")

4. APACHE 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>

5. APACHE PROXY

Datei:

/etc/apache2/sites-available/000-default.conf

Innerhalb von <VirtualHost *:80>:

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

Module aktivieren und Apache neu laden:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo systemctl reload apache2

6. SYSTEMD (AUTOSTART)

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

Aktivieren:

sudo systemctl daemon-reload
sudo systemctl enable python_web
sudo systemctl start python_web

7. TEST

8. REBOOT TEST

projekt/python_fastapi.1771615091.txt.gz · Zuletzt geändert: von torsten.roehl