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í, 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.