Connecting simple devices to IoT Central

Once you start collecting data in an IoT solution, you will need some kind of dashboard to represent the raw or aggregated data.

IoT projects typically start as a POC to validate IoT scenarios. When the POC success, a pilot project is started to check scalability, monitoring, maintainability, etc.

Microsoft provides multiple solutions for these various scenarios. The most lightweight solution is IoT Central.

Experience the simplicity of SaaS for IoT (Internet of Things), with no cloud expertise required—Azure IoT Central is a fully managed global IoT SaaS (software-as-a-service) solution that makes it easy to connect, monitor, and manage your IoT assets at scale. Bring your connected products to market faster while staying focused on your customers.”

You can start with a 7-day trial or with pay-as-you-go. This last option is free if you limit yourself to 5 actual or simulated devices.

At this moment, Microsoft has examples for the Raspberry Pi, the MX Chip IoT Devkit and Windows 10 IoT Core.

But what if you want to connect your own device? Is this simple to do too?

Let’s check this out.

There are two rules of thumbs regarding connecting to Azure IoT Central:

  1. You must at least be able to program against an Azure IoT Hub
  2. The messages you produce must have a simple JSON shape, no arrays, no difficult nesting of data

Let’s see what it takes to connect a device. In this example, I simulate a device using an Azure Function.

Azure Function as a device?

Yes, just to prove any device can connect to Azure IoT Central, I use an Azure Function. Of course, this is not ideal due to the stateless nature of the functions (this is not a durable function). And you will see this is not a scalable solution. It’s a good example that any ‘device’ can connect.

But first, let’s register out ‘device’ first.

Registering the device

Connect with an existing IoT Central application or create a new one. I recommend the trial version to start with. You can also start with the Pay-As-You-Go version and delete all simulations which you do not need right away.

You then start with a new device by registering a Device Template which is a description for a ‘family’ of the same devices. This means you have to tell something about the values arriving, standard properties of these devices or the default dashboard of such a device.

Here we see how the property of  the incoming telemetry, the ‘temp’ value is described:


This is an example of one of the properties of this message:

public class Command
  public decimal temp {get; set;}

  public decimal hum {get; set;}

  public int level {get; set;}

Note: Keep in mind that IoT Central only supports messages like these, arrays, etc. are not supported at this moment.

Just experiment with the fields. E.g. you can also add a state field.

After you entered the fields, IoT Central automatically create a simulated device:


But we want to add a physical device:


As you can see, IoT Central can add devices with a configurable Device ID.

But this information is not enough for a regular device to connect using any IoT Device SDK. No, we need credentials. IoT Central exposes device credentials using the connect button:


But again, the data provided is only useful if your device is ready for Azure Device Provisioning:


Why are we shown this information? It’s because IoT Central is hiding the IoT Hub and the Device Provisioning Service behind the IoTHub service. We only get to see what is needed to connect.

We only want to get the connection string behind our device. Luckily, Microsoft has a solution for us.

Key generation

Visit the GitHub page of the Azure IoT DPS Symmetric Key Generator. There you find the tooling to derive a connection string from the device administration in IoT Central:


First, you get the code from GitHub and compile it using:

git  clone
cd dps-keygen
npm i -g dps-keygen

Then, you generate the key using:

dps-keygen -di:deviceidhere -dk:devicekeyhere -si:scopeidhere

This is enough to generate a connection string.

Now we are ready to actually send some telemetry!

Azure Function as a device

Just create or open an Azure Function App. In there, create a new function triggered by a timer. Set the timer to once every twelve seconds:

*/12 * * * * *

Note: This twelve is an optimal interval for IoT Central. If you send more messages per minute you are likely to be throttled. If you send fewer messages, some gaps could be shown in the diagrams.

First, add an extra file with a reference to the extra Nuget packages we use. Call this file function.proj:

<Project Sdk="Microsoft.NET.Sdk">
    <PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.21.0" />

Do not forget to save this file.

Note: I find the experience of adding Azure Function a nice way to explain the usage of serverless compute. But the portal experience is less good than using Visual Studio for writing Azure Functions. Adding NuGet packages the way described above can be tedious.

This will look like this:


Then, alter the actual function to:

#r "Newtonsoft.Json"

using System;
using Newtonsoft.Json;
using System.Text;
using Microsoft.Azure.Devices.Client;

public static void Run(TimerInfo myTimer, ILogger log)
  log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");

  // Connect to IoT Hub
  var connectionString = "[IoT Central IoT Hub connectionstring]";
  using (var deviceClient = DeviceClient.CreateFromConnectionString(connectionString, TransportType.Mqtt))
    var temp = (new Random(DateTime.Now.Millisecond) ).Next(-30,70);
    var hum = (new Random(DateTime.Now.Millisecond) ).Next(0,100);
    var level = (new Random(DateTime.Now.Millisecond) ).Next(0,3);

    log.LogInformation($"temp: {temp}; hum: {hum}; level: {level}");

    var messageString = JsonConvert.SerializeObject(new Command { temp = temp, hum = hum, level = level });
    var message = new Message(Encoding.ASCII.GetBytes(messageString));

public class Command
  public decimal temp {get; set;}
  public decimal hum {get; set;}
  public int level {get; set;}

And that’s it…

Save the function and check the log of it. It should look like this:

2019-04-06T19:26:09.997 [Information] Executing 'Functions.TimerTrigger1' (Reason='Timer fired at 2019-04-06T19:26:09.9968182+00:00', Id=e24f2fc0-9f76-48fb-8068-a2c51ac4be45)
2019-04-06T19:26:09.997 [Information] C# Timer trigger function executed at: 4/6/2019 7:26:09 PM
2019-04-06T19:32:30.001 [Information] temp: -6; hum: 24; level: 0
2019-04-06T19:26:10.066 [Information] Executed 'Functions.TimerTrigger1' (Succeeded, Id=e24f2fc0-9f76-48fb-8068-a2c51ac4be45)

2019-04-06T19:26:20.005 [Information] Executing 'Functions.TimerTrigger1' (Reason='Timer fired at 2019-04-06T19:26:20.0051185+00:00', Id=4ed24bc0-c013-40d5-801c-9fe8761e30a5)
2019-04-06T19:26:20.005 [Information] C# Timer trigger function executed at: 4/6/2019 7:26:20 PM
2019-04-06T19:32:09.995 [Information] temp: 23; hum: 53; level: 1
2019-04-06T19:26:20.111 [Information] Executed 'Functions.TimerTrigger1' (Succeeded, Id=4ed24bc0-c013-40d5-801c-9fe8761e30a5)

So the data is sent. Let’s check out if it is arriving.

Note: I got this error “SerializeObject Could not load the specified file.” while creating my function. Please drop your function and retry this step if you get it too.

IoT Central dashboard

Check the incoming measurements of your device:


Yes, the telemetry is arriving!

You can now start making use of the full power of IoT Central. This is an example of a simple device dashboard:



We have seen how easy it is to connect any IoT device as long as you can make use of the Azure IoT Device SDK. This includes devices which do not support the DPS directly.

In this example, I demonstrated even an Azure Function can connect to IoT Central. This is not recommended in a production scenario. I can be used though if you want to offer a dashboard scenario in a POC. This way, you can discuss dashboards in general and which KPIs to show at what interval.