10.5. カメラ用の制御API¶
所有者はどこからでも動き検出器の感度を設定する必要があります。風の強い日には風が木をより大きく揺らすからです。これは、ダッシュボードが現在の設定を読み取り、変更を投稿できるルートが必要だということを意味します。
モジュール上の小さな共有状態辞書があれば、つまみを保持するには十分です。後のページではこれにさらにキーを追加します。今のところは1つだけです。
state = {
'threshold': 12,
'frame_count': 0,
'trigger_count': 0,
}
10.5.1. GETで読み取り、POSTで書き込み¶
1つは get、もう1つは post という1組のルートが、ダッシュボードに 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 は、ボディをJSONとしてパースしたものを返します。Content-Type が application/json でなかった場合は None を返します。post ハンドラは各障害モード(キーの欠落、型の誤り、範囲外)を順に検査し、microdot.abort() で中断します。これは microdot.HTTPException を送出して、指定したステータスとメッセージでハンドラを短絡させます。
10.5.2. GET、POST、PUT、DELETE¶
get() と post() は、最もよく使う2つです。put() と delete() は、RESTの慣習に従うケースのために存在します。イベント42を置き換える PUT /events/42 や、それを削除する DELETE /events/42 などです。ハンドラはその点を除いて同一です。
10.5.3. クエリ文字列とフォームの読み取り¶
ダッシュボードはJSONを投稿するため、request.json が必要なものです。カメラがデータを受け取る他の2つの方法は次のとおりです。
args-- クエリ文字列です。?foo=1&bar=2はmicrodot.MultiDictになり、request.args.get('foo')で読み取れます。form--application/x-www-form-urlencodedとして投稿されたHTMLフォームです。同じMultiDict型です。
MultiDictは辞書のように振る舞いますが、1つのキーが複数の値を持つことができます(?tag=cat&tag=dog は2つの tag 値です)。全インターフェースについては microdot.MultiDict を参照してください。
10.5.4. 動的なURLセグメント¶
ルートパスは、microdotがハンドラに追加の引数として渡す型付きプレースホルダーを宣言できます。
@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
return {'id': event_id, 'msg': 'placeholder'}
サポートされている変換子は、<int:>、カスタム正規表現用の <re:>、スラッシュを含むことができるセグメント用の <path:>、そして「次のスラッシュまでの任意の文字列にマッチ」を意味するデフォルト(接頭辞なし)です。<int:event_id> は /events/42 を受け付け、/events/abc を拒否します。拒否はハンドラを実行せずに404になります。
10.5.5. カスタムエラーレスポンス¶
microdotが送信するデフォルトの404は、素の Not found です。ダッシュボードはすべてのレスポンスにJSONを期待するため、404ハンドラを上書きして、こちらもJSONを返すようにします。
@app.errorhandler(404)
async def not_found(request):
return {'error': 'not found', 'path': request.path}, 404
errorhandler() は、ステータスコード(そのステータスのすべてのエラーを捕捉)または例外クラス(その例外を送出したすべてのハンドラを捕捉)のいずれかを受け取ります。(body, status) タプルは、Response を構築せずにレスポンスを短絡します。
カメラはこれで状態を公開し、編集を受け付けるようになりました。