Azure IoT Hub End-to-End

I recently had the pleasure of talking again at the Perth MS Cloud Computing User Group about the Microsoft Azure IoT Hub.

For the presentation I wanted to make sure I spoke about the Internet of Things as a subject, as a technology and in particular I wanted to provide a simple end-to-end demonstration.

Having not had many opportunities to play with actual devices before, I’ve mostly demonstrated IoT Hub using console apps, I thought it would be a good opportunity to have a look at a device.

For this I got myself a Raspberry Pi 2, and the GrovePi+ Starter Kit from Dexter Industries.

I went this route for a couple of reasons. First, the Raspberry Pi 2 runs Windows 10 IoT Core, and second the GrovePi+ has a reasonably well supported C# managed library for IoT Core for the sensors available both on GitHub and Nuget.

I figured that whilst I wanted to play around I also wanted to be able to build out an end-to-end demonstration quickly.

So, armed with my device and an Azure subscription I came up with the following demonstration architecture.

Demonstration Architecture

The purpose behind the demonstration is to simulate a building management solution whereby devices send temperatures and alerts are sent to and managed by a device that is acting as a sprinkler management system.

iothub-arch

This is a pretty straightforward simulation using a console application to measure the temperature of rooms. The console application that simulates this temperature device can be triggered to simulate a fire, and then triggered again to then linearly reduce the temperature.

The telemetry is sent to IoT Hub where two Azure Stream Analytics jobs do the required work.

  1. One job is a pass through query that simply takes the input telemetry from IoT Hub using a specific consumer group and moves it in to an Azure Storage Table. The purpose of this job is to archive all the data and allow for easy visualisation, for instance using Power BI.
  2. The second job looks for the maximum temperature within a 10 second tumbling window and sends the result to an Azure Service Bus Queue.

Once on the queue an Azure WebJob does the backend work of reading the information, checking for conditions and acting if certain conditions are met. In this way it acts as the IoT Business Logic layer for my backend IoT application. This business logic looks for certain temperature events and sends a message to IoT Hub when they are reached.

I then have my Raspberry Pi 2 and GrovePi+ listening for messages and acting accordingly.

Device Setup

In order to use my Raspberry Pi 2 for my project I first needed to install Windows 10 IoT Core. You can use the Windows 10 IoT Core Dashboard for this, but I found the easiest way was to download the IoT Core release image for Rasberry Pi 2, install it and use the tools provided. Both these can be obtained from the Windows IoT Downloads and Tools page.

Once installed it is a simple task to flash your SD card for your Pi.

iothub-imagehelp

Once this is finished and the Pi booted and you’ve connected an Ethernet cable you can use the IoT Core Watcher application to get the IP address and then browse to the device using the browser of your choice.

iothub-corewatch

iothub-browser

From here if you have a hardware compatible WiFi dongle you can set up WiFi access, and change password and device name if you wish.

The IP address is important so make a note of that.

I installed my GrovePi+ and the sensors I wanted and was then ready to code.

My GrovePi+ was setup to use the RGB LCD screen, a buzzer and button that I use to reset the device.

iothub-pisetup

Visual Studio 2015 Setup

To make Visual Studio 2015 play well with your device, you need to  make sure you install the Windows IoT Core templates and the Universal Windows (UWP) templates.

When you create a Blank App (Universal Windows) you need to make sure you set it up to target the correct architecture and remote device. This is where you’ll need that IP address you made a note of earlier.

iothub-vs

IoT Hub Setup

Once you’ve visited the Azure Portal and created an IoT Hub, you can use the managed SDK to create and register devices. This is great if you’re bootstrapping device registration, but if you want to just create some basic devices and do some testing is overkill.

If you download the Device Explorer you can manage devices, manage SAS tokens, and receive and send data to registered devices all within the confines of a simple Windows application. This is the lowest level of entry for setup.

For my purposes, I wanted to create devices for 5 rooms plus one for my sprinkler management system that would be receiving alerts.

iothub-devexp

Room Temperature Device Setup

To simulate a temperature sensor I created a simple console application that listened for key inputs.

When started this room would simulate a specific room and send an event that represented a temperature of 23 degrees plus a random value between 0.0 and 1.0.

Pressing the Up key would increase the temperature until it was above 400.0 and then pressing the Down key would reduce the temperature until it was below 50.0.

deviceClient = DeviceClient.CreateFromConnectionString(room.connectionString);

var rnd = new Random();
var root = 23.0;

