This article describes how to call the API operations of Link SDK for C to connect sub-devices to IoT Platform by using gateways. In this example./demos/fota_posix_demo.c sample code file is used.
Step 1: Initialize a client
- Add header files.
...
...
#include "aiot_subdev_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_subdev_init operation to create a
subdev
client instance and initialize the default parameters. subdev_handle = aiot_subdev_init();
if (subdev_handle == NULL) {
printf("aiot_subdev_init failed\n");
demo_mqtt_stop(&mqtt_handle);
return -1;
}
Step 2: Configure required features
Call the aiot_subdev_setopt operation to configure the following items:
- Associate with MQTT connection handles.
- Configure message callbacks.
- Associate with an MQTT connection handle.
Notice Before you set parameters that are related to the gateway and sub-device, make sure
that the authentication information of the gateway is configured. For more information,
see
Example.
- Configure the message callbacks.
- Specify the message callbacks.
- Define the message callbacks.
For more information about the Alink data format of messages, see
Manage topological relationships and
Connect or disconnect sub-devices.
void demo_subdev_recv_handler(void *handle, const aiot_subdev_recv_t *packet, void *user_data)
{
switch (packet->type) {
case AIOT_SUBDEVRECV_TOPO_ADD_REPLY:
case AIOT_SUBDEVRECV_TOPO_DELETE_REPLY:
case AIOT_SUBDEVRECV_TOPO_GET_REPLY:
case AIOT_SUBDEVRECV_BATCH_LOGIN_REPLY:
case AIOT_SUBDEVRECV_BATCH_LOGOUT_REPLY:
case AIOT_SUBDEVRECV_SUB_REGISTER_REPLY:
case AIOT_SUBDEVRECV_PRODUCT_REGISTER_REPLY: {
printf("msgid : %d\n", packet->data.generic_reply.msg_id);
printf("code : %d\n", packet->data.generic_reply.code);
printf("product key : %s\n", packet->data.generic_reply.product_key);
printf("device name : %s\n", packet->data.generic_reply.device_name);
printf("message : %s\n", (packet->data.generic_reply.message == NULL)?("NULL"):(packet->data.generic_reply.message));
printf("data : %s\n", packet->data.generic_reply.data);
}
break;
case AIOT_SUBDEVRECV_TOPO_CHANGE_NOTIFY: {
printf("msgid : %d\n", packet->data.generic_notify.msg_id);
printf("product key : %s\n", packet->data.generic_notify.product_key);
printf("device name : %s\n", packet->data.generic_notify.device_name);
printf("params : %s\n", packet->data.generic_notify.params);
}
break;
default: {
}
}
}
Step 3: Add a topological relationship
- Obtain the authentication information of the sub-device.
Create a product and device for the sub-device. When you create the product, set the
node type to Gateway sub-device. In this example, the following product and sub-devices are created.
ProductName |
ProductKey |
DeviceName |
DeviceSecret |
ProductSecret |
LightSwitchSD |
a13FN****** |
LightSwitch_SubDev_01 |
768XBgQwgOakz3K4uhOiLeeh9x****** |
y7GSILD480****** |
LightSwitch_SubDev_02 |
iwTZrbjbgNVChfuJkihjE5asek****** |
LightSwitch_SubDev_03 |
fdutq35iKMYdcWWBuIINY26hsN****** |
LightSwitch_SubDev_04 |
HCKv50YqgwdKhy5cE0Vz4aydmK****** |
For more information, see Create a product and Create a device.
- Define the
g_subdev
variable that indicates the authentication information of the sub-device.
In this example, the authentication information of four sub-devices is provided. In
actual business scenarios, you must write code and define the method to obtain the
authentication information of sub-devices. Sample code:
- After a gateway discovers a connected sub-device, the gateway can obtain the certificate
of the sub-device based on a protocol that is defined between the gateway and the
sub-device. The protocol is defined by the provider of the gateway and the provider
of the sub-device.
- The provider of the gateway provides a configuration method that allows the gateway
to preset certificate information about the sub-device. This feature is implemented
by the provider of the gateway.
aiot_subdev_dev_t g_subdev[] = {
{
"a13FN******",
"LightSwitch_SubDev_01",
"768XBgQwgOakz3K4uhOiLeeh9x******",
"y7GSILD480******"
},
{
"a13FN******",
"LightSwitch_SubDev_02",
"iwTZrbjbgNVChfuJkihjE5asek******",
"y7GSILD480******"
},
{
"a13FN******",
"LightSwitch_SubDev_03",
"fdutq35iKMYdcWWBuIINY26hsN******",
"y7GSILD480******"
},
{
"a13FN******",
"LightSwitch_SubDev_04",
"HCKv50YqgwdKhy5cE0Vz4aydmK******",
"y7GSILD480******"
}
};
- Call the aiot_subdev_send_topo_add operation to add a topological relationship between the sub-device and the gateway.
The request is sent IoT Platform.
res = aiot_subdev_send_topo_add(subdev_handle, g_subdev, sizeof(g_subdev)/sizeof(aiot_subdev_dev_t));
if (res < STATE_SUCCESS) {
printf("aiot_subdev_send_topo_add failed, res: -0x%04X\n", -res);
aiot_subdev_deinit(&subdev_handle);
demo_mqtt_stop(&mqtt_handle);
return -1;
}
- Optional:If you do not need the gateway to receive messages from IoT Platform as a proxy, call
the aiot_subdev_send_topo_delete operation to delete the topological relationship between the sub-device and the gateway.
aiot_subdev_send_topo_delete(subdev_handle, g_subdev, sizeof(g_subdev)/sizeof(aiot_subdev_dev_t));
if (res < STATE_SUCCESS) {
printf("aiot_subdev_send_topo_delete failed, res: -0x%04X\n", -res);
aiot_subdev_deinit(&subdev_handle);
demo_mqtt_stop(&mqtt_handle);
return -1;
}
Step 4: Connect the sub-device to IoT Platform
- Call the aiot_subdev_send_batch_login operation to connect one or more sub-devices with IoT Platform. After a sub-device
is connected to IoT Platform, the status of the sub-device changes to Online.
aiot_subdev_send_batch_login(subdev_handle, g_subdev, sizeof(g_subdev)/sizeof(aiot_subdev_dev_t));
if (res < STATE_SUCCESS) {
printf("aiot_subdev_send_batch_login failed, res: -0x%04X\n", -res);
aiot_subdev_deinit(&subdev_handle);
demo_mqtt_stop(&mqtt_handle);
return -1;
}
- Optional:If you need to disconnect the sub-device, call the aiot_subdev_send_batch_logout operation to send a disconnection request. After IoT Platform receives the request,
IoT Platform ends the connection. Then, the status of the sub-device changes to Offline.
Notice IoT Platform updates the status of the sub-device to be Offline. In this case, the
gateway no longer receives messages that IoT Platform sends to the sub-device.
aiot_subdev_send_batch_logout(subdev_handle, g_subdev, sizeof(g_subdev)/sizeof(aiot_subdev_dev_t));
if (res < STATE_SUCCESS) {
printf("aiot_subdev_send_batch_logout failed, res: -0x%04X\n", -res);
aiot_subdev_deinit(&subdev_handle);
demo_mqtt_stop(&mqtt_handle);
return -1;
}
The messages that IoT Platform sends to the sub-device are processed based on the
online status of the sub-device.
- If the sub-device is offline,
QoS 0
messages are discarded.
- If the sub-device is online, IoT Platform sends messages to the gateway. Then, the
gateway forwards the messages to the sub-device.
Step 5: Subscribe to topics
After a sub-device is connected to IoT Platform, you can call the aiot_mqtt_sub operation to subscribe to topics. Then, the sub-device can receive messages by using
the topics.
Notice When specify topics, differentiate the ProductKey and DeviceName of the sub-device and the gateway.
- Sample code
{
char *sub_topic = "/a13FN******/LightSwitch_SubDev_01/user/get";
res = aiot_mqtt_sub(mqtt_handle, sub_topic, NULL, 1, NULL);
if (res < 0) {
printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res);
return -1;
}
}
- Parameters:
Parameter |
Example |
Description |
sub_topic |
/a13FN******/LightSwitch_SubDev_01/user/get |
The topic that has the Subscribe permission.
a1oGs****** indicates the ProductKey of the sub-device.
LightSwitch_SubDev_01 indicates the DeviceName of the sub-device.
In this example, the default custom topic is specified. The device can receive messages from IoT Platform by using this topic.
For more information about topics, see What is a topic?.
|
Step 6: Publish messages from the sub-device
Call the aiot_mqtt_pub operation to send a message to a specified topic.
- Sample code
{
char *pub_topic = "/a13FN******/LightSwitch_SubDev_01/user/update";
char *pub_payload = "{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}";
res = aiot_mqtt_pub(mqtt_handle, pub_topic, (uint8_t *)pub_payload, (uint32_t)strlen(pub_payload), 0);
if (res < 0) {
printf("aiot_mqtt_sub failed, res: -0x%04X\n", -res);
return -1;
}
}
- Parameters:
Parameter |
Example |
Description |
pub_topic |
/a13FN******/LightSwitch_SubDev_01/user/update |
The topic that has the Publish permission.
a1oGs****** indicates the ProductKey of the sub-device.
LightSwitch_SubDev_01 indicates the DeviceName of the sub-device.
In this example, the default custom topic is specified. The device can send messages to IoT Platform by using this topic.For more information about topics, see What is a topic?.
|
pub_payload |
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}} |
The message that is sent to IoT Platform.
In this example, a custom topic is used. Therefore, you can customize the message
format.
For more information about message formats, see Data formats.
|
Step 7: Disconnect the gateway
Note
MQTT connections are applied to devices that remain persistently connected. You can
manually disconnect devices from IoT Platform.
In this example, the main thread is used to set parameters and establish a connection.
After the connection is established, you can put the main thread to sleep.
Call the aiot_mqtt_disconnect operation to disconnect the device from IoT Platform.
res = aiot_mqtt_disconnect(mqtt_handle);
if (res < STATE_SUCCESS) {
aiot_mqtt_deinit(&mqtt_handle);
printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
return -1;
}
Step 8: Exit the program
Call aiot_subdev_deinit operation to destroy the subdev
client instance and release resources.
res = aiot_subdev_deinit(&subdev_handle);
if (res < STATE_SUCCESS) {
printf("aiot_subdev_deinit failed: -0x%04X\n", res);
}
What to do next
After you configure the sample code file, compile the file to generate an executable
file In this example, the ./output/subdev-basic-demo executable file is generated. For more information, see Compilation and running