Raspberry Pi, Sense Hat, Azure IoT Hub, oh my!

In this blog post, we’ll post a very simple tutorial about gathering some simple data from a Sense Hat on a Raspberry Pi, post this data to Azure IoT Hub, parse them though Azure Stream Analytics and insert them into a simple Azure SQL Database table. This blog post helps as a tutorial for Azure IoT Hackathon we organized in Athens, on 18/3/2016.

  • On the hardware side, we’ll use a Raspberry Pi 2 and a Sense Hat
  • Creating a new Universal Windows Platform application
  • Write some code to get the temperature reading from the Sense Hat
  • Post the temperature/pressure/humidity reading from Sense Hat to Azure IoT Hub
  • A Stream Analytics job will store the temperatures on an Azure SQL Database

We’ll start by creating a new Azure IoT Hub, so we can connect our Raspberry to it.

Create a new Azure IoT Hub

  • Connect to the new Azure portal: http://portal.azure.com
  • Click on New -> Internet Of Things -> Azure IoT Hub
  • Name your IoT Hub, select a pricing tier, a Resource Group and a Azure datacenter location
  • Finally, click “Create”

1

Your Azure IoT Hub is ready!

2

Create the Visual Studio solution for the Universal WIndows Platform app

  • Before we start writing code, we’ll need a handy extension called Connected Service for Azure IoT Hub which you’ll need to install. This will make it easier for our small device to connect to Azure IoT Hub.
  • Create a new Universal Windows Platform project, I call mine “SenseHatIoTHub”.
  • We need some additional libraries to communicate with the Sense Hat. There’s a nice and open source library here which we’ll use. Luckily, the author has supplied a Nuget package for us to use. So, right click on the project, select “Manage Nuget packages” and search for “sensehat”. You’ll find the package called “Emmellsoft.IoT.RPi.SenseHat”.
    Capture
  • Click “Install” and this will be installed in your project
  • We’ll proceed by adding a reference to the Azure IoT Hub. This will generate some code for our device to connect.
  • Right click on the project, select “Add” -> “Connected Service”
  • Select “Azure IoT Hub” and press “Configure”
  • Enter your Azure account credentials
  • Select the account that contains the Azure IoT Hub that you previously created and press “Add”
  • It will prompt you to select a device or create a new one. Let’s create a new one, I’ll call mine “myraspberry”. Enter the name and press “Add”.
  • You’ll see a new file added to the project, called “AzureIoTHub.cs”. This file contains some useful code to send and receive messages from Azure IoT Hub.
  • We’ll need a class to store the messages we’ll send to Azure IoT Hub. Create a new class, call it “SenseHatData” and paste the following code
    namespace SenseHatIoTHub
    {
        public class SenseHatData
        {
            public double? Humidity { get; set; }
            public double? Pressure { get; set; }
            public double? Temperature { get; set; }
            public string Location { get; set; }
        }
    }
    
  • Go to the AzureIoTHub.cs file and add the following method
     public static async Task SendSenseHatDataToCloudAsync(SenseHatData data)
        {
            var deviceClient = DeviceClient.CreateFromConnectionString(deviceConnectionString, TransportType.Http1);
            var messageInJson = JsonConvert.SerializeObject(data);
            var message = new Message(Encoding.UTF8.GetBytes(messageInJson));
    
            await deviceClient.SendEventAsync(message);
        }
    
  • Let’s add the code to see the SenseHat sensor readings on the screen. Remember to connect the Raspberry Pi to an HDMI capable device. Go to MainPage.xaml and add two textblocks, to display the current temperature. Modify the parent Grid to a StackPanel, for an easy layout. Your code should be like this
    Capture
  • Now, go to MainPage.xaml.cs and write the following code
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
                this.Loaded += MainPage_Loaded;
            }
    
            private async void MainPage_Loaded(object sender, RoutedEventArgs e)
            {
                //get a reference to SenseHat
                senseHat = await SenseHatFactory.GetSenseHat();
                //initialize the timer
                DispatcherTimer timer = new DispatcherTimer();
                timer.Tick += Timer_Tick;
                timer.Interval = TimeSpan.FromSeconds(1);
                timer.Start();
            }
    
            private async void Timer_Tick(object sender, object e)
            {
                senseHat.Sensors.HumiditySensor.Update();
                senseHat.Sensors.PressureSensor.Update();
    
                //gather data
                SenseHatData data = new SenseHatData();
                data.Temperature = senseHat.Sensors.Temperature;
                data.Humidity = senseHat.Sensors.Humidity;
                data.Pressure = senseHat.Sensors.Pressure;
    
                //send them to the cloud
                await AzureIoTHub.SendSenseHatDataToCloudAsync(data);
    
                //notify UI
                TempText.Text = data.Temperature.ToString();
                TempHumidity.Text = data.Humidity.ToString();
                TempPressure.Text = data.Pressure.ToString();
            }
    
            ISenseHat senseHat;
    
        }
    

Create a new Azure SQL Database

  • Select “New” and search for “SQL Database”
  • Write the name of the database, select the pricing tier. You may need to configure a new SQL Server instance to host the database, if you haven’t already created one.
    Capture
  • After you create the database, you need to select it, press “Tools” and then “Open in Visual Studio”. You will see a small text on the right blade in the portal that prompts you to allow access in the Azure firewall for your DB. Do it!
  • Create a new table in the database. Here is the SQL script I used to create mine
    CREATE TABLE [dbo].StatusPerLocation
    (
        [Temperature] FLOAT NOT NULL,
        [Humidity] FLOAT NOT NULL,
        [Pressure] FLOAT NOT NULL,
        [Location] NVARCHAR(50) NOT NULL
    )
    
  • When you finish, click update. The script will run on SQL Azure and your table will be created.

Create a new Stream Analytics job

  • On the Azure portal, select to create a new “Stream Analytics job”
  • Enter a name, select a Resource group (preferably the same as the Azure IoT Hub) and click “Create”
    Capture
  • Before setting the input, we need to get some data from the Azure IoT Hub. Go to the IoT Hub blade, select “Shared Access Policies” and copy the Primary Key for the iothubowner role. We’ll need it to configure the input for the Stream Analytics job.
    Capture
  • Let’s return to the Stream Analytics job. Once there, click on the “Inputs”, this will allow us to set the input of the Stream Analytics job. Click to add a new input and fill in the requested fields.
    Capture
  • Click “Create”, your input is ready!
  • Now, let’s create a new output. We’ll configure it to use the SQL Server table we previously created
    Capture
  • Finally, we’ll create the query. We’ll use a simple query pass all data to SQL Server
    SELECT
        Temperature, Humidity, Pressure, Location
    INTO
        output
    FROM
        input
    
  • Click on “Save” to save your changes. Your Stream Analytics service is ready, you can click “Start” to initiate it.
  • By the way, there are lots of interesting things to do with Stream Analytics query language, check the documentation here

Monitoring events

Wee need something to monitor events that our sensor is sending to Azure IoT Hub. Visit the website https://github.com/Azure/azure-iot-sdks/blob/master/tools/DeviceExplorer/doc/how_to_use_device_explorer.md#download and download the Device Explorer application. You need an Azure IoT Hub connection string for it to work. To get this

  • Open the Azure IoT Hub in the Azure portal
  • Open the Shared Access Policies settings blade
  • Select the iothubowner
  • Copy the primary connection string

After you get that, paste it in the Device Explorer app and click Update.

Capture

Then, select the data tab. Select your device (“myraspberry”, in our case) and click “Monitor”. The application starts to monitor events coming from the “myraspberry” device.

Return to Visual Studio and debug the UWP Sense Hat app. You’ll see that the Device Explorer app captures the events coming from “myraspberry”.

Capture

If you connect to SQL Server from within Visual Studio (using Cloud Explorer and SQL Server Explorer), you’ll see that the table contains the data output of the Azure Stream Analytics job.

Capture

That’s all! If you’ve made it so far, congratulations :) As always, you can check the source code here on GitHub, on the SenseHatIoTHub folder.

