Controlling lights connected to a Raspberry Pi from a Windows Phone app

Last year I spoke at Pune User Group’s DevCon 2014, an annual event for Developers in Pune that focuses on Microsoft technologies. This year we tried to have some tracks on devices and Internet of Things, and this blog covers a DIY for one of the demos I presented.

You get a glimpse of the demo here – Cortana Turn on the lights

To cut this DIY short I will be assuming you have a fair idea of

  • Some ultra basic linux stuff (because, Raspberry Pi)
  • Basic Windows Phone development
  • Running a Node.js “hello world”
  • Heard of Microsoft’s Azure platform
  • Some experience with REST API calls and OAuth

Even if you had none of these, you could still follow this DIY and use the links above to peek into the details of each pre-requisite as they show up.

Tools that you’ll need

  • A Raspberry Pi board running Raspbian (Wheezy) setup to connect to the internet – I’ll be using RPi Model B, but the older or newer versions should work just as fine. We are not doing anything fancy with the hardware.
  • An LED.
  • Pair of wires with header connectors
  • A 470 Ohm resistor
  • A Windows Phone – the SDK emulator will do, but not as much fun
  • A Microsoft Azure account. If you don’t have one, you can signup for a free trial here with $200 monthly credit. For this DIY you wont need more than a few cents.

Let’s get started…

Step I – Setting up Raspberry Pi

Raspberry Pi running Raspbian is capable of running Node.js. If you haven’t setup your Pi for Node.js yet or running a Node.js version older than 0.10.2, here’s a guide to install Node.js v0.10.2 on your Raspberry Pi in 5 minutes.

Once you have Node.js up and running, verify if you have the right version entering the following on your terminal.

node -v

OR

nodejs -v

If your version is 0.10.2 or later, you are good to go.

Now we need to figure out a way to interface the LED with your Pi. The Raspberry Pi has 8 safe to use GPIO (General Purpose Input Output) pins. There are more pins that could be used as GPIO, but they do a lot more than that and I prefer to keep them out of my designs. You can find their layout below.

Also, here is an interactive GPIO layout of the Raspberry Pi. Remember the Pi models until Model B had only 26 pins, the other pins are part of the extended GPIO of Model B+.

To check if your LED is working right, first start your Pi and connect the cathode of the LED to the GND pin i.e Pin 6 and the anode to Pin 1 (3.3v supply). Your LED should glow. Remove the anode and now connect to one of the GPIO pins. I’ll be using Pin 11 in my code, so you might as well tag along.

One last mile before we get started with Pi. The pi-gpio module for Node.js needs to be installed, so that we can control the GPIO from Node.js. Do install the module, use the following command in the directory you wish to use for your project.

npm install pi-gpio<code></code>

Once this goes successful, your Pi is ready for action.

Step II – Controlling LED via Node.js on Raspberry Pi

By now you should have the directory you’ll be working in, as you have already installed the pi-gpio module. Create a new JS file with a name of your choice. I’ll name mine “led.js”.

This file will host our Node.js process that talks to the internet and accepts commands to control the LED.

Let us begin by controlling the LED state via Node.js. If you have already been through the pi-gpio documentation on npm or github, you already have a hang of it. But to keep things documented here I’ll cover it.

var gpio = require("pi-gpio");
var pin = 11; // use your pin number here

gpio.open(pin, "output", function(err) {  // configure pin as output
   gpio.write(pin, 1, function() {  // set pin to HIGH state
      gpio.close(pin);  // close pin access
   });
});

Run this code

node led.js

The LED should turn on if your code runs successfully. With this in place, we are done with the hardware part of this DIY. All we need to do next is, create a channel of communication between this Node.js script and a Windows Phone.

Step III – Setting up Microsoft Azure Service Bus

The easiest way to send a signal from a Windows Phone to the Node.js script running on your Pi is by creating a Node.js web server and accepting HTTP requests from the Windows Phone. But, this would need the Raspberry Pi to have a static IP. Even then, we wont be able to support use cases where the Pi is behind a router without doing some port forwarding. Our motive is to create a channel that can be easily accessible irrespective of the network hops between the Windows Phone and the Pi. Enter, Azure’s Service Bus. The Service Bus will act as a mediator for messages being sent between the Windows Phone and the Pi. The Service Bus offers a variety of messaging topologies, we’ll be using Topics for this particular use case.

