Friday, May 13, 2016

Control LED through Webpage PIP using Raspberry pi 3

Sending input to your raspberry pi through Flask

What you will need:

  • Raspberry pi with raspbian & SSH set up already
  • LED
  • 1 - 50 ohm resistor
  • Small gauge solid core wire
  • Breadboard
  • Some basic knowledge of python syntax

Setting up the wiring

The first thing you'll need to do is wire up your raspberry pi to the LED. See the diagram below for wiring it up.
diagram

Installing dependencies

Once you've wired it up, we can start preparing to code on the raspberry pi - first we need to install some dependencies:
To install pip and Flask, first we SSH into the raspberry pi, then run the following command:
sudo apt-get install python-pip && pip install Flask
This will install pip, then if that succeeds it will install Flask using pip. If you used NOOBS to install raspbian on a low capacity memory card, you may not have the free space to install pip and flask. To fix this, simply install Raspbian alone without using NOOBS. See this guide for details on how to do that.

Setting up Flask

Now that we have pip and Flask installed, let's set up the files/folders we need to run Flask.
Run the following commands:
cd ~/
mkdir Flask
cd Flask
touch flask_rpi.py
mkdir templates
cd templates
touch index.html
So now we have the following files/folders:
/home
    /user
        /Flask
            flask_rpi.py
            /templates
                index.html
Let's open up our flask_rpi.py file and add some basics to it so we can display index.html
Use the following command to open it in Nano, a text editor.
nano ~/Flask/flask_rpi.py

from flask import Flask, render_template
app = Flask(__name__)

@app.route("/")
def hello():
    return render_template("index.html")

if __name__ == "__main__": 
    app.run(debug=True, host="0.0.0.0")
What does the above code do?
  1. First we import the Flask class from the flask module along with the render_template function
  2. Then we create the Flask object by passing it the __name__ of our python file.
  3. We then define a route @app.route("/") which tells flask to bind the proceeding function to that route. ("/") is the root URL, or "http://192.168.1.1:5000/" (your RPi's IP address)
  4. The function for the route we set up simply returns index.html as a template - we aren't using Flask's templating system in this example, but we will in the future.
  5. Finally, we run the app in debug mode which starts up a local development server that can provide tracebacks if we run into errors.
  6. CTRL+X and Y then Enter to save the file.
Next, on the command line, do:
python ~/Flask/flask_rpi.py
This will run the flask server.
Now we need to go to our raspberry pi's IP address in the browser, this is the same IP you use to SSH into. For example http://192.168.1.1:5000/ - :5000 is the default port for flask and is necessary to connect to our local server.
Providing everything was done correctly, when you load up your raspberry pi's IP address on port 5000 in your browser, you should see.. Nothing! Don't panic - a blank page is exactly what should be displayed, because we have yet to put anything inside of index.html!
Cancel the flask server with CTRL+C

Creating our index page

Now we need to edit index.html which is inside our templates folder:
nano ~/Flask/templates/index.html
Now that we're in, let's add some basics - We need a way to send input to the raspberry pi, so let's add a button.
<!doctype html>
<html lang="en">
<head>
    <title>RPi input</title>
</head>
<body>
<button data="/led/">Toggle LED</button>
</body>
</html>
Now if we go and load up the RPi in our browser again, we get a button - unfortunately, that button doesn't do much until we give it something to do. We'll add functionality to the button using jQuery, a javascript library that makes interacting with elements on a page very easy.
Below the button, we're going to add the javascript - don't worry if you're not familiar with javascript, i'll explain what the javascript does.
<button data="/led/">Toggle LED</button>

<script src="https://code.jQuery.com/jQuery-1.11.2.js"></script>

<script>
var button = $("button"),
    url = button.attr("data");

button.on("click", function () {
        $.ajax({
            url: url,
            success: function (response) {
                console.log(response)
                if (response === "True") {
                    button.css("background-color", "green")
                } else {
                    button.css("background-color", "red")
                }
            }
        })
    })
</script>
First off we load jQuery from their website - you can host your own copy of jQuery but for the sake of simplicity i'll use jQuery's website.
We then use jQuery ($ is shorthand for the jQuery object) to wrap the button as a jQuery object. This allows us to execute jQuery functions on the button. After we have the button, we grab what is in the "data" attribute - this is our url we'll be sending requests to.
on() is one such jQuery function - it allows us to put an "event handler" on the button object, which means that it is constantly listening for whatever event we tell it to listen for. We want to know when the button is clicked, so we tell it to look for click events.
button.on("click").on()
jQuery requires us to pass it a function to execute when the click event happens - which we do with button.on.("click",function(){}) - the code within the {} is what will be executed whenever the button is clicked.
So what does the function do?
We're using jQuery's ajax function to send a request to the flask server at the url we grabbed from the button's data attribute - if the local server responds with a status 200 code, meaning our request was successful, it will check the response to see if the server responded with "True" or not and update the buttons background colour accordingly.
If you now refresh the page and click on the button, you'll see it does.. Nothing! This is because we haven't set up our server to respond when a web request comes in at any route other than the root ("/") route - we need to go edit our flask_rpi.py file to respond with something!

Responding to requests with flask

Let's go back to our flask_rpi.py file and make some additions so we can respond to the jQuery requests.
nano ~/Flask/flask_rpi.py

from flask import Flask, render_template
import RPi.GPIO as GPIO
import threading
import time

app = Flask(__name__)

@app.route("/")
def hello():
    return render_template("index.html")

@app.route("/led/")
def toggle_led():
    global looping
    looping = not looping
    threading.Thread(target=loop_till_false).start()
    return str(looping)

def loop_till_false():
    while looping:
        GPIO.output(7, True)
        time.sleep(0.1)

if __name__ == "__main__":
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(7, GPIO.OUT)
    looping = False
    app.run(debug=True, host="0.0.0.0")
We set up a function loop_till_false - when called, this will continually send power to whatever is on pin 7 of the GPIO pins, untill the global variable looping is set to False
Next we set up a route for '/led/', which runs the function toggle_led(). toggle_led() will access the global variable looping which is set to False when our script starts. Whenever we go to 192.168.1.1:5000/led/ (your RPi's IP:5000/led/), we will set looping to equal not looping - which means the opposite of whatever the variable looping is at the moment:
@app.route("/led/")
def toggle_led():
    global looping
    looping = not looping
    threading.Thread(target=loop_till_false).start()
    return str(looping)
This will allow us to toggle our LED on/off. After toggling looping, we spawn a new thread and give it the loop_till_false function we defined earlier to run. The reason we do this is because if we were to run the function on the same thread as our flask server, the server would stop working untill the loop_till_false function stopped - which would be never, as the flask server wouldn't be able to receive our requests to toggle the looping variable!
Once you've got the latest flask_rpi.py saved, run the file:
python ~/Flask/flask_rpi.py
Open up your browser and go to http://192.168.1.1:5000/ where 192.168.1.1 is the IP of your RPi. You should now be able to toggle the button on/off and have your LED turn on/off accordingly.

Congratulations, you've successfully used Flask to send input to your Raspberry pi!

R

No comments:

Post a Comment