This is the fifth part in a series of blog posts looking at integrating Zebra Android devices as IoT clients in a public cloud infrastructure.  For other posts in this series, please see the links below:


This post will walk through an example cloud IoT infrastructure using Azure IoT Hub as the entry point.  A C# MQTT client will mimic device location, Android OS info and battery information with this data being shown in a Power BI dashboard.  Critically low battery levels will be emailed so an administrator can take immediate action to replace the batteries.  The next part in this series will move to using a real device.


This example is based on Microsoft’s tutorial which covers configuring message routing with IoT hub. I have simplified the tutorial slightly by removing the storage container but please refer back to the original tutorial for more detail.



  • This is a very simple example but the aim is to show the principles of injecting IoT data into Azure and how that data might be processed or stored for later retrieval and analysis.
  • Any hosted cloud computing solution may incur costs.  Please ensure you are aware of the costs associated with the cloud components you are using and how to monitor and set spending limits.



  • Publish simulated device telemetry using the Azure Devices Client SDK
  • Receive device telemetry into Azure using the IoT Hub
  • Set up a message route to perform a special action for devices with critical battery level.
  • Use a Service Bus and logic app to send an email to notify an administrator when a device has a critically low battery
  • Visualize received data using a Power BI dashboard
  • Data that will be simulated along with some sample values is defined in JSON as follows:

  "deviceId": "test-device",

  "dateTime": "[String representation of date]",

  "model": "TC57",

  "lat": "35.6602997",

  "lng": "139.7282743",

  "battLevel": "[Randomly generated]",

  "battHealth": "[Randomly generated]",

  "osVersion": "8.1.0",

  "patchLevel": "2019-02-01",

  "releaseVersion": "01-10-09.00-OG-U00-STD"


Source Code:

The source code discussed in this tutorial is available from GitHub.



  • An Azure subscription.  If you do not have an Azure subscription you can create a free account before you begin.
  • An installation of Visual Studio (to run the simulator)
  • A Power BI account to analyse the stream analytics.
  • An Office 365 account to send notification emails.


Set up resources:

It is necessary to create some resources in Azure to facilitate this tutorial.  The easiest way to create resources is using the Azure Cloud Shell

  • Open the Azure portal
  • Select the Cloud shell button on the menu in the upper-right corner of the screen

Cloud Shell in the portal

The following Azure CLI script will create the following:

  • A resource group
  • An IoT hub in the S1 tier with a consumer group which is used by the Azure Stream Analytics when retrieving data
  • A Service Bus namespace and queue
  • A device identity for the simulated device that sends messages to the hub.

Although the Azure Cloud Shell supports both Azure CLI and PowerShell, for simplicity only the Azure Bash commands are given here (and in GitHub) – paste these into the Azure Cloud shell and execute:


Note that the variables which must be globally unique have $RANDOM concatenated to them, be sure to make a note of the actual names of the generated resources when using them in subsequent steps. 

# This is the IOT Extension for Azure CLI.

# You only need to install this the first time.

# You need it to create the device identity.

az extension add --name azure-cli-iot-ext

# Set the values for the resource names that don't have to be globally unique.

# The resources that have to have unique names are named in the script below

#   with a random number concatenated to the name so you can probably just

#   run this script, and it will work with no conflicts.






# Create the resource group to be used

#   for all the resources for this tutorial.

az group create --name $resourceGroup \

    --location $location

# The IoT hub name must be globally unique, so add a random number to the end.


echo "IoT hub name = " $iotHubName

# Create the IoT hub.

az iot hub create --name $iotHubName \

    --resource-group $resourceGroup \

    --sku S1 --location $location

# Add a consumer group to the IoT hub.

az iot hub consumer-group create --hub-name $iotHubName \

    --name $iotHubConsumerGroup

# The Service Bus namespace must be globally unique, so add a random number to the end.


echo "Service Bus namespace = " $sbNameSpace