Each device will be continuously listening to a channel subscription (Service Bus Topic Subscription) assigned to it. Any message transmitted to its topic on the Service Bus will then be available for the device subscription to read and then mark as read when the appropriate action has been taken on the message. Multiple devices can listen to a topic, but a message once read on a topic subscription by a device will not be available for other devices on the same subscription. You can picture a single topic subscription as a single queue. This is particularly useful when you are planning to have multiple devices who perform the same actions using a single topic subscription, and each checks for new messages based on its availability. Example: Consider a fleet of Roombas assigned to mop the floor of a large shopping mall, while some Roombas might be already mopping a particular section, the idle ones can keep polling for new messages. The one that gets the next message is dispatched for cleaning, while others keep polling for new messages.

You can use the Service Bus Topic Subscription documentation to understand it better.

Another benefit of Service Bus is that it is a polyglot web service. You can communicate with Service Bus using SBMP (Service Bus Messaging Protocol), REST API or even AMQP, a lightweight Machine-to-Machine protocol that allows devices to use a single communication link to the web service to send and receive multiple messages.

Before we move to the Pi, create a service namespace on your azure account, and obtain the connection string for the namespace. Follow the documentation link above to create one.

Step IV – Connecting Raspberry Pi to Service Bus

The Node.js Azure SDK has a Service Bus library which can be consumed from our Node.js on Pi. We will create a Topic named ‘lights’ and create a subscription for the Pi to listen to. Before we start with that, lets download the azure npm package with the usual ritual in your project directory.

npm install azure

 Let us start by creating a new JS file. I’ll name this ‘control.js’. This is where our final code will be. The following lines will check if there is a topic named ‘lights’ on the service bus, if not it will create one. Don’t forget to place your namespace connection strings in the code below.

var azure = require('azure');
var gpio = require("pi-gpio");

var AZURE_SERVICEBUS_NAMESPACE = "name-space";
var AZURE_SERVICEBUS_ACCESS_KEY = "access-key";

var DEVICE_NAME = "rpi";
var topic = "lights";
var serviceBusService = azure.createServiceBusService(AZURE_SERVICEBUS_NAMESPACE,AZURE_SERVICEBUS_ACCESS_KEY);
var topicOptions = {
    MaxSizeInMegabytes: '5120',
    DefaultMessageTimeToLive: 'PT1M'
};

serviceBusService.createTopicIfNotExists(topic, topicOptions, function(error){
    if(!error){
        console.log("Topic created/exists.");
        
        serviceBusService.createSubscription(topic,DEVICE_NAME,function(error){
            if(!error){
                console.log("Subscription created...");
            }
            else {
                console.log(error);
            }
        }); 
    }
});

The code above, also creates a subscription named ‘rpi’. Now this might work the first time, second run onwards the subscription name might throw an error on the console while we can safely ignore. The topic options are used to set maximum message size and TTL.

Step V – Connect a Windows Phone app to Service Bus

We will be using the Service Bus REST API for Windows Phone to send messages to the Service Bus. So you can easily map the same APIs onto any other mobile device of your choice. Start by creating a Windows Phone ‘Blank App’ project in Visual Studio. On the MainPage.xaml paste the following XAML inside your parent grid.

<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBlock Name="Status" Foreground="#333" FontSize="24" Margin="20">Fetching LED Status...</TextBlock>
            <Button Height="120" Width="120" Name="LightON" Content="ON" HorizontalAlignment="Center" Foreground="#333" BorderBrush="#333" Click="LightON_Click"></Button>
            <Button Height="120" Width="120" Name="LightOFF" Content="OFF" HorizontalAlignment="Center" Foreground="#333" BorderBrush="#333" Click="LightOFF_Click"></Button>
            <Button Height="120" Width="120" Visibility="Collapsed" Name="LightParty" Content="Party" HorizontalAlignment="Center" Foreground="#333" BorderBrush="#333" Click="LightParty_Click"></Button>
        </StackPanel>
        
        

This will create two buttons on your UI. ON and OFF. Now your MainPage.xaml.cs should look something like this.

 

public MainPage()
{
    this.InitializeComponent();

    this.NavigationCacheMode = NavigationCacheMode.Required;
    Loaded += MainPage_Loaded;
}

private void LightON_Click(object sender, RoutedEventArgs e)
{
     sb.SendMessage("lights","{\"status\": true}");
}

private void LightOFF_Click(object sender, RoutedEventArgs e)
{
     sb.SendMessage("lights", "{\"status\": false}");
}

You will need to define the ServiceBus class and consume the REST API in there. Create a new class file, ServiceBus.cs. Now let us implement two methods in there. GetToken and SendMessage. GetToken will retreive an authentication token from Service Bus using the management credentials. This token will be used by the SendMessage method for every message being sent. Note, we will not be receiving any messages from Service Bus in Windows Phone. We will only send messages from the Phone and receive it on the Raspberry Pi.

 

GetToken is called in the constructor itself, so that it need not be explicitly called unless the token has expired which usually expires after 30 minutes. With this in place, the Windows Phone app is ready!