10.5. API sterujące dla kamery¶
Właściciel musi móc ustawiać czułość detektora ruchu z dowolnego miejsca – w wietrzny dzień drzewa poruszają się bardziej. Oznacza to trasy, z których panel może odczytać bieżące ustawienia i do których może wysłać zmiany.
Mały współdzielony słownik stanu w module wystarcza, by przechowywać pokrętła. Późniejsze strony dodają do niego więcej kluczy; na razie jest jeden:
state = {
'threshold': 12,
'frame_count': 0,
'trigger_count': 0,
}
10.5.1. GET do odczytu, POST do zapisu¶
Para tras – jedna get, jedna post – daje panelowi dostęp do odczytu i zapisu 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 zwraca treść sparsowaną jako JSON lub None, jeśli Content-Type nie był application/json. Handler post przechodzi przez każdy tryb awarii – brakujący klucz, zły typ, poza zakresem – i przerywa za pomocą microdot.abort(), które zgłasza microdot.HTTPException, aby zakończyć handler na skróty z podanym statusem i komunikatem.
10.5.2. GET, POST, PUT, DELETE¶
get() i post() to dwie, których będziemy używać najczęściej. put() oraz delete() istnieją dla przypadków zgodnych z konwencjami REST – PUT /events/42 zastępujące zdarzenie 42, DELETE /events/42 usuwające je. Poza tym handler jest identyczny.
10.5.3. Odczytywanie ciągów zapytań i formularzy¶
Panel wysyła JSON, więc request.json to to, czego chcemy. Dwa inne sposoby, na jakie kamera może odbierać dane:
args– ciąg zapytania.?foo=1&bar=2staje się obiektemmicrodot.MultiDict, który możesz odczytać przezrequest.args.get('foo').form– formularz HTML wysłany jakoapplication/x-www-form-urlencoded. Ten sam typMultiDict.
MultiDict jest słownikopodobny, ale pozwala, by jeden klucz niósł wiele wartości (?tag=cat&tag=dog to dwie wartości tag); pełny interfejs znajdziesz w microdot.MultiDict.
10.5.4. Dynamiczne segmenty URL¶
Ścieżka trasy może deklarować typowane symbole zastępcze, które microdot przekazuje do handlera jako dodatkowe argumenty:
@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
return {'id': event_id, 'msg': 'placeholder'}
Obsługiwane konwertery to <int:>, <re:> dla niestandardowego wyrażenia regularnego, <path:> dla segmentu mogącego zawierać ukośniki oraz domyślny (bez prefiksu) dla „dopasuj cokolwiek aż do następnego ukośnika”. <int:event_id> akceptuje /events/42 i odrzuca /events/abc – odrzucenie staje się błędem 404 bez uruchamiania handlera.
10.5.5. Niestandardowe odpowiedzi błędów¶
Domyślny błąd 404 wysyłany przez microdot to zwykłe Not found. Panel oczekuje JSON-a dla każdej odpowiedzi; nadpisz handler 404, aby on także zwracał JSON:
@app.errorhandler(404)
async def not_found(request):
return {'error': 'not found', 'path': request.path}, 404
errorhandler() przyjmuje albo kod statusu (przechwytuje każdy błąd o tym statusie), albo klasę wyjątku (przechwytuje każdy handler, który zgłosił ten wyjątek). Krotka (body, status) zwraca odpowiedź na skróty bez konstruowania Response.
Kamera udostępnia teraz swój stan i przyjmuje edycje.