# Create the Service Bus namespace.

az servicebus namespace create --resource-group $resourceGroup \

    --name $sbNameSpace \

    --location $location

# The Service Bus queue name must be globally unique, so add a random number to the end.


echo "Service Bus queue name = " $sbQueueName

# Create the Service Bus queue to be used as a routing destination.

az servicebus queue create --name $sbQueueName \

    --namespace-name $sbNameSpace \

    --resource-group $resourceGroup

# Create the IoT device identity to be used for testing.

az iot hub device-identity create --device-id $iotDeviceName \

    --hub-name $iotHubName

# Retrieve the information about the device identity, then copy the primary key to

#   Notepad. You need this to run the device simulation during the testing phase.

az iot hub device-identity show --device-id $iotDeviceName \

    --hub-name $iotHubName


After some time, the script will finish running.  I recommend you take a copy of the output so you can refer to it later.


Verify the test device was created:

The script which was ran in the previous stage will create an iot device as the penultimate step. To check that the iot test device was successfully created:

  • Open the Azure portal
  • Click on Resource groups and select your resource group, EntAndroidResources in the case of this tutorial.
  • In the list of resources, click your IoT hub, EntAndroidHub in the case of this tutorial.
  • Select IoT Devices from the hub pane
  • You should see a single device, test-device

  • If you click on test-device you will be presented with the keys and connection string associated with this device.
    • Both the primary key and connection string will be required in subsequent steps of this and the next tutorial respectively so make a note of these for future reference.


Set up message routing

We are going to route messages to different resources based on properties attached to the message by the device or simulated device.  Messages that are not custom routed are sent to the default endpoint.


Value Result
battLevel <= 15 Write to a Service Bus queue. A Logic App retrieves the message from the queue and uses Office 365 to e-mail the message.
Default Display this data using Power BI


Note: In a real solution we would probably also route those messages with battery level <= 15 to the Power BI dashboard but for consistency with the parent tutorial, I will keep things simple here.


Routing to a Service Bus queue

  • In the Azure portal, click Resource Groups, then select your resource group.  This tutorial uses EntAndroidResources.
  • Click the IoT hub under the list of resources, EntAndroidHub in the case of this tutorial.
  • Click Message Routing.
  • In the Message routing pane, click +Add.
  • On the Add a Route pane, click +Add next to the endpoint field and select Service bus queue.

  • On the Add Service Endpoint pane specify the following fields:
    • Endpoint Name, CriticalBatteryQueue in the case of this tutorial
    • Service Bus Namespace: From the dropdown list select the service bus namespace created in the preparation steps.  This tutorial uses EntAndroidSBNamespace.
    • Service Bus queue: From the dropdown list select the service bus queue created in the preparation steps.  This tutorial uses entandroidsbqueue.

  • Click Create to add the Service Bus queue endpoint.
  • Now complete the rest of the routing query information.  This query specifies the criteria for sending messages to the Service Bus queue which was just added as an endpoint:
    • Name: Name of the routing query, this tutorial uses SBQueueRoute
    • Endpoint: The previously configured endpoint, in this case CriticalBatteryQueue
    • Data source: Select ‘Device Telemetry Messages’ from the dropdown list.
    • Routing query: Enter batteryLevel=”critical” as the query string.  In subsequent steps we will assign this in the client when the battery level is critical.

  • Click Save. You will be returned to the routes pane to see the route you just configured


  • Close the Message Routing pane, which returns you to the Resource group pane.


Create a Logic App

