Azure SDK for C Arduino ESP2866 sample comes with Cloud to Device Me3ssaging. Lets expand upon that..


  • Hub sends a Cloud to Device (CD) messages
    • Typically just a simple string
    • Device receives it and may or may not take action
    • Default is no acknowledgment from device to hub. May also be
      • Full
      • Only on error
      • Only on success

Device Setup

  • After the WiFi is setup, the WiFi Client is setup followed by MQTT:
    mqtt_client.setServer(host, port);
  • Note the setting of the Callback
  • After MQTT is initialised, it needs to subscribe to “devices/+/messages/devicebound/#”
  • The Callback gets called whenever a subscribed topic is received by the device from the hub
    • This gets a topic and payload as string parameters as well as a length of the payload.
       void receivedCallback(char* topic, byte* payload, unsigned int length);
  • This one method handles all corresponce from the hub
  • For CD Messages, the topic starts with devices/PicoDev2023/messages/devicebound which can be used to differentiate CD Messages from Direct Methods and Twinning.

Sample CD Msg Log on the Device

Message sent from VS Code (Azure IoT Hub extension) : “TestMsg”

Got IoT Hub Doc-Message-Method-Response
Got Topic: devices/PicoDev2023/messages/devicebound
  Got Payload
CD Message:
Message: TestMsg
 - END Callback

Arduino IDE Serial Terminal Log of a CD Message as on Device

The topic metainformation

The complete topic in this case is:

  Topic: devices/PicoDev2023/messages/devicebound/

Interpretting the metainformation:

  • %2F is code for an embedded forward slash (/).
  • %24 is code for the percent sign (%)

So on the device this metainformation doesn’t tell us anything new.

The Payload

This is simply the string messaging as sent. The message might also be a Json string, or any other string for that matter.

Note that similar to how the topic was “sanitized” the payload is santized such that the payload char array is copied to a buffer, the number as speciied by the length supplied, and a zero byte is inserted in the buffer at the end of that.

CD Message from Azure Iot Explorer

VS Code approach does not give you any option for CD Messages. Az IoT Explorer gives you more options. Sending a message from there results in more metainformation in the topic.

The Payload is as previous.

Sample topic:
devices/PicoDev2023/messages/devicebound/ Got Topic: devices/PicoDev2023/messages/devicebound

This can be deciphered as:

  • devices/PicoDev2023/messages/devicebound/
  • &%.ct=application/json
  • &%.ce=utf-8
  • &messageId=57dfdd2e-df2d-4558-8f80-fcf33b48cd1d

The first 2 parts are as previous. It also says that the message is a Json string (which it wasn’t) , its characters are 8 bit and it has a message ID as Guid.

Azure IoT Explorer enables additional metainformation to attached to the message. For example a TimeStamp can be added. This is prepended to the message payload. eg:

23/02/2023, 12:03:01 - TestMsg

A Custom Property can also be added, such Count=12. This is embedded in the topic just before the Message Id:



System properties can also be sent to the device. These can include a specification with respect to whethere an acknowledgement is required. By default none is required. Options are:

  • None _(DEFAULT) never send an acknowledgement)
  • Full (always send an acknowledgement)
  • Postive (successful transmisssion)
  • Negative (when there is an error)

Azure IoT Explorer selecting CD Messsage Ack type

With Ack=Full, that property can be deciphered from the topic as previous as:


The Acknowledgement is sent back automatically by the SDK software from the device. No further programming was required to make this happen.

Console SendCloudToDeviceMessages App

There are 4 console apps in the repository; one for CD Messages SendCloudToDeviceMessages. This facilitates more fine grain control over the sending of messages and getting the acknowledgement back.

    private async static Task SendCloudToDeviceMessageAsync(string msg, bool IsJson)
        var commandMessage = new
        commandMessage.ContentEncoding = "utf-8";
        if (IsJson)
            commandMessage.ContentType = "application/json";
        commandMessage.Ack = Ack; // Can be None(Default),Full,PostiveOnly,NegativeOnly
        // Is Full in this case
        //commandMessage.ExpiryTimeUtc = DateTime.UtcNow.AddSeconds(10)
        commandMessage.MessageId = Guid.NewGuid().ToString();
        await s_serviceClient.SendAsync(s_DeviceName, commandMessage);

        Console.WriteLine($"Message Sent: {msg}");
        if (Ack != DeliveryAcknowledgement.None)
            Console.WriteLine("Wait for feedback");
            Console.WriteLine("Press any key to continue.");

There is a ReceiveFeedbackAsync() method that awaits the Ack and prints details of it. Typical output without a timeout set is:

Send Cloud-to-Device messages
Receiving c2d feedback from service

Send Cloud-to-Device message
Receiving c2d feedback from service
Message Sent: This is a Cloud to device message.

Wait for feedback
Received feedback - StatusCode: Success
Received feedback - DeviceId: PicoDev2023
Received feedback - DeviceGenerationId: 638126533457352101
Received feedback - EnqueuedTimeUtc: 23/02/2023 2:37:18 AM
Received feedback - Description: Success
Received feedback - OriginalMessageId: 98a8d8b7-aebe-4310-9378-a69a700e3d79

When Timeout is set to deliberately timeout (used Now +0 sec) the feedback is:

Received feedback - StatusCode: Expired
Received feedback - DeviceId: PicoDev2023
Received feedback - DeviceGenerationId: 638126533457352101
Received feedback - EnqueuedTimeUtc: 23/02/2023 2:42:26 AM
Received feedback - Description: Message expired
Received feedback - OriginalMessageId: 0b09bb52-cfaf-4763-ad6a-29957d33dc5b

Note that the metainformation in the topic in this case, get shuffled a little. Also the Message ID is tagged as mid`` rather thanmessageid```.

CD Messages v Direct Methods

One could use CD Messages to trigger Methods on the devices. So why not? I guess its just that Direct Methods are meant for that with infrastrure aroudn them. A message can be lost, especially if no ack is required, whereas a Direct Method does require a resposne. Mesages can be reserved for adhoc messages that have no formal processing on the device. They could be used, for example, for heartbeat where the hub sends periodically sends a message and only if a certain number are missed, missing indivually don’t matter (for example where the hub is busy), causes the device to restart.

 This Category Links 
Category:Pico W AzSDK Index:Pico W AzSDK
  Next: > RPI-Pico-Arduino-AzSDK
<  Prev:   RPI-Pico-Arduino-AzSDK