10.1. Váš první endpoint

Než kamera začne dělat něco zajímavého, musí ji být schopen dosáhnout zbytek sítě. Nejlevnější věc, která prokáže, že server žije, je HTTP endpoint s jedinou cestou, který vrací nějaký JSON:

from microdot import Microdot

app = Microdot()

frame_count = 0
trigger_count = 0

@app.get('/status')
async def status(request):
    return {'frames': frame_count, 'triggers': trigger_count}

app.run(host='0.0.0.0', port=80)

Spusťte jej v IDE. Z libovolného jiného počítače v LAN otevřete http://<cam-ip>/status. Prohlížeč zobrazí:

{"frames": 0, "triggers": 0}

Čítače jsou jen zástupné hodnoty – zatím se jich nic nedotýká – ale požadavek prošel sítí, kamera jej nasměrovala, spustila handler a poslala zpět JSON.

10.1.1. Co dělá každý řádek

Jedna instance microdot.Microdot na skript. Instance vlastní směrovací tabulku, error handlery a životní cyklus (start, obsluha, stop). Velké aplikace se dělí do několika Python modulů, ale stále sdílejí jeden objekt app.

@app.get('/status') je dekorátor cesty. Zde používáme pouze microdot.Microdot.get(); post(), put() a delete() se objeví na pozdějších stránkách, až kamera začne přijímat zápisy.

Každý handler cesty je asyncio korutina a obdrží požadavek jako svůj první argument. Handler nemusí request použít – tento jej ignoruje – ale parametr je tam vždy, takže signatura je konzistentní.

Vrácení slovníku je nejkratší způsob, jak odeslat JSON. Microdot slovník automaticky serializuje do JSON a nastaví v odpovědi Content-Type: application/json. Vrácení řetězce odešle text/plain. Explicitní vrácení microdot.Response je dlouhá forma – potřebná, když je tělo binární nebo když odpověď chce vlastní hlavičky.

app.run(host='0.0.0.0', port=80) spustí server. 0.0.0.0 znamená naslouchat na každém rozhraní, které kamera má – jak na drátovém ethernetu, tak na wifi STA, pokud jsou obě v provozu. Port 80 je výchozí pro HTTP, takže prohlížeče nemusí číslo portu psát.

10.1.2. Jeden požadavek od začátku do konce

The phone opens a TCP connection to the cam, sends an HTTP request, the cam parses, routes, runs the handler, then writes a response back.

Telefon otevře TCP spojení, zapíše řádek požadavku a hlavičky a čeká. Kamera přečte bajty ze socketu, naparsuje je do objektu microdot.Request, porovná cestu a metodu se směrovací tabulkou, počká na korutinu handleru, serializuje cokoli, co vrátila, zapíše zpět do socketu stavový řádek, hlavičky a tělo, poté spojení uzavře (výchozí HTTP/1.0) nebo jej recykluje (HTTP/1.1 s Connection: keep-alive). Celá výměna trvá zhruba tak dlouho jako síťový round-trip plus cokoli, co handler udělal.

10.1.3. Poznámka o blokování

run() je blokující – nikdy se nevrátí, dokud se server nezastaví. To je v pořádku pro jednoúčelový server. Aplikace, která také zachytává snímky nebo spouští jiné korutiny, místo toho používá start_server() uvnitř asyncio.run(), aby HTTP server mohl sdílet smyčku se vším ostatním.

Aplikace odpovídá na jednu URL.