25 thoughts on “Raspberry Pi, Sense Hat, Azure IoT Hub, oh my!

  1. I get an error on the line. senseHat = await SenseHatFactory.Singleton.GetSenseHat();
    Error:
    ‘SenseHatFactory’ does not contain a definition for ‘Singleton’ SenseHatIoTHub

    Any help would be approciated.

    Like

  2. I was able to install the NuGet package. If I leave off the Singleton portion the program compiles, but will not run. I was looking at the SenseHatFactory class on GitHub and did not find a singleton reference there. Am I missing a using? These are the what is currently in my MainPagexaml.cs

    using Emmellsoft.IoT.Rpi.SenseHat;
    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;

    Like

    • You’re right, package author probably changed the class. Nevertheless, it seems weird that when you downloaded the project, it didn’t restore the 1.0.08 version. Anyway, happy it’s working for you, let me know if you need anything else.

      Like

  3. I used your complete solution. Everything is setup on Azure. There is an error message “AzureIoTHub does not contain a definition for ‘SendSenseHatDataToCloudAsync’. I have the reference to Emmellsoft.IoT.RPi.SenseHat.

    Unlike the previous commenter the nuget package version I have is 0.1.0.8

    Any pointers you can give me to get past this challenge?

    I am a noob (beginner).

    Like

  4. Got your new project.json and did an update on the SenseHatFactory:
    SenseHatFactory does not contain a definition for singleton
    AzureIoTHub does not contain a definition for SendSenseHatDataToCloudAsync

    Like

    • Remove the Singleton property, it is not used on new SenseHat library. For your other error, you probably did something wrong with the code. Can you download again from GutHub and try?

      Like

      • As per the developer SenseHatFactory:
        Yes, I did change the creation of the SenseHat class in version 0.1.0.9.

        In version 0.1.0.8 you had to call:
        ISenseHat senseHat = await SenseHatFactory.Singleton.GetSenseHat();

        In version 0.1.0.9 (and up) you have to call:
        ISenseHat senseHat = await SenseHatFactory.GetSenseHat();

        So the only change you need to do is remove the part “Singleton” from the call chain.
        (The old code had some potential problems with race conditions which could occur if you called the GetSenseHat-method simultaneously from two threads at the same time. That was fixed in version 0.1.0.9.)

        Like

  5. Made it all the way to the congratulations with the data coming through in the device explorer (and blowing through my monthly allotment of messages in minutes. No data yet in the the table. Not sure how to diagnose that further.
    Thanks.

    Like

  6. Apparently a streaming job gets dirty. No matter what I tried I could not get it to work. After deleting it and making a new one (with the same settings), it started working.
    Thanks for your help!

    Like

  7. i want to do this project and show temperature value in the led matrix can u tell me what i am doing wrong with this code
    public void Timer_Tick(object sender, object e)
    {
    var tinyFont = new TinyFont();
    senseHat.Sensors.HumiditySensor.Update();
    senseHat.Sensors.PressureSensor.Update();

    ISenseHatDisplay display = senseHat.Display;
    //gather data

    SenseHatData data = new SenseHatData();
    data.Temperature = senseHat.Sensors.Temperature;
    data.Humidity = senseHat.Sensors.Humidity;
    data.Pressure = senseHat.Sensors.Pressure;
    data.Location = “Athens”;
    double tempvalue = data.temperature;
    int temperature = (int)Math.Round(tempvalue);
    var s = Convert.ToString(temperature);
    //notify UI
    TempText.Text = data.Temperature.ToString();
    TempHumidity.Text = data.Humidity.ToString();
    TempPressure.Text = data.Pressure.ToString();
    LightProgress.Value = (int)data.Humidity;

    display.Clear();
    tinyFont.Write(display,s , Colors.Yellow);
    display.Update();

    }

    Like

  8. Made it to the congratulations :-) I noticed the Location value was returning null, which was blocking the output to the SQL table, which was quickly fixed by changing the table to allow nulls.

    However, where exactly should the Location value come from? I notice in your screenshot you have Athens, but I couldn’t see any setting in the Pi itself. Does the Pi know its location from its network?

    Like

    • Congratulations for reaching congratulations!
      No, Location is something set on the code, just for demo purposes. You could get a Location value either by a reverse IP geocoding or (even better) with a GPS module on the Raspberry.

      Liked by 1 person

  9. Nice example. However, is creating a stream analytics job, the most cost effective way of transferring iot data to sql? How about using a hub trigger? Any other options? Thanks.

    Like

Leave a comment