Introduction to the IoT Edge SDK, part 4

We have already made great progress understanding and using the Azure Gateway SDK.

What do we have right now? We can send telemetry data from multiple ‘offline’ devices and accept commands from the IoT Hub.

The data we send is well-formatted JSON so we are good to go.

But I am a bit worried. While reading all documentation regarding the transformation from Azure Gateway SDK towards the IoT Edge SDK, it is clear that multiple types of messages are sent to the IoT Hub. For example, I can imagine that a Stream Analytics module generates other data.

And let’s look at a more ‘close to earth’ example. The gateway itself is a potential device too! But I do not want to mix data coming from the gateway and from sensor devices.

Of course, we recently got the ability to route messages using the message sent. But what about using the properties? This keeps the message content clean.

Will this be working?

This blog is the fourth part of a series:

  • Part one, how to use modules, gateway configuration and the broker
  • Part two, connecting to the IoT Hub
  • Part three, message to device
  • Part four, IoT Hub Routing

Sending an extra routing property

So the idea is to make use of the routing capabilities of the IoT Hub. Let’s try to pass on an extra property:

...
var data = new Dictionary<string, string>
{
  { "source", "sensor" },
  { "route", "dummy" },
  { "macAddress", device.macAddress }
};
...

Here we just pass this property ‘route’ with the value ‘dummy’. We see the arrival in the Device Explorer tool:

Note: I choose ‘dummy’ just to make sure no routing rule would pick it up. Once a route picks up a message, this message is not shown anymore in the Device Explorer tool.

Create a route

Now let’s create a route.

First, we create a new EventHub which will hold all routed messages.

Next, we define an IoT Hub endpoint for this EventHub.

Finally, we create this route:

We are interested in ‘sensor’ messages.

So we have this route running:

Fixing the ‘dummy’ value

Now it’s time to fix the ‘dummy’ value, we want to messages coming from sensors to be picked up by this route:

...
var data = new Dictionary<string, string>
{
  { "source", "sensor" },
  { "route", "sensor" },
  { "macAddress", device.macAddress }
};
...

Arrival of messages in the EventHub

Now start the gateway.

After a while we check the EventHub:

And there we see the arrival of the messages.

Missing properties in message

Using routing has one disadvantage: We are losing the specific IoT Hub properties.

If we look at the output of routing toward an EventHub and we compare it to Stream Analytics Job query messages, we will see only the Message content of the gateway message passed. There are NO properties, and more important: there are no IoT Hub fields. So we do not know from which device the data is coming and we do not know the date and time of arrival of the message.

If we want to know these two properties, we have to add it in the message content. And we can add them with a new module which is put between the Identity Mapper and the IoT Hub.

So I built this extra module:

using System;
using Microsoft.Azure.IoT.Gateway;
using Newtonsoft.Json;
using System.Text;

namespace SensorModule
{
  public class EnrichRoutingModule : IGatewayModule, IGatewayModuleStart
  {
    private Broker broker;

    public void Create(Broker broker, byte[] configuration)
    {
      this.broker = broker;
    }

    public void Start()
    {
      Console.WriteLine("EnrichRoutingModule started");
    }

    public void Destroy()
    {
    }

    public void Receive(Message received_message)
    {
      if (received_message.Properties.ContainsKey("deviceName"))
      {
        var now = DateTime.Now.ToUniversalTime();
        var deviceName = received_message.Properties["deviceName"];
        var dynamicMessage = JsonConvert.DeserializeObject<dynamic>(Encoding.UTF8.GetString(received_message.Content));
        dynamicMessage.dateTime = now;
        dynamicMessage.deviceName = deviceName;
        var jsonString = JsonConvert.SerializeObject(dynamicMessage);
        var newMessage = new Message(Encoding.UTF8.GetBytes(jsonString), received_message.Properties);
        broker.Publish(newMessage);
      }
    }
  }
}

The two properties are added without any effort. The incoming message is transformed to a dynamic and two properties are inserted. Afterward, the new, extended, message is sent using the broker.

This is the configuration:

...
{
  "name": "enrich_routing_module",
  "loader": {
    "name": "dotnet",
    "entrypoint": {
      "assembly.name": "DotNetModuleSample",
      "entry.type": "SensorModule.EnrichRoutingModule"
    }
  },
  "args": ""
},
...

this is how I link this module between the Identity Mapper module and the IoT Hub module:

...
{
  "source": "identity_map_module",
  "sink": "enrich_routing_module"
},
{
  "source": "enrich_routing_module",
  "sink": "iothub_module"
},
...

Now, I have all information regarding which device has sent what data at what time stamp:

Conclusion

IoT Hub routing is an effective way to separate messages coming from connected sensors, the gateway itself and additional services like the upcoming StreamAnalytics.

 

 

 

 

Advertenties