14

I am just getting started into python and flask (for the raspberry pi). I want a web application that would execute some python code to pan and tilt a camera and display a video stream.

My code up until now for flask is:

from flask import Flask, render_template
import time
import serial
#ser = serial.Serial('/dev/ttyUSB0',9600)
app = Flask(__name__)
@app.route('/')
@app.route('/<cmd>') #each button in my html redirects to a specified directory
def execute(cmd=None):
    if cmd == "down":
        print "Moving Down"
        #ser.write("D")

    if cmd == "up":
        print "Moving Up"
        #ser.write("U")

    if cmd == "left":
        print "Moving Left"
        # ser.write("L")

    if cmd == "right":
        print "Moving Right"
        #ser.write("R")

    if cmd == "reset":
        print "Reseting.."
        #ser.write("X")

    return render_template("main.html")


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080, debug=True)

The problem is my code relies on the each button redirecting to a new directory, while this does work well, it refreshes the page each time which means my embedded video reloads and buffers again. Is there a better way of detecting a button press and then executing python code using flask?

1
  • 3
    For that, you'll need to use AJAX calls from JavaScript running on the page. Commented Feb 5, 2014 at 1:14

3 Answers 3

15

I would split it out into two routes to make it easier to see what you have to do:

LEFT, RIGHT, UP, DOWN, RESET = "left", "right", "up", "down", "reset"
AVAILABLE_COMMANDS = {
    'Left': LEFT,
    'Right': RIGHT,
    'Up': UP,
    'Down': DOWN,
    'Reset': RESET
}

@app.route('/')
def execute():
    return render_template('main.html', commands=AVAILABLE_COMMANDS)

@app.route('/<cmd>')
def command(cmd=None):
    if cmd == RESET:
       camera_command = "X"
       response = "Resetting ..."
    else:
        camera_command = cmd[0].upper()
        response = "Moving {}".format(cmd.capitalize())

    # ser.write(camera_command)
    return response, 200, {'Content-Type': 'text/plain'}

Then in your template you just need to use some JavaScript to send off the request:

{# in main.html #}
{% for label, command in commands.items() %}
    <button class="command command-{{ command }}" value="{{ command }}">
        {{ label }}
    </button>
{% endfor %}

{# and then elsewhere #}
<script>
// Only run what comes next *after* the page has loaded
addEventListener("DOMContentLoaded", function() {
  // Grab all of the elements with a class of command
  // (which all of the buttons we just created have)
  var commandButtons = document.querySelectorAll(".command");
  for (var i=0, l=commandButtons.length; i<l; i++) {
    var button = commandButtons[i];
    // For each button, listen for the "click" event
    button.addEventListener("click", function(e) {
      // When a click happens, stop the button
      // from submitting our form (if we have one)
      e.preventDefault();

      var clickedButton = e.target;
      var command = clickedButton.value;

      // Now we need to send the data to our server
      // without reloading the page - this is the domain of
      // AJAX (Asynchronous JavaScript And XML)
      // We will create a new request object
      // and set up a handler for the response
      var request = new XMLHttpRequest();
      request.onload = function() {
          // We could do more interesting things with the response
          // or, we could ignore it entirely
          alert(request.responseText);
      };
      // We point the request at the appropriate command
      request.open("GET", "/" + command, true);
      // and then we send it off
      request.send();
    });
  }
}, true);
</script>
Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thankyou for your answer, but as i am new to javascript i dont really understand how this works and i am not getting this to work :/ could you pls show me how to deal with just one button press in the simplest way, which would print "X" on python? i would study that in detail.
@user3264137 - what errors show up in your browser's debugging console when you load the page? (I am assuming that that is what is breaking, rather than the back-end code).
I tried this but now when I click 'Submit', instead of going to a new page, I get a Client disconnected.
0

I've got the same problem, and the answer is simple using ajax XmlHttpRequest:

// send a request, but don't refresh page
xhttp = new XMLHttpRequest();
xhttp.open("GET", "your script action", true);
xhttp.send();

Here's a small example, calling current script with parameters "like", embedded in a function:

function likeStuffs()
{
    // send a request, but don't refresh page
    xhttp = new XMLHttpRequest();
    xhttp.open("GET", "?like", true);
    xhttp.send();
}

Comments

0

You can simply do this with help of AJAX... Here is a example which calls a python function which prints hello without redirecting or refreshing the page.

In app.py put below code segment.

//rendering the HTML page which has the button
@app.route('/json')
def json():
    return render_template('json.html')

//background process happening without any refreshing
@app.route('/background_process_test')
def background_process_test():
    print "Hello"
    return "nothing"

And your json.html page should look like below.

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type=text/javascript>
        $(function() {
          $('a#test').bind('click', function() {
            $.getJSON('/background_process_test',
                function(data) {
              //do nothing
            });
        return false;
      });
    });
</script>


//button
<div class='container'>
<h3>Test</h3>
    <form>
        <a href=# id=test><button class='btn btn-default'>Test</button></a>
    </form>

</div>

Here when you press the button Test simple in the console you can see "Hello" is displaying without any refreshing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.