pyledriver/webInterface.py

85 lines
2.8 KiB
Python

from multiprocessing import Process
from sharedLogging import SlaveLogger
from flask import Flask, render_template, Response, Blueprint, redirect, url_for
from flask_wtf import FlaskForm
from wtforms.fields import SelectField, StringField, SubmitField
from wtforms.validators import InputRequired
class CamForm(FlaskForm):
fps = SelectField(choices=[(i, '%s fps' % i) for i in range(10, 31, 5)], coerce=int)
submitFPS = SubmitField('Set')
class TTSForm(FlaskForm):
tts = StringField(validators=[InputRequired()])
submitTTS = SubmitField('Speak')
class ResetForm(FlaskForm):
submitReset = SubmitField('Reset')
# TODO: fix random connection fails (might be an nginx thing)
# TODO: show camera failed status here somewhere
class WebInterface(Process):
def __init__(self, camera, stateDict, ttsQueue, loggerQueue):
self._moduleLogger = SlaveLogger(__name__, 'INFO', loggerQueue)
self._flaskLogger = SlaveLogger('werkzeug', 'ERROR', loggerQueue)
camPage = Blueprint('camPage', __name__, static_folder='static', template_folder='templates')
def generateFrame():
while 1:
yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + camera.getFrame() + b'\r\n')
@camPage.route('/', methods=['GET', 'POST'])
@camPage.route('/index', methods=['GET', 'POST'])
def index():
props = camera.getProps('FPS')
fps = int(props['FPS'])
camForm = CamForm(fps = props['FPS'])
ttsForm = TTSForm()
resetForm = ResetForm()
if camForm.validate_on_submit() and camForm.submitFPS.data:
camera.setProps(FPS=camForm.fps.data)
return redirect(url_for('camPage.index'))
if ttsForm.validate_on_submit() and ttsForm.submitTTS.data:
ttsQueue.put_nowait(ttsForm.tts.data)
return redirect(url_for('camPage.index'))
if resetForm.validate_on_submit() and resetForm.submitReset.data:
camera.reset()
return redirect(url_for('camPage.index'))
return render_template(
'index.html',
camForm=camForm,
ttsForm=ttsForm,
resetForm=resetForm,
fps=fps,
state=stateDict['name']
)
@camPage.route('/videoFeed')
def videoFeed():
return Response(generateFrame(), mimetype='multipart/x-mixed-replace; boundary=frame')
self._app = Flask(__name__)
self._app.secret_key = '3276d68dac56985bea352325125641ff'
self._app.register_blueprint(camPage, url_prefix='/pyledriver')
super().__init__(daemon=True)
def run(self):
# TODO: not sure exactly how threaded=True works, intended to enable
# multiple connections. May want to use something more robust w/ camera
# see here: https://blog.miguelgrinberg.com/post/video-streaming-with-flask
self._moduleLogger.info('Started web interface')
self._app.run(debug=False, threaded=True)
def stop(self):
self.terminate()
self.join()
self._moduleLogger.info('Terminated web interface')