Thursday, 31 January 2013

Web-based IR Remote on the Raspberry Pi

There are many devices that use infrared remote controls - TV's, DVD players, cameras, power sockets. So getting a Raspberry Pi to be able to send remote control signals opens up many possibilities for projects. Combining the GPIO pins with a web server on the Raspberry Pi means that we can create a web UI to control these devices.

Installing LIRC on the Raspberry Pi

One of the great things about running a Linux operating system on the Raspberry Pi is that it provides access to a wealth of software projects that can run on the device. One of these is the Linux Infrared Remote Control (LIRC) project that provides a way of receiving and transmitting IR signals from many remote controls. LIRC provides a method of recording signals from a remote control and storing them in a configuration file, so that they can be sent directly from the Raspberry Pi.

Installing LIRC on the Raspberry Pi needs the latest firmware to be on the Raspberry Pi. One of the clearest guides I've found on the process of updating your firmware and installing LIRC is on Alex Bain's site. That walks you through the process of installing LIRC and getting the initial configuration done.

IR Receiver and Transceiver Circuits

Once LIRC is set up, we need to set up an infrared receiver and transmitter circuit.

IR Receiver

The receiver circuit is the simplest to set up. I've used a TSOP382, but check the data sheet for your IR receiver as the pins for ground and Vcc are sometimes the other way round. If you connect those pins incorrectly you could fry the IR receiver. Also, note that I'm connecting the Vcc pin to 3.3V as the TSOP382 works fine on that voltage.

The Adafruit site has a great walkthrough of testing and using an IR receiver.

IR Transmitter

The IR transmitter circuit is a bit more complex as the current output from the Raspberry Pi GPIO pins will only give you a very weak signal from the IR transmitter LED. If you search on the Internet you'll find a number of different circuits that you can use to amplify the signal so that you can get a few meters distance of signal from your IR LED.

I'm sure sure what the IR LED I've used as I rescued it from a Sony DVD remote control. In terms of the components to use for the circuit, you'll find a number of options. I used the components that I had available (Q1=BC547 transistor, R1=220ohm, R2=omitted as I didn't have a low enough resistor). Though I haven't measured the range of the signal, it works fine from 4m away from the devices.


Web-Controlled Remote

Once LIRC is setup and you can configured at least one remote, sending commands to through the IR LED is as simple as:
 #                device command  
 irsend SEND_ONCE Humax  KEY_POWER  

Of course, we don't want limit people to controlling the TV by ssh-ing into the Raspberry Pi to change the channel. So we need a web-based UI that people can access through a computer, tablet or smart phone. I got my 11-year old son to work on a design using Inkscape so that I'd have an SVG image that I could use as the web interface on an HTML5 web page. After a few iterations on the design, we came up with this:

The advantage of using an SVG file is that it will scale naturally with the device that it is viewed one, so should work well on a smartphone's 4-inch screen as well as on a 20-inch monitor.

Flask Web Application

The web application has been written using the Flask micro-framework, similar to my previous post. This time, the application reads the LIRC config file (/etc/lirc/lircd.conf) and gets the names of the devices that have been configured, and presents them to the user.
The web page uses JQuery Mobile to make it look good on smaller devices. Once the user selects the relevant device, the remote control is shown and the user can press a button on the touchscreen to operate the remote. Each button is configured to send a different operation e.g. pressing V+ will send KEY_VOLUMEUP. As we've seen previously, LIRC's irsend command only needs the device name and the operation command code to send the signal to the LED. With Flask, this can be done in less than 50 lines of code:
 #!/usr/bin/env python  
   
 from lirc.lirc import Lirc  
 from flask import Flask  
 from flask import render_template  
 from flask import request, redirect, url_for  
   
 BASE_URL = ''  
   
 app = Flask(__name__)  
   
 # Initialise the Lirc config parser  
 lircParse = Lirc('/etc/lirc/lircd.conf')  
   
   
 @app.route("/")  
 @app.route("/<device>")  
 def index(device=None):  
   # Get the devices from the config file  
   devices = []  
   for dev in lircParse.devices():  
     d = {  
       'id': dev,  
       'name': dev,  
     }  
     devices.append(d)  
     
   return render_template('remote.html', devices=devices)  
   
 @app.route("/device/<device_id>")  
 def device(device_id=None):  
   d = {'id':device_id}      
   return render_template('control.html', d=d)  
   
   
 @app.route("/device/<device_id>/clicked/<op>")  
 def clicked(device_id=None, op=None):  
   # Send message to Lirc to control the IR  
   lircParse.send_once(device_id, op)  
     
   return ""  
   
   
 if __name__ == "__main__":  
   app.debug = True  
   app.run('0.0.0.0')  
   

