[GET/POST zwischen ESP32 und Server]Wird async benötigt?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
Dennis89
User
Beiträge: 1683
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo zusammen,

ich arbeite gerade an einem Projekt und benötige eure Hilfe.
Ein ESP32 liest eine Position eines Ventil's aus, diesen Wert gibt er an einen Server. Der Server speichert den Wert in eine Datenbank und errechnet ein PWM-Signal, das er an den ESP32 sendet und dieser setzt an einem Pin dieses Signal.
Die Kommunikation, vom senden bis zum erhalten des PWM-Wert's soll innerhalb einer Sekunde geschehen.

Ich habe zwei Fragen: Mir ist nichts besseres eingefallen, als das auf dem Server beide `Queue`' s auf Modulebene definiert sind und dass ich das Rechnen und Schreiben in die Datenbank in einem extra Thread mache. Habt ihr eine bessere Idee?
Dann habe ich ein komisches Verhalten, zumindest kommt es mir komisch vor. Mein Testcode sendet jede Zentel Sekunde Werte an den Server und dieser fragt aber nur jede Sekunde die Queue ab und es gehen keine Daten verloren. Ich hätte erwartet, dass da Daten verloren gehen. In die andere Richtung, sende ich jede Sekunde an meinen ESP32, dieser fragt jede Zentel-Sekunde die Daten ab und es gehen hier Daten verloren.

Ich denke, dass das eventuell mit `async` gelöst werden könnte. Zum einen würde ich dieses Verhalten gern verstehen und zum anderen würde ich gerne wissen, wie man so eine Kommunikation richtig aufbaut. Die `sleep`'s in der Schleife, haben bis jetzt noch gar nichts mit der zeitlichen Anforderung zu tun. Das kommt im nächsten Schritt. Ich will erst verstehen, wieso sich das nicht so verhält, wie ich es erwartet habe. Aktuell läuft beides lokal auf einem Rechner, weil das angenehmer ist um den Code anzupassen. Später ist der ESP32 mit Ethernet verbunden.

Server:

Code: Alles auswählen

#!.venv/bin/python
from queue import Empty, Queue
from threading import Thread
from time import sleep

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()
position = Queue(maxsize=1)
pwm = Queue(maxsize=1)


class Position(BaseModel):
    position: float


@app.post("/")
async def get_position(message: Position):
    response = message.position
    if position.full():
        _ = position.get_nowait()
    position.put_nowait(response)


@app.get("/get_pwm")
async def send_pwm():
    if pwm.empty():
        return {"pwm": 0}
    return {"pwm": pwm.get_nowait()}


class PressureInjection(Thread):
    def run(self):
        pwm_value = 1
        while True:
            if pwm.full():
                _ = pwm.get_nowait()
            pwm.put_nowait(pwm_value)
            try:
                print(f"Aus der Schleife: {position.get_nowait()}")
            except Empty:
                print("leer")
            sleep(1)
            pwm_value += 1


if __name__ == "__main__":
    pressure_injection = PressureInjection()
    pressure_injection.daemon = True
    pressure_injection.start()
    uvicorn.run(app, host="0.0.0.0", port=8000)
ESP32 (läuft aktuell auch lokal)

Code: Alles auswählen

import json
from time import sleep

import requests

SERVER_IP = "localhost"
SERVER_PORT = 8000
SERVER_ADDRESS = f"http://{SERVER_IP}:{SERVER_PORT}/"


def send_to_server(address, data):
    response = requests.post(address, data=data)
    response.close()


def get_from_server(address, target):
    return requests.get(f"{address}/{target}").json()


def main():
    position = 1
    while True:
        send_to_server(SERVER_ADDRESS, json.dumps({"position": position}))
        print(get_from_server(SERVER_ADDRESS, "/get_pwm"))
        position += 0.1
        sleep(0.1)


if __name__ == "__main__":
    main()
Wenn ich beide im Terminal start, dann kommt auf der Serverseite:

Code: Alles auswählen

leer
INFO:     Started server process [22084]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
leer
leer
leer
leer
INFO:     127.0.0.1:50810 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.0
leer
INFO:     127.0.0.1:50812 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50814 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.1
leer
INFO:     127.0.0.1:50816 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50818 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.2000000000000002
leer
INFO:     127.0.0.1:50821 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50823 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.3000000000000003
leer
INFO:     127.0.0.1:50825 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50827 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.4000000000000004
leer
INFO:     127.0.0.1:50829 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50831 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.5000000000000004
leer
INFO:     127.0.0.1:50833 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
leer
INFO:     127.0.0.1:50835 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.6000000000000005
leer
INFO:     127.0.0.1:50837 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     127.0.0.1:50839 - "POST / HTTP/1.1" 200 OK
Aus der Schleife: 1.7000000000000006
leer
INFO:     127.0.0.1:50850 - "GET /get_pwm HTTP/1.1" 200 OK
leer
leer
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [22084]
Und der simulierte ESP:

Code: Alles auswählen

{'pwm': 7}
{'pwm': 11}
{'pwm': 15}
{'pwm': 19}
{'pwm': 23}
{'pwm': 27}
{'pwm': 32}
{'pwm': 36}
Man sieht schön, dass am ESP Werte verloren gehen und Server alle ankommen.

Vielen Dank vorab.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten