Building an Azure IoT Demo Device with Raspberry Pi

Although I’ve talked a lot about Azure and Power BI over the last few months with customers, it’s principally been that – just talk, with a few whiteboarding sessions before actually jumping into deployments. Which is all well and good, but I felt I needed some flashy demos to spice things up.

So what better way to do this than to bring some IoT devices in and pull live data through the Azure IoT Hub, process it with the Cortana Intelligence Suite and visualise it with Power BI?

Raspberry Pi devices are incredibly cheap and flexible little boxes into which we can integrate all sorts of weird and wonderful sensors. So, I decided to show off just what Azure can do with relatively small outlay. Perfect for a weekend project! And with Amazon Prime same-day delivery, I had pretty much everything I needed within just a few hours.

So in this post, I’m going to cover off the initial set up of the Raspberry Pi device, the configuration of an Azure IoT Hub and actually getting data into the hub. I will write a follow-up post on what I actually do with the data once it’s in the Azure IoT Hub.

Parts List
Here’s what I started with:

  • A Raspberry Pi 3 Model B
  • A generic microSD card, running Raspbian Jessie Light
  • An AM2302 Temp/Humidity Sensor

Getting readings from the sensors
Pulling information from the temperature sensor was incredibly easy. Using the guide available here I very quickly got a Python script to print the temperature and humidity to the screen. The part that I envisaged to be the most difficult actually turned out to be by far the most simple, even though I know virtually nothing about Python.

Preparing Azure to receive data
So now we need somewhere to send our data. I could have chosen a traditional Event Hub but instead I’ve picked out the Azure IoT Hub. Aside from being able to do per-device authentication, I can later extend the project out to do bi-directional messaging – for example allowing the IoT Hub to send back acknowledgement messages, or to tell the device to perform some action in response to the data sent to Azure.

Creating a new Azure IoT Hub is really easy – and completely free for a dev/test hub. Just note that you can only have one Free Azure IoT Hub per subscription, which is limited to a single IoT Hub device and 8,000 messages a day. I initially wanted to send a message every twelve seconds which works out at about 7,200 messages a day, leaving me some room to play; however, due to limitations in cron (more later) I have to settle for one message a minute right now.

new-iot-hub-1

new-iot-hub-2

Creating the Azure IoT Device Object
With the Azure IoT Hub configured it’s necessary to then create a device object associated with the IoT Hub. Unlike Event Hubs which is a single bucket for all messages, the Azure IoT Hub splits message queueing out on a per-device basis enabling the per-device authentication and bi-directional messaging I mentioned above.

The Azure documentation provides a sample console application to create a device and outputs the device key (required for device authentication) upon successful creation. It’s pretty straightforward but bear in mind that most of the next steps require at least a working knowledge of Visual Studio and basic software development.

The key pieces of information you will need to continue are:

  • Your IoT Hub name – this is name you chose in the ‘Name your hub’ dialog in the Azure Portal
  • Your Device Name – you chose this when compiling and running the console app above
  • Your Device Key – this was returned by the console app when it successfully created the device

Pushing messages into the Azure IoT Hub with Python
Now, if we were using a Windows device that can use the .NET framework the next part would be really, really easy – there’s plenty of sample code available through the Azure SDK. However I’m using Python here – because that’s what my sensor’s library is provided as. This presents me with a problem. There is an SDK for Python, but it’s simply a wrapper for the C SDK and I’m not about to get into resolving dependencies all over the place. So I took the decision to use the REST API provided by the Azure service.

However I soon found the documentation here quite sparse; and by far the most difficult part of getting this to work is generating the Shared Access Token for authentication. So after spending a while building my own SAS token generator in Python – which so very nearly worked – I did a quick search on GitHub and came across Stepan Bechynsky’s work, implementing exactly what I needed. Between this and examining the Azure C# SDK I realised what I was doing wrong – you have to pass the IoT Hub name and URL in lower case to the SAS token generator. I tried a couple of variations before hitting on the right one – everything in the URL must be lower case, except for your Device Name – this has to match exactly. So if you called your IoT Hub “MyFirstHub” and your IoT Device “MyFirstDevice“, the URL you would pass to the SAS token generator would need to be https://myfirsthub.azure-devices.net/devices/MyFirstDevice.

Once this hurdle had been overcome – I could start to send messages to the Azure IoT hub!

Formatting and sending data
The Azure IoT Hub accepts messages in a standard JSON format. So I simply created a variable as follows:

Json_Message  = {'temperature' : temp, 'humidity' : humid }

In the above example I’m sending two fields – temperature and humidity – and some variables temp and humid I defined earlier in my code. You can send any number of comma-separated values in the above, up to the maximum message size of 256KB.

My code is below; it’s not particularly elegant but it works. I will be cleaning it up and posting to GitHub at some stage; I’ll update this post when I do.

#!/usr/bin/python
import sys
import Adafruit_DHT
import DeviceClient

# Set up the required variables for Azure IoT Hub
Azure_DeviceName = "your_device_name_here"
Azure_DeviceKey = "your_device_key_here"
Azure_IoTHubName = "your_Azure_IoT_Hub_name_here"

# Set up the required variables for the sensor
Dht_Type = Adafruit_DHT.AM2302
Dht_Pin  = 4

# Get reading from the sensor
temp, humid = Adafruit_DHT.read_retry(Dht_Type, Dht_Pin)

# Create the JSON message
Json_Message = {'temperature' : temp, 'humidity' : humid}

# Send the data to Azure
Device = DeviceClient.DeviceClient(Azure_IoTHubName.lower(), Azure_DeviceName, Azure_DeviceKey)
Device.create_sas(600)
Azure_Sender = Device.send(Json_Message)
if Azure_Sender == 204:
  print('Success')
else:
  print('Failure')

Finally – I configured a cron job to run this script every minute. Longer term I’ll look at alternatives – a service seems most sensible but I’ll need to investigate how this works on Linux with Python. Eventually I’d like to have two of these units – one running Linux and running Python and a second doing the equivalent on .NET and the Windows 10 IoT Core Edition. But that’s an experiment for another weekend.

Cheers,
Rob

Update:
One vital step missed above. I had originally just thought I could send a string and have the Azure IoT Hub interpret it as JSON. That didn’t work. So I had to update a couple of lines of code to sort this out. You can probably tell I’m new to Python!

At the top I needed to import the JSON library:

import json

Then, I had to fiddle with the message creation:

Str_Temp = str(temp)
Str_Humid = str(humid)
Json_Message = {"temperature" : Str_Temp, "humidity" : Str_Humid}
Encoded_Message = json.dumps(Json_Message).encode('utf8')

And finally update how to send the message:

Azure_Sender = Device.send(Encoded_Message)

Hopefully now I’ll get to take a look at the Azure side of this!

Leave a Reply