The Service Bus queue will receive critical battery level messages.  Set up a Logic app to monitor the Service Bus queue and send an email when a message is added to the queue.

  • In the Azure portal, click +Create a resource.  Put “logic app” in the search box and click Enter. From the search results displayed, select Logic App, then click Create to continue to the Create logic app pane.  Fill in the fields:
    • Name: This field is the name of the logic app, EntAndroidLogicApp in this tutorial.
    • Subscription: Select your Azure subscription
    • Resource group: Click ‘Use existing’ and select your resource group, EntAndroidResources in the case of this tutorial.
    • Location: This tutorial uses West US as specified when we set up the resources.
    • Log Analytics: This toggle should be turned off.

  • Click create.
  • Open the Logic App.  The easiest way to get to the Logic App is to click on Resource groups, select your resource group, then select the Logic App from the list of resources.  The Logic Apps Designer page appears (you might have to scroll over to the right to see the full page).  On the Logic Apps Designer page, scroll down until you see the tile in the Templates section that says Blank Logic App + and click it.
  • Select the Connectors tab and from the displayed connectors select Service Bus.

  • A list of triggers is displayed.  Select Service Bus – When a message is received in a queue (auto-complete).

  • On the next screen, fill in the Connection Name.  This tutorial uses EntAndroidConnection

  • Click the Service Bus namespace (EntAndroidSBNamespace in the case of this tutorial).  When you select the namespace, the portal queries the Service Bus namespace to retrieve the keys.  Select and click Create.

  • On the next screen, select the name of the queue (this tutorial uses ‘entandroidsbqueue’) from the dropdown list.  You can use the defaults for the rest of the fields.

  • Now set up the action to send an email when a message is received in the queue.  In the Logic Apps Designer click + New step to add a step.  In the Choose an action pane, find and click Office 365 Outlook. On the triggers screen, select Office 365 Outlook – Send an email.

  • Next, log into your Office 365 account to set up the connection.  Specify the email address for the recipient(s) of the emails. Also specify the subject, and type what message you would like the recipient to see in the body.  For testing, fill in your own email address as the recipient.
    • Click Add dynamic content to show the content from the message that you can include.  Select Content – it will include the message in the email.

  • Click Save then close the Logic App Designer.


If you wish, you can now jump directly to the “Run Simulated Device app” step to verify that you have configured the message route, Service Bus and Logic app correctly but in the next step, we will configure the stream analytics job that will power the Power BI dashboard


Set up Azure Stream Analytics

To see the data in a Power BI visualization, first set up a Stream Analytics job to retrieve the data. For consistency with the tutorial on which this tutorial is based only non-critical battery events are sent to the default endpoint and will be retrieved by the Stream Analytics job for the Power BI visualization.


Create the Stream Analytics job

  • In the Azure portal, click Create a resource > Internet of Things > Stream Analytics job.
  • Enter the following information for the job
    • Job name: The name of the job, EntAndroidJob in the case of this tutorial.
    • Resource group: Use the same resource group used by your IoT hub.  This tutorial uses EntAndroidResources.
    • Location: Use the same location as specified in the setup script, ‘West US’ in the case of this tutorial.

  • Click Create to create the job.  To get back to the job, click Resource groups, select the resource group (EntAndroidResources in the case of this tutorial) then click the Stream Analytics job in the list of resources.


Add an input to the Stream Analytics job

  • Under Job Topology, click Inputs.
  • In the Inputs pane, click Add stream input and select IoT Hub.  On the screen that comes up, fill in the following fields:
    • Input alias: This tutorial uses entandroidinputs
    • Subscription: Select your subscription
    • Iot Hub: Select the IoT Hub.  This tutorial uses EntAndroidHub
    • Endpoint: Select Messaging
    • Shared access policy name: Select iothubowner which should be the default
    • Consumer group: Select the consumer group created as part of the resource setup. This tutorial uses entandroidconsumers
    • For the rest of the fields, accept the defaults

  • Click Save.


