10.5. Řídicí API pro kameru

Majitel potřebuje nastavit citlivost detektoru pohybu odkudkoli – za větrného dne se stromy hýbou víc. To znamená cesty, ze kterých dashboard může číst aktuální nastavení a odesílat do nich změny.

K uchování ovládacích prvků stačí malý sdílený slovník stavu na úrovni modulu. Pozdější stránky do něj přidají další klíče; prozatím je v něm jeden:

state = {
    'threshold': 12,
    'frame_count': 0,
    'trigger_count': 0,
}

10.5.1. GET pro čtení, POST pro zápis

Dvojice cest – jedna get, jedna post – dává dashboardu přístup pro čtení i zápis ke state:

from microdot import abort

@app.get('/config')
async def get_config(request):
    return state

@app.post('/config')
async def set_config(request):
    body = request.json
    if not body or 'threshold' not in body:
        abort(400, 'missing threshold')
    try:
        threshold = int(body['threshold'])
    except (TypeError, ValueError):
        abort(400, 'threshold must be an integer')
    if not 0 <= threshold <= 100:
        abort(400, 'threshold out of range')
    state['threshold'] = threshold
    return {'ok': True, 'threshold': threshold}

microdot.Request.json vrací tělo parsované jako JSON, nebo None, pokud Content-Type nebyl application/json. Handler post projde každý režim selhání – chybějící klíč, špatný typ, mimo rozsah – a skončí pomocí microdot.abort(), který vyvolá microdot.HTTPException, aby handler zkratoval s daným stavem a zprávou.

10.5.2. GET, POST, PUT, DELETE

get() a post() jsou ty dvě, které budeme používat nejvíce. put() a delete() existují pro případy, které dodržují konvence REST – PUT /events/42 k nahrazení události 42, DELETE /events/42 k jejímu zahození. Handler je jinak identický.

10.5.3. Čtení query stringů a formulářů

Dashboard odesílá JSON, takže request.json je to, co chceme. Dva další způsoby, jak může kamera přijímat data:

  • args – query string. ?foo=1&bar=2 se stane microdot.MultiDict, který lze číst pomocí request.args.get('foo').

  • form – HTML formulář odeslaný jako application/x-www-form-urlencoded. Stejný typ MultiDict.

MultiDict je podobný slovníku, ale umožňuje, aby jeden klíč nesl více hodnot (?tag=cat&tag=dog jsou dvě hodnoty tag); úplné rozhraní viz microdot.MultiDict.

10.5.4. Dynamické segmenty URL

Cesta routy může deklarovat typované zástupné symboly, které microdot předá handleru jako další argumenty:

@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
    return {'id': event_id, 'msg': 'placeholder'}

Podporované převodníky jsou <int:>, <re:> pro vlastní regulární výraz, <path:> pro segment, který může obsahovat lomítka, a výchozí (bez prefixu) pro „vše až do dalšího lomítka.“ <int:event_id> přijme /events/42 a odmítne /events/abc – odmítnutí se stane stavem 404 bez spuštění handleru.

10.5.5. Vlastní chybové odpovědi

Výchozí 404, kterou microdot odesílá, je obyčejné Not found. Dashboard očekává JSON pro každou odpověď; přepište handler pro 404 tak, aby vracel také JSON:

@app.errorhandler(404)
async def not_found(request):
    return {'error': 'not found', 'path': request.path}, 404

errorhandler() přijímá buď stavový kód (zachytí každou chybu daného stavu), nebo třídu výjimky (zachytí každý handler, který danou výjimku vyvolal). N-tice (body, status) zkratuje odpověď bez konstruování Response.

Kamera nyní zveřejňuje svůj stav a přijímá úpravy.