The only complexity that we come across of parsing the LIRC config file to get the names of the devices. Unfortunately, they have not used a standard format like YAML for their config file, so the parser may run into problems if you add comments on the same line as your commands. However, sending the command to LIRC is straightforward using a shell command to irsend:
 from subprocess import call  
   
 ...  
   
 def send_once(self, device_id, message):  
      """  
      Send single call to IR LED.  
      """  
      call(['irsend', 'SEND_ONCE', device_id, message])  
   

The full code is available on GitHub: https://github.com/slimjim777/web-irsend.


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.

Monday, 21 January 2013

Python Web Application Server on the RaspberryPi


One of the great features of the Rev. B RaspberryPi is the built-in Ethernet connection, which opens up many possibilities for web-connected projects. This enables this small device to be able to operate as a web server, ideal for running custom web applications. Since the RaspberryPi can also be connected to a host of other sensors and devices through the GPIO ports, this opens up the possibility of creating web-controlled devices.

Choosing a Web Framework

Since Python is the main programming language for controlling the RaspberryPi, I thought that the ideal web server for the device is a Python-based web framework. This means that the code for controlling the RaspberryPi's GPIO could be integrated right into the code for the web server.

There are a number of Python web frameworks available - so that run some heavy-weight Internet websites. However, the ideal solution is a web framework that is:
  • Easy to install
  • Quick to learn
  • Simple to write
  • Fast and lightweight
Even when considering this criteria, there are multiple options. I settled on one that I really like: Flask. The Flask project describes the framework as a microframework that is fun to work with. That sounds like the perfect accompaniment to a RaspberryPi!

Installing Flask on the RaspberryPi

Installing Flask on the RaspberryPi is really straightforward:

 sudo apt-get install python-pip  
 sudo pip install Flask  
 That's it! What we get is a built-in web server, a Python web framework which is WSGI-compliant, and a built-in templating engine (Jinja2 templates).

Hello World Web App

Once you have Flask installed, then you'll be itching to write your first "Hello World!" web app. Just find a suitable location on your RaspberryPi to store your code (I like to use a 'Sites' directory in the home folder and create a sub-directory for each project e.g. ~/Sites/hello), and a hello.py file as follows:

 from flask import Flask  
 app = Flask(__name__)  
 @app.route("/")  
 def hello():  
   return "Hello World!"  
 if __name__ == "__main__":  
   app.run('0.0.0.0')  

If you've checked out the Flask website, you'll recognise this code as their starting example, with one difference: the addition of '0.0.0.0'. This makes sure that the web server is going to listen on all network devices, so you can browse to the web site from anywhere on your local network.

To start the web server just run:
 $ python hello.py   
  * Running on http://0.0.0.0:5000/  

This will start the built-in web server and it will be listening for web requests on port 5000. You can browse to your web site from any computer, tablet or smart phone that is on your local network by navigating to http://the-ip-address-of-your-pi:5000/ e.g. http://192.168.1.105:5000/. There you will be greeted by your glorious, welcoming message.

Adding a Templated Web Page

Generating HTML from Python code quickly becomes unmanageable, so the recommended approach is to use a templating engine. The Flask install includes the Jinja2 templating engine which makes it quick and easy to develop web applications. Flask is configured to look for templates in a directory called templates. So create a folder structure like this:

 /hello  
   hello.py  
   /templates  
     hello.html  


So, let's create the hello.html template:
 <!DOCTYPE HTML>  
 <html>  
 <header>  
   <title>Welcome!</title>  
 </header>  
 <body>  
   <h1>Hello from the RaspberryPi</h1>  
 </body>  
 </html>  

And now change hello.py to use the template. This is done using render_template:
 from flask import Flask  
 from flask import render_template  
   
 app = Flask(__name__)  
   
 @app.route('/')  
 def hello(name=None):  
   return render_template('hello.html')  
     
 if __name__ == "__main__":  
   app.run('0.0.0.0')  

Restart the web server by running python hello.py and visit the RaspberryPi web page to see your new templated, web application.

That's it! You now have the basis for developing web applications that run on the RaspberryPi, written in Python. For more information on Flask, I recommend working through the tutorials on the Flask website. Once you have a better grasp of working with Flask, you'll be ready to add Python code that controls your RaspberryPi directly from your web application. Stay tuned for the next lesson.