Ajax POST для Flask не работает после обновления страницы - PullRequest
0 голосов
/ 07 ноября 2018

Я совершенствую систему удаленного управления телескопом. Raspberry Pi запускает колбу и предоставляет видеопоток для камеры, прикрепленной к телескопу. Фокусер телескопа приводится в действие шаговым двигателем, управляемым Arduino. Сервер предоставляет веб-сайт, который показывает видеопоток, и предлагает две кнопки для перемещения и фокусировки фокуса.

При нажатии любой кнопки клиент отправляет сообщение POST в RasPi, а затем RasPi сообщает Arduino о перемещении фокусера. Но принципиально я не хотел, чтобы страница обновлялась при перефокусировке. Поэтому я использовал jQuery и Ajax для подавления обновления страницы.

Соответствующие фрагменты кода здесь:

Код Python / Flask:

@app.route('/stream/<wcam>', methods=['GET'])
def stream_get(wcam):
    class FocuserForm(FlaskForm):
        nsteps = IntegerField('# steps: ', default=1)
        focuser_in = SubmitField('Focuser in')
        focuser_out = SubmitField('Focuser out')

    form = FocuserForm()
    return render_template('stream.html', wcam=wcam, form=form)

@app.route('/stream/<wcam>', methods=['POST'])
def stream_post(wcam):
    results = request.form
    arduino_serial = SerialFocuser()
    if results['caller'] == "focuser_in":
        command = "MVD" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    elif results['caller'] == "focuser_out":
        command = "MVU" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    return ''

Интернет (stream.html):

<html>
    <head>
        <title>Video Streaming</title>
        <style>
            ...
        </style>

        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

        <script>
                $(document).ready(function() {});
        </script>
      </head>

    <body>
        <h1>Streaming camera {{ wcam }}</h1>
        <br>
        <img id="bg" src="{{ url_for('video_feed', wcam=wcam) }}", height="480" width="640">
        <a href="{{ url_for('index') }}">Back</a>
        <br>


    <!--######################################################-->
    <!--#  Focuser handling -->
    <!--######################################################-->

    <br>
    <form id="flaskform" method="POST">
        <p>
        {{ form.nsteps.label }} {{ form.nsteps() }} &nbsp;
        {{ form.focuser_in() }} &nbsp;
        {{ form.focuser_out() }}
        </p>
    </form>

    <script>
    // $(document).ready(function() { // Moved to header

            var form = document.getElementById('flaskform');
            function onSubmit(event) {
                console.log('onSubmit function');
                var objectID = event.explicitOriginalTarget.id;
                var nsteps = form.nsteps.value;
                var return_data = {caller: "", steps: nsteps};
                if (objectID == "focuser_in") {
                    return_data.caller = objectID;
                    console.log("Focuser_in detected");
                } else if (objectID == "focuser_out") {
                    return_data.caller = objectID;
                    console.log("Focuser_out detected");
                } else if (objectID == "nsteps") {
                    console.log("nsteps detected");
                    event.preventDefault();
                    return;
                } else {
                    console.log("No matches");
                    return;
                }
                console.log("About to run Ajax");
                $.ajax({
                    url: "stream.html",
                    type: "post",
                    data: return_data,
                    success: function(response) {
                        console.log('It worked!');
                    },
                    error: function(xhr, status, text) {
                        console.log('An error occurred:', status,"; ", text);

                    },
                    timeout: 1000 // 1s
                }); // Ajax
                console.log("After running Ajax");
                if (event) { event.preventDefault(); }

            }
            // prevent when a submit button is clicked
            form.addEventListener('submit', onSubmit, false);

            //<!--form.addEventListener('submit', onSubmit, false);-->
            // prevent submit() calls by overwriting the method
            form.submit = onSubmit;

    //});  // Moved to header
    </script>
    </body>
</html>

Проблема заключается в следующем:

Если я обновлю страницу в браузере клиента, а затем нажму кнопку, ajax выполнит POST, но колба не получит ее. Время ожидания запроса истекло.

Если я теперь перезагружаю сервер (я разрабатываю это с помощью PyCharm, поэтому я просто нажимаю повторно запустить), не обновляя страницу в клиенте, а затем нажимаю кнопку, колба получает POST, и фокусер работает как шарм.

Если я обновлю страницу еще раз, кнопки перестанут работать, пока я не перезагружу сервер.

Почему это происходит? Очевидно, что код работает по своему основному назначению, но каким-то образом обновление страницы что-то ломает.

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Спасибо @Peter van der Wal за указание на решение.

Видеопоток имеет петлю while True, которая непрерывно принимает кадры с камеры, следовательно, блокируя поток.

Решением было запустить приложение с опцией с резьбой на :

До:

app.run(host='0.0.0.0', debug=True)

Сейчас:

app.run(host='0.0.0.0', debug=True, threaded=True)

Это позволяет потоку потокового видео продолжаться самостоятельно, в то же время позволяя серверу обрабатывать другие команды.

0 голосов
/ 07 ноября 2018

Однажды у меня была похожая проблема с потоком камеры, блокирующим все вызовы. Когда вы перезагружаете сервер, работает ли ваш канал камеры (до нажатия кнопки)? Потому что, в основном, вы вызываете канал с вашей камеры дважды - сначала с помощью вызова get, когда вы обновляете страницу, а затем снова с помощью пост-вызова.

Я бы посоветовал вам преобразовать представленный код в альтернативную функцию для ясности:

@app.route('/stream/<wcam>', methods=['POST'])
def moveCommand:
       if form.is_submitted():
    # POST method
    results = request.form
    arduino_serial = SerialFocuser()
    if results['caller'] == "focuser_in":
        command = "MVD" + results['steps'] + "\n"
        arduino_serial.send_command(command)
    elif results['caller'] == "focuser_out":
        command = "MVU" + results['steps'] + "\n"
        arduino_serial.send_command(command)

Так что в основном вы сохраняете метод get только для потоковой передачи и используете сообщение для перемещения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...