Страницы

Поиск по вопросам

четверг, 14 февраля 2019 г.

Python, Flask и PiCamera

Имеется PiCamera с RPi. Пытаюсь написать Python код для управления камерой с помощью веб. В данный момент мой код выглядит вот так
#!/usr/bin/env python # -*- coding: utf-8 -*- ''' Test version '''
from flask import Flask from datetime import datetime import io import time import picamera import logging import sys import os
app = Flask(__name__)
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s ' + '[%(filename)s:%(lineno)s:%(funcName)s()] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
@app.route("/start", methods=['POST']) def start_capture(): with picamera.PiCamera() as camera: camera.resolution = (1920, 1080) camera.start_preview() time.sleep(300)
@app.route("/stop", method=['POST']) def stop_capture(): with picamera.PiCamera() as camera: camera.stop_preview()
@app.route("/screenshot", methods=['POST']) def screenshot(): with picamera.PiCamera() as camera: camera.capture('foo.jpg', use_video_port=True)
if __name__ == "__main__": app.run(host='192.168.0.198', port='8080')
Первое что не работает правильно - если я отправляю POST запрос к примеру на 192.168.192:8080/start, запрос отправляется бесконечно. Далее есть после старта, отправить запрос на стоп, ничего не происходит. Где я что, сделал не правильно? Есть ли способ, каким-то образом записать все в одну функцию, но при это вызывать разным запросом определенные части функции?


Ответ

Попробую угадать ответ по документации picamera. Согласно ей, при входе в with-блок камера включается, а при выходе выключается, то есть получается:
@app.route("/start", methods=['POST']) def start_capture(): with picamera.PiCamera() as camera: # Включили камеру camera.resolution = (1920, 1080) camera.start_preview() # with закончился — выключили камеру
Отсюда вывод: надо как-то держать камеру постоянно включенной независимо от http-запросов. Простейший способ — вынести camera в глобальную переменную, где она и будет лежать включенная независимо от http-запросов:
from threading import Lock import picamera
camera = None # Сразу после запуска камера выключена
camlock = Lock() # Блокировка нужна, чтобы нельзя было # лезть в камеру из нескольких запросов одновременно
# ... app = Flask(__name__) logging всё такое скопировать сюда из вопроса #
@app.route("/start", methods=['POST']) def start_capture(): global camera with camlock: if camera: return 'already started' camera = picamera.PiCamera() camera.resolution = (1920, 1080) return 'ok'
@app.route("/stop", methods=['POST']) def stop_capture(): global camera with camlock: if not camera: return 'already stopped' camera.close() camera = None return 'ok'
@app.route("/screenshot", methods=['POST']) def screenshot(): # Переменную не меняем — global необязателен with camlock: if not camera: return 'camera is not started' camera.capture('foo.jpg', use_video_port=True) return 'saved to foo.jpg'
if __name__ == "__main__": try: app.run(host='192.168.0.198', port='8080') finally: # При завершении работы http-сервера камеру стоит выключить with camlock: if camera: camera.close()
Raspberry Pi не имею и проверить работоспособность кода не могу, но вроде не должен был накосячить.
(Замечание 1: глобальные переменные — довольно опасная штука, и при увеличении сложности проекта от них можно начать получать множество проблем, когда они начнут меняться непредсказуемо и всё такое.)
(Замечание 2: возможно, более хорошим решением будет запуск второго потока, который и будет обслуживать камеру (без глобальной переменной) и принимать сообщения-команды от http-сервера из первого потока вместо непосредственного доступа к камере, но это увеличивает сложность и не факт что целесообразно в данном случае.)

Комментариев нет:

Отправить комментарий