Страницы

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

понедельник, 6 января 2020 г.

Python, Flask и PiCamera

#python #raspberry_pi


Имеется 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,
запрос отправляется бесконечно. 
Далее есть после старта, отправить запрос на стоп, ничего не происходит. Где я что,
сделал не правильно? Есть ли способ, каким-то образом записать все в одну функцию,
но при это вызывать разным запросом определенные части функции?
    


Ответы

Ответ 1



Попробую угадать ответ по документации 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-сервера из первого потока вместо непосредственного доступа к камере, но это увеличивает сложность и не факт что целесообразно в данном случае.)

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

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