10.2. Повернення знімка#
Кінцева точка статусу – це добре, але причина існування камери – це об’єктив. Додайте кінцеву точку, що повертає JPEG того, що датчик бачить прямо зараз.
import csi
from microdot import Response
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
@app.get('/snapshot.jpg')
async def snapshot(request):
img = csi0.snapshot().compress(quality=85)
return Response(
body=img.bytearray(),
headers={'Content-Type': 'image/jpeg'},
)
Відкрийте http://<cam-ip>/snapshot.jpg у браузері, і у вкладці з’явиться JPEG поточного виду. Оновіть сторінку – отримаєте свіжий знімок.
10.2.1. Об’єкт Response#
Обробник, що повертає словник, дозволяє microdot зробити все інше. JPEG-байти потребують повної форми: явно побудованого microdot.Response. Аргумент body приймає будь-яке байтоподібне значення – буфер image.Image камери доступний через bytearray(), тому той самий буфер, у який записав датчик, відправляється прямо до сокета.
Content-Type: image/jpeg повідомляє браузеру, що тіло відповіді є зображенням. Без цього браузер намагатиметься відобразити JPEG-байти як текст, і ви побачите екран беззмістовних символів.
image.Image.compress() виконує JPEG-кодування наявного буфера зображення на місці і повертає те саме зображення (тепер у форматі JPEG), щоб його байти можна було відправити без змін. quality=85 – звичайне значення за замовчуванням – достатньо високе для чіткого зображення, і достатньо низьке, щоб файл вмістився через повільне з’єднання.
10.2.2. Захоплення блокує цикл#
csi.CSI.snapshot() чекає, поки датчик завершить витримку та передачу кадру через DMA, перш ніж повернути результат. Усередині асинхронного обробника це означає, що цикл подій зупиняється на час витримки – десять, двадцять, п’ятдесят мілісекунд залежно від освітлення. При одному клієнті, що запитує один маршрут за раз, це непомітно; але при кількох клієнтах або сопрограмі захоплення, що виконується паралельно, це заблокує все інше.
Неблокуючий варіант snapshot() існує для випадку з кількома сопрограмами (blocking=False повертає наступний готовий кадр або None). Для одного знімка на запит стандартний блокуючий виклик є прийнятним.
Тепер власник може відкрити URL і отримати свіжий кадр.