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

Telefon otevře TCP spojení ke kameře, odešle HTTP požadavek, kamera jej naparsuje, nasměruje, spustí handler a poté zapíše zpět odpověď.

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.