This article describes how to call the API operations of Link SDK for C to configure device shadows. In this example, the ./demos/shadow_basic_demo.c sample code file is used.
Step 1: Initialize a client
- Add header files.
...
...
#include "aiot_shadow_api.h"
- Add the underlying dependency and configure the log output feature.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
aiot_state_set_logcb(demo_state_logcb);
- Call the aiot_shadow_init operation to create a
shadow
client instance and initialize the default parameters. shadow_handle = aiot_shadow_init();
if (shadow_handle == NULL) {
printf("aiot_shadow_init failed\n");
return -1;
}
Step 2: Configure required features
Call the aiot_shadow_setopt operation to configure the following items.
- Associate with an MQTT connection handle.
Notice Before you set device shadow-specific parameters,
- Configure a message callback
Step 3: Submit the device status
If the device is online, the device can submit the status to its shadow. Applications
obtain the status from the shadow.
- The device calls the aiot_shadow_send operation to submit the latest status to the device shadow in IoT Platform.
When you submit the status, take note of the following items:
- aiot_shadow_msg_t indicates the data format. This parameter is an input parameter of the
aiot_shadow_send()
callback.
- AIOT_SHADOWMSG_UPDATE indicates the message type.
int32_t demo_update_shadow(void *shadow_handle, char *reported_data, int64_t version)
{
aiot_shadow_msg_t message;
memset(&message, 0, sizeof(aiot_shadow_msg_t));
message.type = AIOT_SHADOWMSG_UPDATE;
message.data.update.reported = reported_data;
message.data.update.version = version;
return aiot_shadow_send(shadow_handle, &message);
}
- You specify the message content.
- Sample code
res = demo_update_shadow(shadow_handle, "{\"LightSwitch\":1}", 0);
if (res < 0) {
printf("demo_delete_shadow_report failed, res = -0x%04x\r\n", -res);
}
- Sample message:
Sample message |
Alink format |
Description |
{
"LightSwitch": 1
}
|
{
"method": "update",
"state": {
"reported": {
"LightSwitch": 1
}
},
"version": 0
}
|
The message content is in the JSON format. The content is indicated by the state parameter in the Alink data. For more information, see The device submits the status.
The following items describe the message content in this example:
- Set the
LightSwitch property to 1 .
- Set the version number to
0 .
Note
- The version numbers of subsequent operations must be incremented. Otherwise, IoT Platform
returns an error.
- If you set the version number to
-1 , IoT Platform clears the device shadow data and updates the version number to 0 .
|
- After IoT Platform receives the message, IoT Platform updates the shadow file. Then,
IoT Platform returns a response to the device.
- After the device receives the response, the
demo_shadow_recv_handler
callback is called.
When you specify the processing logic of the callback, take note of the following
items:
- aiot_shadow_recv_t indicates the data format. This parameter is an input parameter of the callback.
- AIOT_SHADOWRECV_GENERIC_REPLY indicates the message type.
- The following table describes a sample response and the Alink format of the response.
Example |
Alink format |
Description |
{
"status":"success",
"version":0
}
|
{
"method": "reply",
"payload": {
"status": "success",
"version": 0
},
"timestamp": 1626317187
}
|
The response is indicated by the payload parameter in the Alink data.
This sample response indicates that the status is submitted.
|
- In this example, the message is printed.
void demo_shadow_recv_handler(void *handle, const aiot_shadow_recv_t *recv, void *userdata)
{
printf("demo_shadow_recv_handler, type = %d, productKey = %s, deviceName = %s\r\n",
recv->type, recv->product_key, recv->device_name);
switch (recv->type) {
case AIOT_SHADOWRECV_GENERIC_REPLY: {
const aiot_shadow_recv_generic_reply_t *generic_reply = &recv->data.generic_reply;
printf("payload = \"%.*s\", status = %s, timestamp = %ld\r\n",
generic_reply->payload_len,
generic_reply->payload,
generic_reply->status,
(unsigned long)generic_reply->timestamp);
}
……
...
default:
break;
}
}
Step 4: Change the device status by using desired properties
To change the device status, you can use an application to send desired properties
to the device shadow. You can also log on to the IoT Platform console and modify desired
properties in the device shadow.
- You update desired properties in the device shadow. The following methods are available:
- Develop a cloud application and call the API operation to send desired properties
to the device shadow. For more information, see UpdateDeviceShadow.
- On the Device Details page of IoT Platform, modify desired properties in the device shadow. For more information,
see View and update a device shadow.
- IoT Platform updates the shadow file and then sends the file to the device.
- After the device receives the shadow file, the
demo_shadow_recv_handler
callback is called.
When you specify the processing logic of the callback, take note of the following
items:
- aiot_shadow_recv_t indicates the data format. This parameter is an input parameter of the callback.
- AIOT_SHADOWRECV_CONTROL indicates the message type.
- The following table describes a sample message and the Alink format of the message.
Example |
Alink format |
Description |
{
"state": {
"desired": {
"LightSwitch": 0
}
},
"metadata": {
"desired": {
"LightSwitch": {
"timestamp": 1626319658
}
}
}
}
|
{
"method": "control",
"payload": {
"state": {
"desired": {
"LightSwitch": 0
}
},
"metadata": {
"desired": {
"LightSwitch": {
"timestamp": 1626319658
}
}
}
},
"version": 2,
"timestamp": 1469564576
}
|
The response is indicated by the payload parameter in the Alink data. In this example, the LightSwitch desired property is set to 0 .
|
- In this example, the message is printed.
void demo_shadow_recv_handler(void *handle, const aiot_shadow_recv_t *recv, void *userdata)
{
printf("demo_shadow_recv_handler, type = %d, productKey = %s, deviceName = %s\r\n",
recv->type, recv->product_key, recv->device_name);
switch (recv->type) {
...
...
case AIOT_SHADOWRECV_CONTROL: {
const aiot_shadow_recv_control_t *control = &recv->data.control;
printf("payload = \"%.*s\", version = %ld\r\n",
control->payload_len,
control->payload,
(unsigned long)control->version);
}
……
...
default:
break;
}
}
- After the device updates the local status, the device submits the latest status to
the device shadow and processes the response.
- The device calls the aiot_shadow_send operation to delete the desired properties.
When you delete desired properties, take note of the following items:
- aiot_shadow_msg_t indicates the data format. This parameter is an input parameter of the
aiot_shadow_send()
callback.
- AIOT_SHADOWMSG_CLEAN_DESIRED indicates the message type.
- In this example, all desired properties are deleted and the version number is set
to
1
.
int32_t demo_clean_shadow_desired(void *shadow_handle, int64_t version)
{
aiot_shadow_msg_t message;
memset(&message, 0, sizeof(aiot_shadow_msg_t));
message.type = AIOT_SHADOWMSG_CLEAN_DESIRED;
message.data.clean_desired.version = version;
return aiot_shadow_send(shadow_handle, &message);
}
……
...
res = demo_clean_shadow_desired(shadow_handle, 1);
if (res < 0) {
printf("demo_clean_shadow_desired failed, res = -0x%04x\r\n", -res);
}
- After IoT platform receives the request to delete desired properties, IoT Platform
returns a response. In this case, the
demo_shadow_recv_handler
callback is called.
Step 5: Request the device shadow
When an application sends a command, the device may be offline. After the device goes
online, the device can request the shadow.
- The device calls the aiot_shadow_send operation to request the device shadow content from IoT Platform.
AIOT_SHADOWMSG_GET indicates the message type. int32_t demo_get_shadow(void *shadow_handle)
{
aiot_shadow_msg_t message;
memset(&message, 0, sizeof(aiot_shadow_msg_t));
message.type = AIOT_SHADOWMSG_GET;
return aiot_shadow_send(shadow_handle, &message);
}
……
...
res = demo_get_shadow(shadow_handle);
if (res < 0) {
printf("demo_get_shadow failed, res = -0x%04x\r\n", -res);
}
- After IoT Platform receives the request, IoT Platform returns a response. After the
device receives the response, the
demo_shadow_recv_handler
callback is called.When you specify the processing logic of the callback, take note of the following
items:
- aiot_shadow_recv_t indicates the data format. This parameter is an input parameter of the callback.
- AIOT_SHADOWRECV_GET_REPLY indicates the message type.
- The following table describes a sample response and the Alink format of the response.
Example |
Alink format |
Description |
{
"status": "success",
"state": {
"reported": {
}
},
"metadata": {
"reported": {
}
}
}
|
{
"method": "reply",
"payload": {
"status": "success",
"state": {
"reported": {
}
},
"metadata": {
"reported": {
}
}
},
"version": 5,
"timestamp": 1626320690
}
|
The response is indicated by the payload parameter in the Alink data. This sample response indicates that the request is successful. The reported parameter
contains no data, which indicates that no properties are submitted.
|
- In this example, the message is printed.
void demo_shadow_recv_handler(void *handle, const aiot_shadow_recv_t *recv, void *userdata)
{
printf("demo_shadow_recv_handler, type = %d, productKey = %s, deviceName = %s\r\n",
recv->type, recv->product_key, recv->device_name);
switch (recv->type) {
...
...
case AIOT_SHADOWRECV_GET_REPLY: {
const aiot_shadow_recv_get_reply_t *get_reply = &recv->data.get_reply;
printf("payload = \"%.*s\", version = %ld\r\n",
get_reply->payload_len,
get_reply->payload,
(unsigned long)get_reply->version);
}
default:
break;
}
}
Step 6: Delete properties in the device shadow
If the device is in the latest status, the device can send a command to delete properties
in the device shadow.
- The device calls the aiot_shadow_send operation to delete specified properties in the device shadow.
When you send a request, take note of the following items:
- aiot_shadow_msg_t indicates the data format. This parameter is an input parameter of the
aiot_shadow_send()
callback.
- AIOT_SHADOWMSG_DELETE_REPORTED indicates the message type.
int32_t demo_delete_shadow_report(void *shadow_handle, char *reported, int64_t version)
{
aiot_shadow_msg_t message;
memset(&message, 0, sizeof(aiot_shadow_msg_t));
message.type = AIOT_SHADOWMSG_DELETE_REPORTED;
message.data.delete_reporte.reported = reported;
message.data.delete_reporte.version = version;
return aiot_shadow_send(shadow_handle, &message);
}
- You specify the properties to be deleted.
- Sample code
res = demo_delete_shadow_report(shadow_handle, "{\"LightSwitch\":\"null\"}", 2);
if (res < 0) {
printf("demo_delete_shadow_report failed, res = -0x%04x\r\n", -res);
}
- Sample message:
Example |
Alink format |
Description |
"{\"LightSwitch\":\"null\"}", 2
|
{
"method": "delete",
"state": {
"reported": {
"LightSwitch": "null",
}
},
"version": 2
}
|
The message content is in the JSON format. The content is indicated by the state parameter in the Alink data. For more information, see The device deletes shadow properties.
The following items describe the message content in this example:
- Set the
LightSwitch property to null . This value indicates that all data in the device shadow is cleared.
- Set the version number to
2 .
|
- After IoT Platform receives the request, IoT Platform returns a response. After the
device receives the response, the
demo_shadow_recv_handler
callback is called.
Step 7: Exit the program
Call the aiot_shadow_deinit operation to destroy the shadow
client instance and release resources.
res = aiot_shadow_deinit(&shadow_handle);
if (res < STATE_SUCCESS) {
printf("aiot_shadow_deinit failed: -0x%04X\n", -res);
return -1;
}
What to do next
-
After you configure the sample code file, compile the file to generate an executable
file In this example, the ./demos/shadow-basic-demo executable file is generated.
For more information, see Compilation and running.
Notice
- When you configure the sample code file, delete the comment symbols (
/*
and */
) on both sides of the code and change version numbers based on actual scenarios.
- When you change version numbers, take note of the following items:
- The version numbers of subsequent operations must be incremented. Otherwise, IoT Platform
returns an error.
- If you set the version number to
-1
, IoT Platform clears the device shadow data and updates the version number to 0
.
-
For more information about running results, see View logs.