10.13. Ladda upp utlösta bildrutor till molnet¶
När rörelse utlöser tänder kameran nu upp instrumentpanelen. Det räcker för direktanvändning, men ägaren vill också ha ett permanent arkiv av varje utlöst bildruta, lagrat någonstans utanför kameran. Det är ett utgående HTTP-anrop – kameran fungerar som en klient.
10.13.1. Kameran som klient¶
Modulen requests är kamerans utgående HTTP-klient. Dess gränssnitt är en avsiktlig kopia av CPythons requests – samma verbnamngivna modulfunktioner, samma nyckelordsargument files=, json=, headers=, auth=. Om du har gjort HTTP-anrop från CPython kan du redan API:et:
import requests
import io
ARCHIVE_URL = 'https://api.backyard-cloud.com/frames'
ARCHIVE_TOKEN = load_archive_token()
async def archive_frame(jpeg, ts):
try:
r = requests.post(
ARCHIVE_URL,
files={'image': (
'frame-{}.jpg'.format(ts),
io.BytesIO(jpeg),
)},
headers={'Authorization': 'Bearer ' + ARCHIVE_TOKEN},
)
except OSError as e:
print('upload failed:', e)
return False
if r.status_code >= 400:
print('archive rejected:', r.status_code, r.reason)
return False
return True
requests.post() öppnar en TCP-anslutning, skickar förfrågan och returnerar ett Response med status_code, reason, headers, content, json() och resten av de bekanta egenskaperna.
files={...} bygger en multipart/form-data-kropp. Värdet är en (filename, file-like)-tupel; requests.post() läser det filliknande objektet i bitar så att hela JPEG-bilden inte behöver buffras om till en sträng först. io.BytesIO omsluter de JPEG-byte som redan finns i minnet så att de exponerar ett läs-som-fil-gränssnitt.
headers={...} är en vanlig dict som skickas som förfrågningshuvuden – här en bearer-token i den standardiserade Authorization-positionen. Arkivleverantören dokumenterar vilket tokenformat de vill ha; exemplet är den vanligaste formen.
10.13.2. Koppla in det i rörelsedetektorn¶
Rörelsedetektor-koroutinen som introducerades tidigare körs redan vid varje ny bildruta och utlöses när change > state['threshold']. Lägg till uppladdningen där, men kör den som en bakgrundsuppgift så att detektorn inte slutar bevaka medan uppladdningen pågår:
async def motion_detector():
global last_motion
prev = None
while True:
await new_frame.wait()
change = compute_change(prev, latest_jpeg)
if change > state['threshold']:
state['trigger_count'] += 1
ts = int(time.time())
last_motion = {'ts': ts,
'count': state['trigger_count'],
'change': change}
motion_event.set()
asyncio.create_task(archive_frame(latest_jpeg, ts))
prev = latest_jpeg
await asyncio.sleep_ms(50)
asyncio.create_task() schemalägger uppladdningskoroutinen och returnerar omedelbart. Detektorn fortsätter att hämta bildrutor; uppladdningen körs parallellt med den; kameran låser sig aldrig.
10.13.3. Felscenarier¶
Nätverkskod misslyckas. Kameran kan vara offline, arkivet kan vara nere, bearer-token kan ha löpt ut. De kategorier som är värda att fånga:
OSError– TCP-anslutningen kunde inte öppnas eller stängdes mitt i överföringen. DNS-fel, ingen rutt, anslutning återställd.requestsgenererar exakt detta undantag.status_code >= 400– servern tog emot förfrågan och avvisade den. 401 för en utgången token, 403 för en återkallad, 413 för en för stor kropp, 5xx för att arkivet inte mår bra.Tyst timeout –
requestsanvänder en standardtimeout för socketen (några sekunder); efter det genererar denOSErrormederrno.ETIMEDOUT.
För ett arkiv som verkligen är viktigt skulle du köa avvisade bildrutor till /sdcard/pending/ och försöka igen i en långsammare slinga – det är några rader till per fall, utöver det som visas.
10.13.4. Vad requests inte gör¶
MicroPython-porten är avsiktligt liten. Några saker som CPythons requests gör som den här inte gör:
Anslutningspoolning. Varje anrop öppnar en ny TCP-anslutning.
Automatiska omförsök vid tillfälliga fel. Linda in anropet själv.
Strömmande svar.
r.contentläses in i sin helhet i RAM; det finns ingen motsvarighet tillstream=True.Automatisk dekomprimering av gzip-komprimerade svar. Ange huvudet
Accept-Encodingexplicit endast om servern är konfigurerad för det.
Se requests — HTTP-klient för den fullständiga metodlistan och vad som ingår respektive inte ingår i omfattningen.
HTTPS fungerar direkt – URL-schemat styr det, och standard-SSL-kontexten skapas i farten. För att verifiera arkivets certifikat mot ett CA-paket som du har laddat upp på kameran, se avsnittet som en klient i Verifiera en publik server (kameran som klient).
Appen är fullt levererad: direktförhandsgranskning, rörelsedetektering, instrumentpanel med inloggning, HTTPS, CORS/CSRF, molnarkiv.