10.1. Vaša prva krajnja točka¶
Prije nego kamera može učiniti išta zanimljivo, ostatak mreže mora moći doprijeti do nje. Najjeftinija stvar koja dokazuje da je poslužitelj živ jest HTTP krajnja točka s jednom rutom koja vraća nešto JSON-a:
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)
Pokrenite je u IDE-u. S bilo kojeg drugog računala na LAN-u otvorite http://<cam-ip>/status. Preglednik prikazuje:
{"frames": 0, "triggers": 0}
Brojači su rezervirana mjesta – ništa ih još ne dira – ali zahtjev je prešao mrežu, kamera ga je usmjerila, pokrenula rukovatelj i poslala JSON natrag.
10.1.1. Što svaki redak radi¶
Jedna instanca microdot.Microdot po skripti. Instanca posjeduje tablicu usmjeravanja, rukovatelje pogreškama i životni ciklus (pokretanje, posluživanje, zaustavljanje). Velike aplikacije dijele se na više Python modula, ali i dalje dijele jedan app objekt.
@app.get('/status') je dekorator rute. Ovdje koristimo samo microdot.Microdot.get(); post(), put() i delete() pojavljuju se na kasnijim stranicama kada kamera počne prihvaćati upise.
Svaki rukovatelj rute je asyncio korutina i prima zahtjev kao svoj prvi argument. Rukovatelj ne mora koristiti request – ovaj ga ignorira – ali parametar je uvijek tu pa je potpis dosljedan.
Vraćanje rječnika (dict) najkraći je način slanja JSON-a. Microdot automatski serijalizira rječnik u JSON i postavlja Content-Type: application/json na odgovoru. Vraćanje niza znakova šalje text/plain. Eksplicitno vraćanje microdot.Response dugi je oblik – potreban kada je tijelo binarno ili kada odgovor zahtijeva prilagođena zaglavlja.
app.run(host='0.0.0.0', port=80) pokreće poslužitelj. 0.0.0.0 znači slušaj na svakom sučelju koje kamera ima – i žičanom ethernetu i wifi STA, ako su oba aktivna. Vrata 80 zadana su za HTTP, pa preglednici ne moraju upisivati broj vrata.
10.1.2. Jedan zahtjev, od početka do kraja¶
Telefon otvara TCP vezu, zapisuje redak zahtjeva i zaglavlja te čeka. Kamera čita bajtove sa socketa, raščlanjuje ih u microdot.Request objekt, uspoređuje putanju i metodu s tablicom usmjeravanja, čeka korutinu rukovatelja (await), serijalizira što god je ona vratila, zapisuje redak statusa, zaglavlja i tijelo natrag kroz socket, a zatim zatvara vezu (zadano HTTP/1.0) ili je reciklira (HTTP/1.1 s Connection: keep-alive). Cijela razmjena traje otprilike koliko mrežni put naprijed-natrag plus što god je rukovatelj učinio.
10.1.3. Napomena o blokiranju¶
run() blokira – nikada se ne vraća dok se poslužitelj ne zaustavi. To je u redu za poslužitelj s jednom svrhom. Aplikacija koja također snima sličice ili pokreće druge korutine umjesto toga koristi start_server() unutar asyncio.run(), kako bi HTTP poslužitelj mogao dijeliti petlju sa svime ostalim.
Aplikacija odgovara na jedan URL.