-
Notifications
You must be signed in to change notification settings - Fork 7
IoT Hub Device Twins
Code example, working with Device Twins
- Set ID Scope
- Set Allowed connections
- Set DeviceAuthentication
Device twin bidning.
typedef struct _deviceTwinBinding {
const char* propertyName;
void* propertyValue;
int propertyVersion;
bool propertyUpdated;
DX_DEVICE_TWIN_TYPE twinType;
void (*handler)(struct _deviceTwinBinding* deviceTwinBinding);
void *context;
} DX_DEVICE_TWIN_BINDING;
bool dx_deviceTwinAckDesiredValue(DX_DEVICE_TWIN_BINDING* deviceTwinBinding, void* state, DX_DEVICE_TWIN_RESPONSE_CODE statusCode);
bool dx_deviceTwinReportValue(DX_DEVICE_TWIN_BINDING* deviceTwinBinding, void* state);
void dx_deviceTwinSubscribe(DX_DEVICE_TWIN_BINDING* deviceTwins[], size_t deviceTwinCount);
void dx_deviceTwinUnsubscribe(void);
void (*handler)(struct _deviceTwinBinding* deviceTwinBinding)
Example.
void device_twin_handler(DX_DEVICE_TWIN_BINDING *deviceTwinBinding);
Device twin types
typedef enum {
DX_TYPE_UNKNOWN = 0,
DX_DEVICE_TWIN_BOOL = 1,
DX_DEVICE_TWIN_FLOAT = 2,
DX_DEVICE_TWIN_DOUBLE = 3,
DX_DEVICE_TWIN_INT = 4,
DX_DEVICE_TWIN_STRING = 5,
DX_DEVICE_TWIN_JSON_OBJECT = 6
} DX_DEVICE_TWIN_TYPE;
Device twin acknowledgment codes
typedef enum
{
DX_DEVICE_TWIN_RESPONSE_COMPLETED = 200,
DX_DEVICE_TWIN_RESPONSE_ERROR = 500,
DX_DEVICE_TWIN_REPONSE_INVALID = 404
} DX_DEVICE_TWIN_RESPONSE_CODE;
DX_DEVICE_TWIN_HANDLER(name, deviceTwinBinding)
DX_DEVICE_TWIN_HANDLER_END
DX_DECLARE_DEVICE_TWIN_HANDLER(name)
Azure IoT Hub and IoT Central use device twins to represent point-in-time values. IoT Hub can use device twins to set state on a device, for example, set the desired room temperature. A device can also use device twins to report its current state, for example, report the operating mode of an HVAC (Heating, Ventilation, and Air Conditioning) unit, is it currently heating, cooling, or turned off.
Device twins are JSON documents that Azure IoT Hub keeps in the cloud for all devices and is used for storing device information, including metadata, configurations, and conditions. IoT Hub device twins are often used for long-running commands intended to put the device into a certain state and return it to that state after a device restart. For example, setting the desired room temperature.
Properties can be used in the following ways:
- Cloud-to-device updates
- Device-to-cloud updates
- Querying reported properties
Controlling the heating, ventilation, and air conditioning unit (HVAC) using Azure IoT Hub device twins
From Azure IoT Explorer you can set the desired temperature twin. The device actions and acknowledges the request. Azure IoT Hub updates the device twin reported property and IoT Explorer then queries and display this reported property.
The following steps outline how Azure IoT Explorer uses device twins to set properties on a device:
- You can set the desired room temperature from Azure IoT Explorer.
- Azure IoT Hub updates the device twin desired property and sends a device twin message to the device.
- The corresponding device twin handler function is called.
- The device implements the desired property; in this case, turn on the heater or cooler to bring the room to the desired temperature.
- The device acknowledges the updated configuration to Azure IoT Hub. Azure IoT Hub updates the device twin reported property.
- IoT Explorer queries and displays the device twin reported property data.
A device twin binding maps a device twin property name with a handler function that will be called to implement the action.
The following example declares a Device Twin Binding to set the desired room temperature. This declaration maps the Azure IoT Hub DesiredTemperature
device twin with a handler function named DeviceTwinSetTemperatureHandler
.
// Forward declaration of Device Twin handler
static DX_DECLARE_DEVICE_TWIN_HANDLER(DeviceTwinSetTemperatureHandler);
static DX_DEVICE_TWIN_BINDING dt_desiredTemperature = {
.propertyName = "DesiredTemperature",
.twinType = DX_DEVICE_TWIN_FLOAT,
.handler = DeviceTwinSetTemperatureHandler,
.context = "DesiredTemperature Object"};
The following is the implementation of the handler function DeviceTwinSetTemperatureHandler
. The handler function is called when the device receives a DesiredTemperature
desired property message from Azure IoT Hub.
As part of the IoT Plug and Play conventions, the device should acknowledge the device twin update with a call to dx_deviceTwinAckDesiredState.
/// <summary>
/// Device Twin Handler to set the desired temperature value
/// </summary>
static DX_DEVICE_TWIN_HANDLER(DeviceTwinSetTemperatureHandler, deviceTwinBinding)
{
// validate data is sensible range before applying
char* context = (char*)deviceTwinBinding->context;
Log_Debug("%s\n", context);
if (deviceTwinBinding->twinType == DX_DEVICE_TWIN_FLOAT && *(float*)deviceTwinBinding->propertyValue >= -20.0f && *(float*)deviceTwinBinding->propertyValue <= 80.0f)
{
dx_deviceTwinAckDesiredValue(deviceTwinBinding, deviceTwinBinding->propertyValue,
DX_DEVICE_TWIN_RESPONSE_COMPLETED);
// SetHvacStatusColour((int)previous_temperature);
}
else {
dx_deviceTwinAckDesiredValue(deviceTwinBinding, deviceTwinBinding->propertyValue, DX_DEVICE_TWIN_RESPONSE_ERROR);
}
}
DX_DEVICE_TWIN_HANDLER_END
static char display_panel_message[64];
// Forward declaration of Device Twin handler
static DX_DECLARE_DEVICE_TWIN_HANDLER(dt_set_panel_message_handler);
static DX_DEVICE_TWIN_BINDING dt_hvac_panel_message = {
.propertyName = "HvacPanelMessage",
.twinType = DX_DEVICE_TWIN_STRING,
.handler = dt_set_panel_message_handler
};
A reference to the device twin string is only available for the lifetime of the callback.
// This device twin callback demonstrates how to manage device twins of type string.
// A reference to the device twin string is only available for the lifetime of the callback.
// You must copy to a global char array to preserve the string outside of the callback.
// As strings are arbitrary length on a constrained device this gives you, the developer, control of memory allocation.
static DX_DEVICE_TWIN_HANDLER(dt_set_panel_message_handler, deviceTwinBinding)
{
char *panel_message = (char *)deviceTwinBinding->propertyValue;
// Is the message size less than the destination buffer size and printable characters
if (strlen(panel_message) < sizeof(display_panel_message) && dx_isStringPrintable(panel_message))
{
strncpy(display_panel_message, panel_message, sizeof(display_panel_message));
dx_Log_Debug("Virtual HVAC Display Panel Message: %s\n", display_panel_message);
// IoT Plug and Play acknowledge completed
dx_deviceTwinAckDesiredValue(deviceTwinBinding, deviceTwinBinding->propertyValue, DX_DEVICE_TWIN_RESPONSE_COMPLETED);
}
else
{
dx_Log_Debug("Local copy failed. String too long or invalid data\n");
// IoT Plug and Play acknowledge error
dx_deviceTwinAckDesiredValue(deviceTwinBinding, deviceTwinBinding->propertyValue, DX_DEVICE_TWIN_RESPONSE_ERROR);
}
}
DX_DEVICE_TWIN_HANDLER_END
The HVAC operating mode depends on the room temperature, it can be heating, or cooling, or turned off. We can use a device-to-cloud device twin update to report the current operating mode of the HVAC unit.
- The Azure Sphere detects the HVAC operating mode has changed.
- The Azure Sphere sends a device twin message to report the new operating mode of the HVAC to Azure IoT Hub.
- IoT Explorer queries and displays the updated operating mode of the HVAC unit.
The following example declares a ReportedHvacState device twin property of type string. A handler function is not required as this is a one-way device-to-cloud binding.
static DX_DEVICE_TWIN_BINDING dt_reportedHvacState = {
.propertyName = "ReportedHvacState",
.twinType = DX_DEVICE_TWIN_STRING };
The device updates the ReportedHvacState property by calling the dx_deviceTwinReportState function. You must pass a property of the correct type.
dx_deviceTwinReportValue(&dt_reportedHvacState, (void*)hvacState[(int)current_led]);
All declared device twin bindings must be added by reference to the deviceTwinBindingSet array. When a device twin message is received by the device, it is checked for a matching twinProperty name in the deviceTwinBindingSet array. When a match is found, the corresponding handler function is called.
DX_DEVICE_TWIN_BINDING* deviceTwinBindingSet[] = { &dt_desiredTemperature, &dt_reportedTemperature, &dt_reportedHvacState };
The device twin binding set is initialized in the InitPeripheralsAndHandlers function in main.c.
dx_deviceTwinSubscribe(device_twin_bindings, NELEMS(device_twin_bindings));
The device twin bindings set is closed in the ClosePeripheralsAndHandlers function in main.c.
dx_deviceTwinUnsubscribe();
AzureSphereDevX Examples Wiki
- Home
- Build Tools
- Adding the DevX library
- Azure IoT Hub Messaging
- Azure IoT Hub Device Twins
- Azure IoT Hub Direct Methods
- Avnet IoT Connect messaging
- Handling multithreaded async events
- Working with GPIO
- Working with UARTS
- Working with PWM
- Working with Event Timers
- Intercore Messaging
- Application termination
- Deferring updates
- Utility functions
- Tools and scripts
- Hardware Definitions