Tuesday, 22 January 2013

Controlling the RaspberryPi from a Web Application

The AdaFruit website has an excellent tutorial on connecting a 16x2 LCD display to a Raspberry Pi. That's great, but what if you want to be able to send messages to the display from a web application? In the previous tutorial, we saw how to create a basic Python-based web application using the Flask framework. Let's create a new web application that will interact with the Raspberry Pi.


The Goal

Using Flask, we will create a simple web application with with a form that allow a user to send a message to the Raspberry Pi using a web browser. This will allow us to control the Raspberry Pi from a PC, tablet or smart phone. When the form is submitted, it will send the message to the LCD via the device's GPIO ports. All the code, including the web application, is in Python and HTML... with some HTML and JQuery Mobile thrown in (just because we can).

To the Code

We'll be using the same circuit and the AdaFruit_CharLCD.py library, so make sure you have everything up-and-running as per the AdaFruit tutorial. So let's set up the folder structure that we'll need:
 /lcd  
    lcd.py  
    /adafruit  
        __init__.py
        Adafruit_CharLCD.py  
    /templates  
        index.html  
    

The source for application is available at https://github.com/slimjim777/web-lcd. The application uses the Adafruit class to communicate with the LCD from the Raspberry Pi. The only changes to the code were to convert tabs to spaces in the class (Python is generally very fussy over combining tabs and spaces for indentation).

Main LCD Application

The main LCD application is lcd.py, which is the app controller for the Flask framework.

 from flask import Flask  
 from flask import render_template, request  
 from adafruit.Adafruit_CharLCD import Adafruit_CharLCD  
   
 app = Flask(__name__)  
   
 # Initialise the LCD class  
 lcd = Adafruit_CharLCD()  
 lcd.begin(16,2)  
   
   
 @app.route("/")  
 def index():  
   return render_template('index.html', value=value)  
 
 ...

The script initializes the Adafruit LCD class and sets the size of the display (16x2 characters). After that the Flask index method is defined that renders the Jinja2 template. The template contains the web form to allow users to submit messages to the LCD:
 {% extends "base.html" %}  
 {% block body %}  
 <div data-role="header">  
  <h1>Raspberry Pi Controller</h1>  
 </div>  
   
 <div data-role="content">  
   
 <form method="post" action="change">  
  <label for="slider-1">Message to Send:</label>  
  <input type="text" name="lcd" id="lcd" />   
  <br />  
    
  <input type="submit" value="Submit" />  
 </form>  
   
 {% if value %}  
 <p>Message sent: {{ value }}</p>  
 {% endif %}  
   
 </div>  
 {% endblock %}  
   

The Jinja2 template extends from the base.html template, which contains the main details of the HTML page, including importing the JQuery Mobile libraries and CSS (to style the web page for mobile devices).

Starting the Web App

To start the web application, run:
 sudo python lcd.py  
   
This needs to be run with elevated permissions (using sudo) as it is communicating to the GPIO ports. Now, browsing to port 5000 on the Raspberry Pi will bring up the web form.


When the form is submitted, it send an HTTP POST request to the change method, including the message text that has been submitted.

 @app.route("/change", methods=['POST'])  
 def change():  
   if request.method == 'POST':  
     # Get the value from the submitted form  
     lcdText = request.form['lcd']  
     print "---Message is", lcdText  
       
     # Send the message to the LCD  
     lcd.clear()  
     lcd.message(lcdText)  
   else:  
     lcdText = None  
   return render_template('index.html', value=lcdText)  
   

The change method retrieves the message text from the HTTP POST request and stores it in the lcdText variable. Now, and this is the really clear bit, because all this code is running on the Raspberry Pi, that text can be sent through the device's GPIO port to the LCD using the Adafruit_CharLCD class. That's the beauty and simplicity of using a Python-based web-framework - the same code that someone else has developed to drive the LCD can be used directly in the web application.

This is a fairly simple example without much of a real-world use. But a similar approach could be taken to drive any component or device that is connected to the Raspberry Pi. That could be to switch a relay to turn on the central heating in your home automation system, or to send an message to an IR LED that will change the channel on the TV.

2 comments: