Using a Weidmueller UC 20 Controller as Azure IoT Edge child device

Azure IoT Edge is a powerful solution for your edge computing needs. It can collect telemetry, make local decisions, and send data to the cloud. This works great if an internet connection is available. If the connection is temporarily broken, everything still works. The telemetry is temporarily persisted so no data is lost.

An edge gateway can also act as a transparent gateway:

Here, child devices are made part of the local routing mechanism of the edge. The child devices are configured to send their telemetry to the edge device. From there, the same telemetry is sent to the cloud as if it’s sent by the child device itself.

The main advantages are:

  1. If no internet connection is available, the child telemetry is stored on the edge until the connection is restored. The child devices have no notion of the edge gateway, hence ‘transparent’
  2. The logic running on the edge is able to access the telemetry coming from child devices so this can be used and combined with other data to take local decisions

This architecture is also known as downstream devices.

I already wrote a blog on this topic previously. In there, some test apps stole the show.

Now, let’s see this in action with an actual industrial device. We also check out sending telemetry back:

We will be working with a Weidmueller UC20, an automation controller.

This controller runs Node-Red so it can be connected to the cloud:

This makes it possible to run both the controller logic and additional Node-Red logic side-by-side.

Azure portal configuration

First, we need to create a device registration for the UC20 controller:

With this registration, we also select the already registered edge device ‘Uno2372G’ as being the parent device. Both child and edge devices run on the same local network so they can ‘see’ each other.

Azure IoT Edge configuration

As seen in my previous blog, for each edge gateway, x509 certificates must be generated so child devices are trusted to communicate with the edge using the same routing mechanism. Here is a list of test certificates as an example (seen in my previous blog):

Note: The certificate needed for the child device is already highlighted.

Some of these certificates need to be configurated in the config.yaml of the IoT edge device (e.g. see /etc/iotedge/config.yaml in Linux):

Note: These certificates are needed to secure the IoT Edge routing in general. A vanilla edge runtime comes with a development certificate which will expire within ninety days. So you get the child-parent relationship for free.

Last but not least, you need the DNS name of your edge gateway which represents the local IP address of it. You can look it up in, again, the config.yaml of your IoT edge device:

The edge gateway is now ready to be used as parent device. We move over to the child device configuration.

Configuring the UC20 controller as a downstream device

First, the controller needs two big changes before we can use it as an IoT Edge device:

  1. Add a new Node-Red node to make it a child device
  2. Upgrade to the newest firmware to support DNS lookups

Upgrading Node-Red with a new Azure Device node

The UC20 controller runs Node-Red on a separate core so it does never interrupt the factory logic on the controller. The initial installation of NodeRed comes with several Azure nodes preinstalled.

It is recommended to ignore these nodes due to several reasons. Actually, we have to use a, far more superior, newer node which supports the child device configuration:

Add this ‘node-red-contrib-azure-iot-device’ to the palette in NodeRed:

Note: A restart of your controller is needed after the installation of the node.

Upgrading to the newest UC20 controller firmware

The newest UC20 controller firmware (V1.10.0 and up) support resolving DNS names. This is needed for our node to reach the edge gateway.

You can find the latest firmware here:

Note: Read the release notes before you upgrade. You need to perform an extra step before installing the full firmware update.

Once you have installed the firmware update, give the controller a fixed IP address and set up multiple DNS server addresses:

Here, I configured both the local DHCP router as a DNS server and also the primary and secondary DNS servers of Google.

Setting up the node

Once the Azure IoT device node is installed, I suggest using the example flow to get started:

Azure IoT Device node example

This generates a full example with sample telemetry and a Direct Method named ‘blink’.

Open the Device node and fill in the identity information as seen in the Azure portal for the ‘weidmueller’ device:

We are also interested in the ‘IoT Edge Gateway’ tab:

Here, we fill in both the DNS hostname ‘adminsv-UNO-2372G-J031AE’ of the edge gateway. And we upload the certificate ‘azure-iot-test-only.root.ca.cert.pem’ to connect.

Deploy the flow and see how the device node connects:

But where is it connected to?

Note: We will change the setup a little later on. For now, let’s test the setup and see the actual connection.

Testing the connection

In Azure, we see the incoming messages of our connected Weidmueller UC20 controller:

So, the UC20 controller is connected to the cloud

So, the UC20 controller is connected to the cloud at least. Is the controller also making use of the Edge gateway? Is the telemetry flowing through the edge?

To test this, I deployed an iot-edge-echo module on the edge:

It just writes messages to the console and is perfect to test the message flow on the edge. This module must show us the UC20 controller messages are flowing through the routing mechanism.

We attach it to incoming messages from child devices. We can recognize them because these messages are not coming from any module with this route:

FROM /messages/* WHERE NOT IS_DEFINED($connectionModuleId) INTO BrokeredEndpoint("/modules/echo/inputs/input1")

Use it next to the route used for sending all messages upstream:

Once this setup is deployed, we can check for incoming messages coming from the child device:

Yes, the telemetry is available on the edge!

As you can see the name of the device which sent the messages is seen in two ways:

  1. the ‘ConnectionDeviceId’ is a property of the incoming message
  2. the message application property named ‘localDevice’ is something I added in NodeRed

So there are two ways to play with the device Id. It’s up to you to do cool stuff with them.

The message application property is set here in the ‘telemetry’ node:

You can now add any property to the message.

As you can see, we are in full control of messages sent by child devices and messages received in the parent edge gateway!

Sending back commands

We can retrieve messages from the UC20 controller. Are we also able to send commands back?

In the past, I wrote a blog about executing direct methods between modules on the Edge gateway. We can make use of the same call to send direct methods to child devices.

To demonstrate this, I altered the node for direct methods a bit:

In the Device node, this ‘blink’ method was already defined:

The altered function node which handles the command response doubles the ‘action’:

With this set in the UC20 controller, we call the direct method from the edge.

To make a DirectMethod call, executed on the edge, we need some custom code in an extra module.

So I wrote this module which accepts a direct method called ‘ExecuteBlink’. Once called, it executes a ‘blink’ on the UC20 controller using the deviceId ‘weidmueller’. The response from the child is then sent back:

namespace ChildDirectMethodModule
{
    ...

    class Program
    {
        ...

        /// <summary>
        /// Initializes the ModuleClient and sets up the callback to receive
        /// messages containing temperature information
        /// </summary>
        static async Task Init()
        {
            ...
            Console.WriteLine("IoT Hub module client initialized.");

            await ioTHubModuleClient.SetMethodHandlerAsync("ExecuteBlink", MethodModule, ioTHubModuleClient);

            Console.WriteLine("Direct method 'ExecuteBlink' attached.");
        }

        private async static Task<MethodResponse> MethodModule(MethodRequest methodRequest, object userContext)
        {
            Console.WriteLine($"Method request 'ExecuteBlink' for 'weidmueller' received at {DateTime.Now}");

            ModuleClient ioTHubModuleClient = (ModuleClient)userContext;

            var request = new MethodRequest("blink", methodRequest.Data);
            var responseBlink = await ioTHubModuleClient.InvokeMethodAsync("weidmueller", request).ConfigureAwait(false);

            Console.WriteLine($"method response {responseBlink.Status} received: '{responseBlink.ResultAsJson}'");

            var responseBody = new ResponseBody
            {
                result = responseBlink.ResultAsJson
            }; 

            var json = JsonConvert.SerializeObject(responseBody);
            var response = new MethodResponse(Encoding.UTF8.GetBytes(json), 200);

            return response;
        }
    }

    public class ResponseBody
    {
        public string result {get;set;}
    }
}

So, we call this direct method on the edge device using the Azure portal:

We get back from the edge this response:

This ‘inner result’ is just the response of our Weidmueller controller.

Yes, the message result is altered by our Weidmueller controller:

Conclusion

We have seen how a Weidmueller UC20 controller, as a child device, works well together with an Azure IoT edge transparent gateway.

The controller exposes its telemetry to the cloud under its own device name while all telemetry flows through the gateway.

Meanwhile, the telemetry is accessible for modules running on the edge using the secure routing mechanism.

Finally, using that same routing mechanism, we are able to send commands back to the controller based on decisions made by the edge gateway. This makes it possible to combine telemetry from eg. multiple controllers and other sources to make new decisions.

So, this opens up numerous new southbound architectures on the edge and beyond.