Add an output to the Stream Analytics job

  • Under Job Topology, click Outputs.
  • In the Outputs pane, click Add, then select Power BI.  On the screen that comes up, fill in the following fields:
    • Output alias: The unique alias for the output.  This tutorial uses entandroidoutputs.
    • Dataset name: Name of the dataset to be used in Power BI.  This tutorial uses entandroiddataset.
    • Table name: Name of the table to be used in Power BI.  This tutorial uses entandroidtable.
    • Accept the defaults for the rest of the fields.

  • Click Authorize and sign into your Power BI account.
    • At this point you can choose to change the Group workspace should you wish to do so.  This tutorial will use the default ‘My workspace’.
    • You can create additional workspaces from the Power BI tool.
  • Click Save


Configure the query of the Stream Analytics job

  • Under Job Topology, click Query.
  • Replace [YouOutputAlias] with the output alias of the job.  This tutorial uses entandroidoutputs.
  • Replace [YourInputAlias] with the input alias of the job.  This tutorial uses entandroidinputs.

  • Click Save.
  • Close the Query pane and return to the view of the resources in the Resource Group. Click the Stream Analytics job, EntAndroidJob in the case of this tutorial.


Run the Stream Analytics Job

  • In the Stream analytics job, click Start > Now > Start.  Once the job successfully starts, the job status changes from Stopped to Running.

  • Data is required to set up the Power BI report therefore the next step is to run a simulated device app before setting up the Power BI dashboard.


Run Simulated Device app

When setting up resources for this tutorial a test device was automatically created (see also the earlier section on “Verify the test device was created”).  In this section we will use a .NET console app that simulates a physical device sending device-to-cloud messages to an IoT hub, including the generation of random critically low battery events.


Download the solution for IoT Device simulation from GitHub. This is based on the solution from the original tutorial but I have modified it to pass device telemetry such as battery level and location information.


Open the solution file (IoT_SimulatedDevice.sln) in Visual Studio and open Program.cs.  Substitute the correct values for your iotHubUri and deviceKey.  The format of the IoT hub hostname is {iot-hub-name} (this tutorial uses


You can find the values for your test device from the Device details pane in Azure (see the previous section, “Verify the test device was created”).  You want to ‘Primary key’ and ‘HostName’ which is part of the ConnectionString.

private readonly static string s_myDeviceId = "test-device";    //  Device Id

private readonly static string s_iotHubUri = ""; // HostName

private readonly static string s_deviceKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";  //  Primary Key

Run and test

Run the console application. Wait a few minutes.  You can see the messages being sent on the console screen of the application of which around 20% should be critical battery messages.


The app sends a new device-to-cloud message to the IoT hub every second.  The message contains a JSON-serialized object with the device ID and some mocked telemetry data.  The batteryLevel property will be set to “critical” if the randomly generated value drops below 15.

Critical battery events will generate an email (Courtesy of the Service Bus and Logic App) whilst normal battery events will be displayed in the BI report set up in the next step (courtesy of the Azure Stream Analytics)


If everything is set up correctly, at this point you should see the following results:

  • The console application reports that data is being successfully sent

  • Emails appear about critical messages containing the test data

This means that:

  • The routing to the Service Bus queue is working correctly.
  • The Logic App retrieving the message from the Service Bus queue is working correctly.
  • The Logic App connector to Outlook is working correctly


Set up the Power BI Visualizations

  • Sign in to your Power BI account.
  • Go to Workspaces and select the workspace that you set when you created the output for the Stream Analytics job.  This tutorial uses My Workspace.
  • Click the Datasets tab.
    • You should see the listed dataset that you specified when you created the output for the Stream Analytics job.  This tutorial uses entandroiddataset. (It may take 5-10 minutes for the dataset to show up the first time).
  • Under ACTIONS, click the first icon to create a report.

  • Create a line chart to show battery level over time
    • On the report creation page, add a line chart by clicking on the line chart icon.
    • On the Fields pane, expand the table you specified when you created the output for the Stream Analytics job, entandroidtable in the case of this tutorial.
    • Drag EventEnqueueUtcTime to Axis on the Visualizations pane.
    • Drag battLevel to Values