IoT Hub from the Command Line

If you’re like me, in other words old enough to have spent large periods of time working at a command prompt, then you’ll always be looking for command line tools to get things done.

If you’re like me and spending lots of time doing things with IoT Hub, then wouldn’t it be nice to have a command line tool for that.

I spend time in the Azure Portal and using tools like Device Explorer to manage devices and check connectivity but was looking for a CLI for these tasks when I came across iothub-explorer.

iothub-explorer is a Node.js application so before you can have a play you’ll need to head on over to Node.js website and download it if you don’t have it installed.

You use the node package manager (npm) to install the command line interface tool.

npm install -g iothub-explorer@latest

This will install it globally so you’ll be able to have a good play from your command prompt of choice, I like to use PowerShell.

If you want to examine the dependencies, just issue the following from a command prompt.

npm list -g --depth=1

This will list all the things that are also installed as part of iothub-explorer.

iothub-explorer@1.0.8
  ├── azure-event-hubs@0.0.2
  ├── azure-iot-common@1.0.8
  ├── azure-iot-device@1.0.8
  ├── azure-iothub@1.0.10
  ├── bluebird@3.4.1
  ├── colors-tmpl@1.0.0
  ├── nopt@3.0.6
  ├── prettyjson@1.1.3
  └── uuid@2.0.2

If you run iothub-explorer on its own or with the help command line argument you get a list of supported commands.

iothub-commandsSo as you can see you can do an awful lot with this tool.

The easiest way of having a play from a PowerShell command line is to store your connection string in a variable.

$conn = [YOUR CONNECTION STRING]

You can then start a new session with your IoT Hub by simply logging in to it.

iothub-explorer login $conn

By default this gives you a session lasting one hour. If you need a longer period the command has a –-duration argument that takes the number of seconds you need.

Once you’re logged in you’re live to interact with your IoT Hub in lots of the same ways you can from Device Explorer, except this time from the command line which is pretty cool, and of course scriptable!

If you want to take a look at the devices you currently have registered just get a list. Since you previously logged in you don’t need to provide the connection string, so think of all the key strokes you’ll have left.

iothub-explorer list

This returns all the information about each device, but again there is a handy command line argument to limit the level of information, just use -–display and comma separate the properties you want. The argument is used in a few places, so I’d suggest issuing without, taking a look at what there is and then just grabbing what you need in future.

iothub-explorer list --display="deviceId, connectionState"

If you just want a single device use “get” instead of “list” and use the deviceId.

You can also create devices (for instance by including some JSON that defines your device) and retrieve a SAS token for a device.

If you’re really interested in checking how IoT Hub works then the most interesting commands allow monitoring of events sent by a device, and also sending cloud-to-device messages directly. To top even that though, you can also monitor the feedback queue and check for acknowledgement messages from the device which is very cool.

So how do we do that?

First let’s take a look at monitoring events from devices. You’ll need a console application to send messages to your device, that’s just boilerplate code and I’ve covered that to a degree before so I’ll not repeat that here. Once you’ve hooked that up and are sending messages, monitoring from the command line is simple.

iothub-explorer $conn monitor-events [deviceId]

You’ll notice we need to pass the connection string this time, this is one command that still requires it, but I assume that will change in a later version.

Once issued, the command just waits until messages are received at the device endpoint.

iothub-monitor.png

For simulating messages send to a device from the cloud you’ll need another console application that is pretending to be a device in a receive loop. Again that’s boilerplate that I’ve covered before.

You’ll need the console application running because the whole point is to check that messages are received and an acknowledgement is sent. For this one you need 2 PowerShell command windows and don’t forget to set the connection string in the new window.

In one window issue the following and it’ll pause listening to the feedback queue on the IoT Hub.

iothub-explorer retrieve

You can add an argument, –messages=n where n is the number of messages it’ll wait to receive before stopping, otherwise it’ll just wait until you quit.

In the other window, you need to send a message to the cloud endpoint for the device which will then be received by the console application. You’ll want to request an acknowledgement, after all that is what we’re trying to show here!

For the purpose of ease, I’ve gone and created a message variable containing some simple JSON that I’m sending.

iothub-explorer send [deviceId] $msg --ack=full

So in this we’ve requested a full acknowledgement.

iothub-send.png

You’ll notice we get a message ID, this is what we use to see the feedback message.

iothub-receive.png

So we can see we have the same ID so we can correlate these two events which is pretty amazing.

You can see with a simple command line tool we are able interact with IoT Hub and monitor events from devices, and both send messages to a device from the cloud and receive feedback when that message has been received by the device.

I love iothub-explorer, I can see me using this all the time.

I hope you enjoy using it as much as I do!

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?