10.5. Vezérlő API a kamerához

A tulajdonosnak bárhonnan be kell tudnia állítani a mozgásérzékelő érzékenységét – szeles napon a szél jobban mozgatja a fákat. Ez olyan útvonalakat jelent, amelyekről az irányítópult kiolvashatja az aktuális beállításokat, és módosításokat küldhet rájuk.

Egy kis megosztott állapot-dict a modulon elegendő a kapcsolók tárolásához. A későbbi oldalak további kulcsokat adnak hozzá; egyelőre egy van:

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

10.5.1. GET az olvasáshoz, POST az íráshoz

Egy útvonalpár – egy get, egy post – olvasási/írási hozzáférést ad az irányítópultnak a state változóhoz:

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}

A microdot.Request.json a JSON-ként értelmezett törzset adja vissza, vagy None értéket, ha a Content-Type nem application/json volt. A post kezelő végigjárja az egyes hibamódokat – hiányzó kulcs, rossz típus, tartományon kívül – és a microdot.abort() függvénnyel kilép, amely microdot.HTTPException kivételt dob, hogy a megadott állapottal és üzenettel rövidre zárja a kezelőt.

10.5.2. GET, POST, PUT, DELETE

A get() és a post() az a kettő, amelyet a legtöbbet fogunk használni. A put() és a delete() olyan esetekhez létezik, amelyek REST-konvenciókat követnek – egy PUT /events/42 a 42-es esemény cseréjéhez, egy DELETE /events/42 az eldobásához. A kezelő egyébként azonos.

10.5.3. Lekérdezési stringek és űrlapok olvasása

Az irányítópult JSON-t küld, így a request.json az, amit szeretnénk. Két másik mód, ahogyan a kamera adatot kaphat:

  • A args – a lekérdezési string. A ?foo=1&bar=2 egy microdot.MultiDict lesz, amelyet a request.args.get('foo') segítségével olvashatsz.

  • A form – egy application/x-www-form-urlencoded formában elküldött HTML-űrlap. Ugyanaz a MultiDict típus.

A MultiDict dict-szerű, de megengedi, hogy egy kulcs több értéket hordozzon (a ?tag=cat&tag=dog két tag érték); a teljes felületért lásd: microdot.MultiDict.

10.5.4. Dinamikus URL-szegmensek

Egy útvonal-elérési út deklarálhat típusos helykitöltőket, amelyeket a microdot extra argumentumokként ad át a kezelőnek:

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

A támogatott konverterek a <int:>, a <re:> egyéni reguláris kifejezéshez, a <path:> egy perjeleket tartalmazható szegmenshez, és az alapértelmezett (előtag nélküli) a „bármit illeszt a következő perjelig” esetre. A <int:event_id> elfogadja a /events/42 címet, és elutasítja a /events/abc címet – az elutasítás 404-é válik anélkül, hogy a kezelő lefutna.

10.5.5. Egyéni hibaválaszok

Az alapértelmezett 404, amelyet a microdot küld, egyszerűen Not found. Az irányítópult minden válasznál JSON-t vár; bíráld felül a 404-kezelőt, hogy az is JSON-t adjon vissza:

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

A errorhandler() vagy egy állapotkódot vesz át (minden olyan állapotú hibát elkap), vagy egy kivételosztályt (minden olyan kezelőt elkap, amely azt a kivételt dobta). A (body, status) tuple rövidre zárja a választ anélkül, hogy Response objektumot konstruálna.

A kamera most már felfedi az állapotát, és elfogad szerkesztéseket.