Azure SDK for C Arduino ESP2866 sample comes with Telemetry and Cloud to Device Me3ssaging. It does not include Direct Methods so lets implement that making deeper use of the SDK.

Scenario

  • Hub sends Direct Method with or without payload
    • If recognised by device and has any required parameters in payload
      • Action the method
      • Postive acknowledgement
    • Else Negative acknowledgement

Device Setup

  • After the WiFi is setup, the WiFi Client is setup followed by MQTT:
    mqtt_client.setServer(host, port);
    mqtt_client.setCallback(receivedCallback);
    
  • Note the setting of the Callback
  • After MQTT is initialised, it needs to subscribe to ““$iothub/methods/POST/#””
     mqtt_client.subscribe(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC);
    
  • 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 Direct Methods, the topic starts with "$iothub/methods/" which can be used to differentiate Direct Methods from CD Messages and Twinning.

Sample Direct Method no Parameter

Direct Method called from VS Code (Azure IoT Hub extension) : “stop”, blank payload

[C2DMessage] Sending message to [PicoDev2023] ...
[C2DMessage] [Success] Message sent to [PicoDev2023]
[DirectMethod] Invoking Direct Method [stop] to [PicoDev2023] ...
[DirectMethod] Response from [PicoDev2023]:
{
  "status": 200,
  "payload": {
    "request_id": 1,
    "method": "stop",
    "parameter": "\"\""
  }
}

The log in VS Code

========================================
Got IoT Hub Doc-Message-Method-Response
=========================================
Got Topic: $iothub/methods/POST/stop
  Got Payload
\\\\\\\\\\\\\\\\\\\\\\\
Direct Method: stop
Telemtry was stopped.
\\\\\\\\\\\\\\\\\\\\\\\
{
  "IsRunning": false,
  "TelemetryFrequencyMilliseconds": 10000,
} - END Callback
========================================

Arduino IDE Serial Terminal Log of a Direct Method call as on Device

The topic metainformation

The complete topic in this case is:

    Topic: $iothub/methods/POST/stop/?$rid=1

Interpretting the metainformation:

The method to call is embedded within the topic. The id increments with every method sent.

The Payload

Payload is actually a string of two double quote characters, so it is interpretted as blank..

Sample Direct Method with Parameter

Direct Method called from VS Code (Azure IoT Hub extension) : “frequency”, payload: “5”

[DirectMethod] Invoking Direct Method [frequency] to [PicoDev2023] ...
[DirectMethod] Response from [PicoDev2023]:
{
  "status": 200,
  "payload": {
    "request_id": 3,
    "method": "frequency",
    "parameter": "5"
  }
}

Log in VS Code

========================================
Got IoT Hub Doc-Message-Method-Response
========================================
  Topic: $iothub/methods/POST/frequency/?$rid=3
Got Topic: $iothub/methods/POST/frequency
  Got Payload
\\\\\\\\\\\\\\\\\\\\\\\
Direct Method: frequency
Telemetry Period is now: 5 sec.
Telemtry is running.
\\\\\\\\\\\\\\\\\\\\\\\
{
  "IsRunning": true,
  "TelemetryFrequencyMilliseconds": 5000
} - END Callback
========================================

Log in serial terminal, from device perspective

Implemented Methods on the device.

Note case sensitive; would be easy to make it case insensitive. Also only first 4 characters required.

  • start
    • No Payload
  • stop
    • No payload
  • frequency
    • Requires a payload.
    • (In VS Code) After first return enter a period (in seconds) then press enter.
  • Toggle
    • Toggles the builtIn LED
    • Note that this also toggles with MQTT telemetry sends.
    • This could esily be a Cloud activated relay or other actuator.

Also: Added (simplistic) reset direct method that unsubscribes mqtt subscriptions, turns off/disconnects serial, wifi, mqtt etc and recalls setup().

Direct Methods from Azure Iot Explorer

THe Explorer approach allows for the setting of a timeout.

Console InvokeDirectMethodFrequency App

There are 4 console apps in the repository; one for Direct Methods InvokeDirectMethodFrequency. This sets the period (need to change frequency to period!) between Telemetry sends.

// s_connectionString is the IOT Hub Connectioon string
s_serviceClient = ServiceClient.CreateFromConnectionString(s_connectionString);
  // Invoke the direct method on the device, passing the payload
  private static async Task InvokeMethod(int period)
  {
      var methodInvocation = new CloudToDeviceMethod("frequency") { ResponseTimeout = TimeSpan.FromSeconds(30) };
      methodInvocation.SetPayloadJson(period.ToString());

      // Invoke the direct method asynchronously and get the response from the simulated device.
      var response = await s_serviceClient.InvokeDeviceMethodAsync(s_DeviceName, methodInvocation);

      Console.WriteLine("Response status: {0}, payload:", response.Status);
      Console.WriteLine(response.GetPayloadAsJson());
  }

Typical output is:

IoT Hub Direct Method - Back-end application.

Using Env Var IOTHUB_CONN_STRING_CSHARP = HostName=PicoHub2023.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=LKoTY/upWavEIoDYa1hSIH9cKGIVSo6WtyF1GbEYW/U=
Using Env Var DEVICE_NAME (N.b.Same as DEVICE_ID) = PicoDev2023
Press Enter to continue when the device is sending messages.

2/4 Press Enter to change period again(15s)

15
Response status: 200, payload:
{"request_id":3,"method":"frequency","parameter":"15"}
3/4 Press Enter to change period again (5s)

5
Response status: 200, payload:
{"request_id":4,"method":"frequency","parameter":"5"}
4/4 Press Enter to change period again (2s)

Output of Console app that sends Direct Method request, with parameter


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