Adding an array to your ModuleTwin desired properties

The IoT Modules can be modified using the Azure portal. Microsoft provides two methods to change modules ‘over the air’:

  1. Module Identity Twin
  2. Direct Method
The Module Identity twin is simply a JSON document which contains information about the module: tags, desired properties, and reported properties.
In this article, we focus on the Module twin and especially the desired properties.
Most examples show how to pass a simple value (like an integer value or a string).
But what if we want to pass an array?

JSON supports arrays. So we could do something clever with a JSON array.

But I like the way that array values are passed as seen in the Modbus module:

{
 "PublishInterval": "2000",
  "Version":"2",
  "SlaveConfigs": {
    "Slave01": {
      "SlaveConnection": "192.168.0.1",
      ... 
    },
    "Slave02": {
      "SlaveConnection": "ttyS0",
      ...
    }
  }
}

Look at SlaveConfigs, is this really an array? Well yes, but it looks like it contains two separate JSON elements.

The clever part is that the “Slave01” and the “Slave01” describe what they are containing. And we can add as many ‘slaves’ as we want.

Example with code

Look at this JSON example:

{
  "someTestValue": "test",
  "configArray": {
    "configa": {
      "type": "aaa",
      "boolValue" : true,
      "intValue" : 42,
      "dateValue" : "2018-11-21T11:12:13"
    },
    "configb": {
      "type": "bbb",
      "boolValue" : false,
      "intValue" : 53,
      "dateValue" : "2018-10-20T14:15:16"
    }
  }
}

We can parse this construct with this code:

using Microsoft.Azure.Devices.Shared;
using System;
using System.IO;
 
namespace JsonArrayConsoleApp
{
  class Program
  {
    static void Main(string[] args)
    {
      var json = File.ReadAllText("jsontext.txt");
      var desiredProperties = new TwinCollection(json);

      if (desiredProperties.Contains("someTestValue") 
            && desiredProperties["someTestValue"] != null)
      {
        var someTestValue = desiredProperties["someTestValue"];
        Console.WriteLine($"someTestValue: {someTestValue}");
      }
 
      if (desiredProperties.Contains("configArray") 
            && desiredProperties["configArray"] != null)
      {
        var configArray = desiredProperties["configArray"];
 
        foreach (var config in configArray)
        {
          Console.WriteLine($"{config.Name}: {config.First.type} - {config.First.boolValue} - {config.First.intValue} - {config.First.dateValue}");
 
          string c = config.First.type;
          bool b = (bool) config.First.boolValue;
          int i = (int)config.First.intValue;
          DateTime d = (DateTime)config.First.dateValue;
 
          Console.WriteLine($"{config.Name}: type {c} - boolValue {b} - intValue {i} - dateValue {d}");
        }
      }
  
      Console.WriteLine("Press a key to exit");
      Console.ReadKey();
    }
  }
}

There are a few things to notice:

  • We check properties for both to exist and not being null. This is because, if an element is removed in the Azure portal by setting it to NULL, the property is sent to the module:

  • The description of an array element is named ‘Name’.
  • To read the properties of an element, make sure you cast them to the right type! Until then they are just dynamic values which give ugly runtime exceptions (mostly type cast errors).

The outcome is:

someTestValue: test
configa: aaa - True - 42 - 11/21/2018 11:12:13 AM
configa: type aaa - boolValue True - intValue 42 - dateValue 11/21/2018 11:12:13 AM
configb: bbb - False - 53 - 10/20/2018 2:15:16 PM
configb: type bbb - boolValue False - intValue 53 - dateValue 10/20/2018 2:15:16 PM
Press a key to exit

Conclusion

Now you can safely add meaningful arrays to your module twin collection.

Advertenties