Tuesday, June 22, 2021

Convenience IoT Plug and Play APIs added to Azure IoT SDK (C# Preview)

We just added new APIs in preview in the Azure IoT SDK for C# that will make it easier and more intuitive for device developers to implement IoT Plug and Play, and we'd love to have your feedback.   

 

When we released IoT Plug and Play back in September 2020, we provided the Plug and Play specific helpers functions in the form of samples to help demonstrate the Plug and Play convention e.g., how to format Plug and Play telemetry message, how to ack on properties updates, etc. 

 

As IoT Plug and Play is becoming the "new normal" for connecting devices to Azure IoT, it is important that there is a solid set of APIs in the C# client SDK to help you efficiently implement IoT Plug and Play in your devices. IoT Plug and Play models expose components, telemetry, commands, and properties. These new APIs format and send messages for telemetry and property updates. They can also help the client receive and ack writable property update requests and incoming command invocations.  

 

These additions to the C# SDK can become the foundation of your solution, taking the load off your plate when it comes to formatting data and making your devices future proof. We introduced these functions in preview for now, so you can test them in your scenarios and give us feedback on the design.  Your feedback will help us to simplify, streamline and improve these APIs before we make them generally available. 

The NuGet package can be found here: https://www.nuget.org/packages/Microsoft.Azure.Devices.Client/1.38.0-preview-001  

We have created a couple of samples to help you get started with these new APIs, have a look at:  

https://github.com/Azure/azure-iot-sdk-csharp/blob/preview/iothub/device/samples/convention-based-sa... 

The API names are aligned with the concepts of the IoT Plug and Play convention, making development more intuitive. With IoT Plug and Play, we use the terminology telemetry, commands, properties and component in place of events, direct method and device twin, so we added these terms in the API name to make them more aligned with the concepts. 

 

For example, we introduced a couple of new types to help with convention operations mapped directly to the IoT Plug and Play concept and terminology.  For telemetry, we expose TelemetryMessage that simplifies message formatting for the telemetry, notably when you use component (here thermostat1) in the model: 

 

double temperature = 70.0D; 
using var telemetryMessage = new TelemetryMessage("thermostat1") 
{ 
    Telemetry = {["temperature"] = temperature }, 
}; 
await _deviceClient.SendTelemetryAsync(telemetryMessage, cancellationToken); 

 

For properties, we introduced the type ClientProperties which exposes the method TryGetValue.   
With this new type, accessing a device twin property becomes:  

 

// Retrieve the client's properties. 
 ClientProperties properties = await _deviceClient.GetClientPropertiesAsync(cancellationToken); 

// To fetch the value of client reported property "serialNumber" under component "thermostat1". 
bool isSerialNumberReported = properties.TryGetValue("thermostat1", "serialNumber", out string serialNumberReported); 

// To fetch the value of service requested "targetTemperature" value under component "thermostat1". 
bool isTargetTemperatureUpdateRequested = properties.Writable.TryGetValue("thermostat1", "targetTemperature", out double targetTemperatureUpdateRequest); 

 

Note that in that case, we have a component named thermostat1, first we get the serialNumber and second for a writable property, we use properties.Writable.  

Same pattern for reporting properties, we have now the ClientPropertyCollection, that helps to update properties by batch, as we have here a collection and exposing the method AddComponentProperty:  

 

// Update the property "serialNumber" under component "thermostat1". 
var propertiesToBeUpdated = new ClientPropertyCollection(); 
propertiesToBeUpdated.AddComponentProperty("thermostat1", "serialNumber", "SR-1234"); 
ClientPropertiesUpdateResponse updateResponse = await _deviceClient 
    .UpdateClientPropertiesAsync(propertiesToBeUpdated, cancellationToken); 
long updatedVersion = updateResponse.Version; 

 

With this, it became much easier to respond to top-level property update requests even for a component model: 

 

await _deviceClient.SubscribeToWritablePropertiesEventAsync( 
    async (writableProperties, userContext) => 
    { 
        if (writableProperties.TryGetValue("thermostat1", "targetTemperature", out double targetTemperature)) 
        { 
            IWritablePropertyResponse writableResponse = _deviceClient 
                .PayloadConvention 
                .PayloadSerializer 
                .CreateWritablePropertyResponse(targetTemperature, CommonClientResponseCodes.OK, writableProperties.Version, "The operation completed successfully."); 
            var propertiesToBeUpdated = new ClientPropertyCollection(); 
            propertiesToBeUpdated.AddComponentProperty("thermostat1", "targetTemperature", writableResponse); 
            ClientPropertiesUpdateResponse updateResponse = await _deviceClient.UpdateClientPropertiesAsync(propertiesToBeUpdated, cancellationToken);       } 

 

As long as we stay in preview for these APIs, you ‘ll find the set of usual Iot Plug and Play samples, migrated to use these news APIs in the code repository, in the preview branch:  

https://github.com/Azure/azure-iot-sdk-csharp/tree/preview/iothub/device/samples/convention-based-sa... 

See project Thermostat for the non-component sample and TemperatureController for the component sample.  

Again, now is a great time to let us know of any feedback and comments on these APIs. Contact us, open an issue, and help us provide the right IoT Plug and Play API you need.  

Happy testing,  

Eric for the Azure IoT Managed SDK team  

 

Posted at https://sl.advdat.com/3gOkavw