do
{
   while (!Console.KeyAvailable)
   {
      SendToIoTHub(new DeviceData { id = room.id, date = DateTime.UtcNow, temperature = root + rnd.NextDouble() });
      Thread.Sleep(1000);
   }
} while (Console.ReadKey(true).Key != ConsoleKey.UpArrow);

do
{
   var seed = 2.0;
   while (!Console.KeyAvailable)
   {
      temperature = root + seed + rnd.NextDouble();
      SendToIoTHub(new DeviceData { id = room.id, date = DateTime.UtcNow, temperature = temperature });
      Thread.Sleep(1000);
      if (seed < 400.0) seed *= 2.5; 
   } 
} while (Console.ReadKey(true).Key != ConsoleKey.DownArrow); 

do 
{ 
   var seed = 30.0; 
   while (!Console.KeyAvailable) 
   { 
      var rndVal = rnd.NextDouble(); 
      temperature = temperature - seed + (rndVal > 0.5 ? rndVal : -rndVal);
      SendToIoTHub(new DeviceData { id = room.id, date = DateTime.UtcNow, temperature = temperature });
      Thread.Sleep(1000);
      if (temperature < 50.0) seed = 0.0;
    }
} while (Console.ReadKey(true).Key != ConsoleKey.LeftArrow);

This allows the simulation of, for instance a fire, and then the action of the sprinkler system reducing the temperature by putting out the fire.

Whilst this is simple code, the code that does the actual interaction with IoT Hub is even simpler.

static async void SendToIoTHub(object data)
{
   var messageString = JsonConvert.SerializeObject(data);
   var message = new Message(Encoding.UTF8.GetBytes(messageString));

   await deviceClient.SendEventAsync(message);
   Console.WriteLine("Sending: {1}", DateTime.Now, messageString);
}

Since the console application is representing a device and not a backend application process, DeviceClient is used to send the data.

Azure Stream Analytics Setup

To represent the pass through and maximum temperature queries two Azure Stream Analytics jobs where created with very basic queries.

SELECT
    id, date, temperature
INTO
    allmessages
FROM
    iothub
SELECT
    id, max(temperature), System.TIMESTAMP as date
INTO
    servicebusqueue
FROM
    iothub
GROUP BY 
    id, TumblingWindow(Second, 10)

Clearly these queries could be more complex, and there could be more based on any number of IoT Hub consumer groups to provide input to a range of tooling such as HDInsight, or Machine Learning algorithms as required.

Azure WebJob Setup

Once the maximum temperature data has been pushed on to a Service Bus Queue a simple Azure WebJob is triggered and reacts to certain conditions.

public static void ProcessQueueMessage([ServiceBusTrigger("maxtemp")] string message, TextWriter log)
{
   if (zonetemps == null) zonetemps = new Dictionary<string, double>();
   if (zoneactive == null) zoneactive = new Dictionary<string, bool>();

   var command = JsonConvert.DeserializeObject(message);
   var zone = command.id;
   var temp = command.max;

   if (!zonetemps.ContainsKey(zone))
   {
       zonetemps.Add(zone, temp);
   }
   else
   {
       zonetemps[zone] = temp;
   }

   if (!zoneactive.ContainsKey(zone)) zoneactive.Add(zone, false);

   if (zonetemps[zone] > 400.0 && !zoneactive[zone])
   {
       zoneactive[zone] = true;
       var sprinkler = new SprinklerCommand { deviceName = command.id, temperature = command.max, activate = true };
       SendToIoTHub(sprinkler);
   }
   else if (zonetemps[zone] < 60.0 && zoneactive[zone])
   {
       zoneactive[zone] = false;
       var sprinkler = new SprinklerCommand { deviceName = command.id, temperature = command.max, activate = false };
       SendToIoTHub(sprinkler);
   }
}

First, some state is created so we don’t constantly send data back, and then the temperature of the maximum temperature event is read along with the room it has occurred in. If that has already triggered an event for that room is moves on otherwise it sends data back to IoT Hub.

Again the code that does the actual work of sending the data to IoT Hub is very simple.

static async void SendToIoTHub(object data)
{
   var messageString = JsonConvert.SerializeObject(data);
   var message = new Message(Encoding.UTF8.GetBytes(messageString));
   message.Ack = DeliveryAcknowledgement.Full;
   message.MessageId = Guid.NewGuid().ToString();

   var serviceClient = ServiceClient.CreateFromConnectionString("[IoT Hub Connection String]");
   await serviceClient.SendAsync("sprinkler", message);

   await serviceClient.CloseAsync();
}

