10.13. Przesyłanie wyzwolonych ramek do chmury¶
Gdy ruch wyzwoli zdarzenie, kamera podświetla teraz panel. To wystarcza do użytku na żywo, ale właściciel chce też mieć trwałe archiwum każdej wyzwolonej ramki, przechowywane gdzieś poza kamerą. To wychodzące wywołanie HTTP – kamera działa jako klient.
10.13.1. Kamera jako klient¶
Moduł requests to wychodzący klient HTTP kamery. Jego interfejs jest celowym odwzorowaniem requests z CPythona – te same funkcje modułu nazwane czasownikami, te same argumenty słowne files=, json=, headers=, auth=. Jeśli wykonywałeś już wywołania HTTP z CPythona, znasz to API:
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() otwiera połączenie TCP, wysyła żądanie i zwraca Response z status_code, reason, headers, content, json() oraz pozostałymi znanymi właściwościami.
files={...} buduje treść typu multipart/form-data. Wartością jest krotka (filename, file-like); requests.post() odczytuje obiekt plikopodobny w blokach, dzięki czemu cały JPEG nie musi być najpierw ponownie buforowany do łańcucha znaków. io.BytesIO opakowuje obecne już w pamięci bajty JPEG, tak aby udostępniały interfejs odczytu jak z pliku.
headers={...} to zwykły słownik wysyłany jako nagłówki żądania – tutaj token typu bearer na standardowej pozycji Authorization. Dostawca archiwum dokumentuje, jakiego formatu tokenu oczekuje; przykład pokazuje najczęstszą postać.
10.13.2. Wpięcie tego w detektor ruchu¶
Wprowadzona wcześniej korutyna detektora ruchu działa już na każdej nowej ramce i wyzwala się, gdy change > state['threshold']. Dodaj tam przesyłanie, ale uruchom je jako zadanie w tle, aby detektor nie przestawał obserwować, dopóki trwa przesyłanie:
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() planuje korutynę przesyłania i natychmiast wraca. Detektor dalej pobiera ramki; przesyłanie działa równolegle; kamera nigdy się nie zatrzymuje.
10.13.3. Tryby awarii¶
Kod sieciowy zawodzi. Kamera może być offline, archiwum może być niedostępne, token bearer mógł wygasnąć. Kategorie warte przechwycenia:
OSError– nie udało się otworzyć połączenia TCP lub zostało ono zamknięte w trakcie transferu. Awaria DNS, brak trasy, zresetowanie połączenia.requestszgłasza dokładnie ten wyjątek.status_code >= 400– serwer otrzymał żądanie i je odrzucił. 401 dla wygasłego tokenu, 403 dla unieważnionego, 413 dla zbyt dużej treści, 5xx gdy archiwum jest niesprawne.Ciche przekroczenie limitu czasu –
requestsużywa domyślnego limitu czasu gniazda (kilka sekund); po jego przekroczeniu zgłaszaOSErrorzerrno.ETIMEDOUT.
Dla archiwum, na którym naprawdę zależy, kolejkowałbyś odrzucone ramki do /sdcard/pending/ i ponawiał próby w wolniejszej pętli – to kilka dodatkowych linii na każdy przypadek, ponad to, co pokazano.
10.13.4. Czego requests nie robi¶
Port dla MicroPythona jest celowo niewielki. Kilka rzeczy, które robi requests z CPythona, a których ten nie robi:
Pula połączeń. Każde wywołanie otwiera nowe połączenie TCP.
Automatyczne ponawianie przy przejściowych błędach. Opakuj wywołanie samodzielnie.
Strumieniowanie odpowiedzi.
r.contentjest w całości wczytywany do RAM; nie ma odpowiednikastream=True.Automatyczna dekompresja odpowiedzi spakowanych gzipem. Ustaw nagłówek
Accept-Encodingjawnie tylko wtedy, gdy serwer jest do tego skonfigurowany.
Pełną listę metod oraz to, co jest w zakresie i poza nim, znajdziesz w requests — Klient HTTP.
HTTPS działa od razu – napędza go schemat URL, a domyślny kontekst SSL jest tworzony w locie. Aby zweryfikować certyfikat archiwum względem pakietu CA wczytanego na kamerę, zobacz sekcję jako klient w Weryfikacja publicznego serwera (kamera jako klient).
Aplikacja jest w pełni gotowa: podgląd na żywo, wykrywanie ruchu, panel z logowaniem, HTTPS, CORS/CSRF, archiwum w chmurze.