10.13. Tải các khung hình được kích hoạt lên đám mây¶
Khi phát hiện chuyển động, camera bây giờ sẽ sáng lên bảng điều khiển. Điều đó đủ cho việc sử dụng trực tiếp, nhưng chủ nhân cũng muốn có một kho lưu trữ vĩnh viễn của mọi khung hình được kích hoạt, được lưu trữ ở đâu đó bên ngoài camera. Đây là một lệnh gọi HTTP ra ngoài -- camera đóng vai trò là client.
10.13.1. Camera với vai trò là client¶
Module requests là HTTP client hướng ra ngoài của camera. Giao diện của nó là bản sao có chủ ý từ requests của CPython -- cùng các hàm module được đặt tên theo động từ, cùng các đối số từ khóa files=, json=, headers=, auth=. Nếu bạn đã thực hiện các lệnh gọi HTTP từ CPython thì bạn đã biết API này:
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() mở kết nối TCP, gửi yêu cầu và trả về Response với status_code, reason, headers, content, json() và các thuộc tính quen thuộc còn lại.
files={...} tạo nội dung multipart/form-data. Giá trị là một tuple (filename, file-like); requests.post() đọc file-like theo từng đoạn để toàn bộ ảnh JPEG không cần phải được đệm lại vào một chuỗi trước. io.BytesIO bọc các byte JPEG đã có trong bộ nhớ để chúng hiển thị giao diện đọc như file.
headers={...} là một dict thông thường được gửi dưới dạng header yêu cầu -- ở đây, một token bearer ở vị trí Authorization tiêu chuẩn. Nhà cung cấp lưu trữ ghi lại định dạng token họ muốn; ví dụ là dạng phổ biến nhất.
10.13.2. Kết nối vào bộ phát hiện chuyển động¶
Coroutine phát hiện chuyển động được giới thiệu trước đó đã chạy trên mỗi khung hình mới và kích hoạt khi change > state['threshold']. Thêm lệnh tải lên đó, nhưng kích hoạt nó như một tác vụ nền để bộ phát hiện không dừng theo dõi trong khi quá trình tải lên đang diễn ra:
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() lên lịch cho coroutine tải lên và trả về ngay lập tức. Bộ phát hiện tiếp tục lấy các khung hình; quá trình tải lên chạy song song với nó; camera không bao giờ bị dừng lại.
10.13.3. Các trường hợp lỗi¶
Mã mạng có thể thất bại. Camera có thể ngoại tuyến, kho lưu trữ có thể ngừng hoạt động, token bearer có thể đã hết hạn. Các loại đáng bắt được:
OSError-- kết nối TCP không thể được mở hoặc đã bị đóng giữa chừng khi truyền. Lỗi DNS, không có tuyến đường, kết nối bị đặt lại.requestsném ra chính xác ngoại lệ này.status_code >= 400-- máy chủ đã nhận yêu cầu và từ chối. 401 cho token hết hạn, 403 cho token bị thu hồi, 413 cho nội dung quá lớn, 5xx cho kho lưu trữ không hoạt động bình thường.Hết thời gian chờ âm thầm --
requestssử dụng thời gian chờ socket mặc định (vài giây); sau đó nó ném raOSErrorvớierrno.ETIMEDOUT.
Đối với kho lưu trữ thực sự quan trọng, bạn nên xếp hàng các khung hình bị từ chối vào /sdcard/pending/ và thử lại trong một vòng lặp chậm hơn -- đó là thêm vài dòng cho mỗi trường hợp, trên những gì đã hiển thị.
10.13.4. requests không làm gì¶
Cổng MicroPython được thiết kế nhỏ một cách có chủ ý. Một vài điều mà requests của CPython làm nhưng phiên bản này thì không:
Gộp kết nối. Mỗi lệnh gọi mở một kết nối TCP mới.
Tự động thử lại khi gặp lỗi tạm thời. Hãy tự bọc lệnh gọi.
Phản hồi dạng luồng.
r.contentđược đọc vào RAM đầy đủ; không có tương đươngstream=True.Giải nén tự động các phản hồi được nén gzip. Chỉ đặt header
Accept-Encodingmột cách rõ ràng nếu máy chủ được cấu hình cho điều đó.
Xem requests --- HTTP client để có danh sách phương thức đầy đủ và những gì có trong / ngoài phạm vi.
HTTPS hoạt động ngay lập tức -- sơ đồ URL điều khiển nó và ngữ cảnh SSL mặc định được tạo ra khi cần. Để xác minh cert của kho lưu trữ so với bộ CA bundle bạn đã tải lên camera, hãy xem phần as a client của Xác minh máy chủ công cộng (camera đóng vai trò client).
Ứng dụng đã được hoàn thiện đầy đủ: xem trực tiếp, phát hiện chuyển động, bảng điều khiển có đăng nhập, HTTPS, CORS/CSRF, kho lưu trữ đám mây.