Since the WebJob is representing a backend application process and not a device, ServiceClient is used to send the data.

Universal Windows App Setup

The application that is deployed to the Rasperry Pi needs to poll for data on the IoT Hub and respond to events received.

public MainPage()
{
   this.InitializeComponent();
   deviceClient = DeviceClient.CreateFromConnectionString("[IoT Hub Connection String]");

   ReceiveIoTHub();
}

private static async void ReceiveIoTHub()
{
   var buzzer = deviceFactory.Buzzer(Pin.DigitalPin2);
   var button = deviceFactory.ButtonSensor(Pin.DigitalPin4);
   var rgb = deviceFactory.RgbLcdDisplay();
   rgb.SetBacklightRgb(200, 125, 0);
   rgb.SetText("Sprinklers\nonline");

   while (true)
   {
      try
      {
         if (button.CurrentState == GrovePi.Sensors.SensorStatus.On)
         {
            rgb.SetBacklightRgb(200, 125, 0);
            rgb.SetText("Sprinklers\nonline");
            buzzer.ChangeState(GrovePi.Sensors.SensorStatus.Off);
         }

         Message receivedMessage = await deviceClient.ReceiveAsync();
         if (receivedMessage == null) continue;

         var message = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(receivedMessage.GetBytes()));

         if (message.activate)
         {
            rgb.SetBacklightRgb(250, 0, 0);
            rgb.SetText("Zone: " + message.deviceName + "\nTemp: " + message.temperature.ToString());
            buzzer.ChangeState(GrovePi.Sensors.SensorStatus.On);
         }
         else
         {
            rgb.SetBacklightRgb(0, 75, 200);
            rgb.SetText("Zone: " + message.deviceName + "\nFire: Out");
            buzzer.ChangeState(GrovePi.Sensors.SensorStatus.Off);
         }

         await deviceClient.CompleteAsync(receivedMessage);
      }
      catch (Exception e)
      {
         var msg = e.Message;
      }
   }
}

Again the code that does the actual polling is minimal and most of the code is actually acting on received data.

Pulling It Together

Starting the Stream Analytics jobs is simple and they can be started to start listening for events arriving in IoT Hub from Now to ensure only new data is processed.

iothub-asa

The Azure WebJob can be published to Azure or run locally in debug mode. Once started it listens to trigger events on the Service Bus Queue and reacts accordingly. If the event doesn’t require intervention it is essentially dropped.

iothub-webjob

Starting an instance of the Room temperature device application, a room can be chosen and events are then sent. Using the Up arrow the temperature can be increased and then using the Down arrow decreased to simulate a fire and fire intervention.

iothub-room

On the device when the application first starts, the screen lights up and indicates that the device is ready.

iothub-online

Results

Data is being constantly sent to IoT Hub by the console applications that represent the room temperature devices.

The WebJob picks up events and checks whether the maximum temperature provided is above the allowed threshold before the sprinkler device is activated and sends a command message to the device via IoT Hub.

If the maximum temperature provided is below the allowed threshold and a device has already been activated, it can be assumed the issue has passed and a the WebJob then sends a command message to the device via IoT Hub

If data is received by the device activates an alarm, the screen changes to red and information is displayed. Additionally the buzzer is activated to alert any operator of the issue.

iothub-fire

If data is received by the device clears an alarm, the screen changes to blue and information is displayed. Additionally the buzzer is deactivated.

iothub-clear

Obviously since the screen is only two lines, it is only capable of reacting to a single room event at a time, but this is just a demonstration.

Conclusion

Azure IoT Hub is part of the Azure Platform as a Service offering. By combining it with other platform services such as Stream Analytics, Service Bus Queues and WebJobs it is very quick and easy to create simple simulation scenarios for proving out ideas.

Other than simulation code, and excusing exception handling (!!), this can all be achieved in a very small number of lines of code because the connectivity and interactions between the platform services can be leveraged and a basic solution quickly designed, delivered and proved.

IoT Hub is a truly compelling service in Azure especially when taken in connection with other services. It would be a relatively simple task to flesh out the demonstration to include trend analysis, data aggregations, storage, searching and state management facilities all still within the platform. This could be achieved for instance using services such as HDInsight, Machine Learning, DocumentDB and Service Fabric.

What do you think would make a great solution using these bits of Azure and stitching them together?

 

Leave a Reply

Your email address will not be published. Required fields are marked *