0

This is a question continue from this question here.

I am trying to control a servo motor using the image buttons on my web page. My servo controller is in the form of python script (cameraservo2.py) and I am using jQuery to post the data to the python function. The conclusion that I get from asking "how to run python script from webpage" is by using 'Flask' which is totally new to me. However I have installed it successfully using just pip install Flask. (let me know if i miss out anything?)

I have my index.html, cameraservo3.py and routes.py in my /var/wwwfolder. My webserver is by default running and I can access it by my Raspberry Pi IP address from another network computer.

This is my routes.py code:

from flask import Flask, jsonify, render_template, request
from cameraservo3 import turnCamera

app = Flask(__name__)

@app.route('/turn_servo', methods=['POST'])
def turn_servo_ajax():
    direction = request.form['direction']
    cam_result = turnCamera(direction=direction)
    return '<div> {} </div>'.format(cam_result)   

if __name__ == '__main__':
    app.debug = True
    app.run(host='0.0.0.0')

Part of my jQuery script in index.html:

$('#left_button').click(function(){
            $.post("/turn_servo", {direction:"left"}).done(function (reply) {
                $('#camerapos').empty().append(reply);
                alert("left button clicked");});

        });

part of my html:

<div id="control_button">
    <img src="button_left.png" id="left_button" height="50" width="50">
    <img src="button_right.png" id="right_button" height="50" width="50">
    <p id="camerapos"> test </p>
  </div>

cameraservo2.py can be found in the answer for my question there. I run python routes.py and it gave me

 * Running on http://0.0.0.0:5000/
 * Restarting with reloader

But the script (cameraservo2.py) doesn't get executed when I click the left_button. What's wrong? Which part have I done wrong??

The quickstart guide of Flask isn't very helpful as well. :/

Community
  • 1
  • 1
yvonnezoe
  • 7,129
  • 8
  • 30
  • 47
  • replace the `your_cam_function` with `turnCamera`. `turnCamera` is supposed to be the function to call. – msvalkon Mar 03 '14 at 08:17
  • Is there actually an element in your DOM with an ID of `left_button`? Does it appear before or *after* this script in the DOM? Is there an element with the ID of `camerapos` in the DOM? Seeing the key bits of your `index.html` template would help :-) – Sean Vieira Mar 03 '14 at 08:46
  • @msvalkon sorry bout the mistake. yes, i did use `turnCamera` in my code but still nothing happens. i suspect my problem may be about the :5000 port... but how can i troubleshoot where is problem? – yvonnezoe Mar 03 '14 at 11:54
  • 3
    You'll need to load the `index.html` page from the flask server as well; you can make it a static page or a new route at `/` that returns the script. Otherwise you run into a [same origin policy](https://en.wikipedia.org/wiki/Same-origin_policy) violation; a page at `http://localhost/` isn't allowed to use AJAX to post to `http://localhost:5000` (different port numbers). – Martijn Pieters Mar 03 '14 at 11:54
  • @SeanVieira yes i do. updated my question as above. :) and it is after the script. – yvonnezoe Mar 03 '14 at 11:56
  • @MartijnPieters ahh, that makes sense! so you mean, i should do another @app.route() for index.html too right? – yvonnezoe Mar 03 '14 at 11:57
  • @yvonnezoe: exactly; it can use a template to render that page; that'd allow you to use the `url_for()` function to let Flask fill in the target URL for the `$.post()` call, for example. – Martijn Pieters Mar 03 '14 at 11:58
  • hmm totally new to Flask here, so those terms are still confusing. but will do more research based on the direction you gave me. thank you! :) – yvonnezoe Mar 03 '14 at 11:59
  • @MartijnPieters umm wait, just a quick question here. is it similar to cherrypy?? in this case, i have a camera app running on the server (not sure what it is running on, the developer hasnt reply me) and i have no idea how to let it run on cherrypy server. so if flask is the same as cherrypy, it can't solve my problem. oh no. :( – yvonnezoe Mar 03 '14 at 12:04
  • @yvonnezoe: CherryPy is another Python web server, so yes, Flask and CherryPy are similar. Flask is a little newer, a little easier to work with (in my experience). But you should be able to get CherryPy to do the same thing here. – Martijn Pieters Mar 03 '14 at 12:07

1 Answers1

3

You'll run into the same-origin policy restrictions unless you serve the index.html file from the same host and port number. It's easiest to just add the index.html page to your Flask server too.

Add a / route that serves the page that will do the AJAX post. You could use a template to fill in the route here for $.post() to. If using Jinja2 for the template, that would be:

@app.route('/')
def homepage():
    return render_template('index.html')

and the file index.html in the templates subdirectory of your Flask project with:

$('#left_button').click(function(){
        $.post("{{ url_for('turn_servo_ajax') }}", {direction:"left"}).done(function (reply) {
            $('#camerapos').empty().append(reply);
            alert("left button clicked");});

    });

where the {{ }} part is Jinja2 template syntax, and url_for() returns a fully-formed URL for the turn_servo_ajax view function.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Thank you. I created a new folder called `templates` in /var/www directory and put all necessary files, i.e. index.html, jquery js and css file and images, into the folder. But my formatting is all gone. now i can't even click on the button... – yvonnezoe Mar 03 '14 at 12:26
  • @yvonnezoe: that usually means the links in the ` – Martijn Pieters Mar 03 '14 at 12:28
  • but it shouldn't be. because i put all of them in the same directory as index.html and it was working fine in the /var/www... :( – yvonnezoe Mar 03 '14 at 12:30
  • 1
    @yvonnezoe: ah, right, but templates need to be loaded explicitly. But static information in the `static` folder and adjust the urls to load `static/filename.css` instead. – Martijn Pieters Mar 03 '14 at 12:34
  • ahhhh i was so hopeful that that's the only problem but nothing happens after i clicked on the img again. I looked at the terminal and it returns me quite some errors... i pasted them here: http://pastebin.com/eGgVQnML do i have to put jsonify or anything else at anywhere? – yvonnezoe Mar 03 '14 at 13:31
  • 1
    @yvonnezoe: That's 3 times the same error; the Flask code is working but apparently the `cameraservo3.turnCamera()` does something wrong. – Martijn Pieters Mar 03 '14 at 13:36
  • Hmm that's true. but this section of code should give `m` a number.. `m=1500 while (m >= 500 and m <= 2500): if (key =="left"): m=m+100 elif (key =="right"): m=m-100` Anyway, I am sure this code won't work practically because it will initialize `m=1500` everytime i click it, which is unwanted. but i will settle that later. – yvonnezoe Mar 03 '14 at 13:37
  • it's working? :D yayy! so now i'm moving to next phase of troubleshooting! thank you so much for your guidance and help! – yvonnezoe Mar 03 '14 at 13:37
  • Well, the bottom line is that your *Flask* code works. :-) The POST arrives, the view does what it is supposed to do. – Martijn Pieters Mar 03 '14 at 13:38