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 і отримати свіжий кадр.