Use the demo file ./demos/subdev_basic_demo.c in the C Link SDK to call Link SDK APIs and connect a sub-device to IoT Platform through a gateway.
Background information
-
For more information about gateways and sub-devices, see Overview.
-
The gateway for the sub-device must maintain a persistent connection with IoT Platform. The connection method is the same as that for a directly connected device. For more information, see MQTT connection overview.
In this example, the identity authentication information for the gateway device is as follows:
ProductKey
DeviceName
DeviceSecret
a18wP******
LightSwitchGW
uwMTmVAMnGGHaAkqmeDY6cHxxB******
Step 1: Initialization
-
Add the header file.
…… …… #include "aiot_subdev_api.h" Configure underlying dependencies and log output.
aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); aiot_state_set_logcb(demo_state_logcb);-
Call aiot_subdev_init to create a
subdevclient 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 features
Call aiot_subdev_setopt to configure the following features.
-
Associate the handle of the MQTT connection.
ImportantBefore you configure gateway and sub-device feature parameters, make sure that you have configured the identity authentication information for the gateway. For more information, see Configure connection parameters for MQTT.
-
Sample code:
aiot_subdev_setopt(subdev_handle, AIOT_SUBDEVOPT_MQTT_HANDLE, mqtt_handle); -
Parameters:
Configuration item
Example
Description
AIOT_SUBDEVOPT_MQTT_HANDLE
mqtt_handle
Gateway and sub-device features rely on the MQTT connection. Use this configuration item to associate the MQTT connection handle.
-
-
Configure message callbacks for gateway and sub-device features.
-
Configure the message callback function.
-
Sample code:
aiot_subdev_setopt(subdev_handle, AIOT_SUBDEVOPT_RECV_HANDLER, demo_subdev_recv_handler); -
Parameters:
Configuration item
Example value
Description
AIOT_SUBDEVOPT_RECV_HANDLER
demo_subdev_recv_handler
When the device receives gateway or sub-device messages from IoT Platform, this callback function is triggered to process them accordingly.
-
-
Define the message callback function.
For information about the Alink data format for messages, see Manage topology relationships and Sub-device online and offline status.
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 topology relationship
-
Obtain the authentication information of the sub-device.
Create a product and a device for the sub-device. When you create the product, set the node type to Gateway Sub-device. For example, create a sub-device product and add four sub-devices.
Product Name
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_subdevvariable for the authentication information of the sub-device.The sample code presets authentication information for four sub-devices. In a production environment, write your own code to retrieve the sub-device authentication information. Examples:
- Define a protocol between the gateway and the sub-device that allows the gateway to discover the sub-device and obtain its device certificate. The gateway and sub-device manufacturers define this protocol.
- Alternatively, the gateway manufacturer can provide a method to preconfigure the sub-device's certificate information on 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 aiot_subdev_send_topo_add to send a request to IoT Platform to add a topology relationship between the sub-device and the gateway device.
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 the gateway device no longer acts as an agent for the sub-device to receive messages from IoT Platform, call aiot_subdev_send_topo_delete to delete the topology relationship between the sub-device and the gateway device.
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: Log on to the sub-device
-
Call aiot_subdev_send_batch_login to send a request to IoT Platform to log on to the sub-devices in a batch. After the sub-devices log on using the established topology relationship, their status 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: To take a sub-device offline, call aiot_subdev_send_batch_logout to send a request to IoT Platform. After IoT Platform receives the request, the sub-device is taken offline and its status changes to Offline.
ImportantWhen this API is called, IoT Platform updates the sub-device status to offline, which prevents the gateway from receiving messages intended for 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; }
After a sub-device logs on or off, IoT Platform handles messages based on the sub-device status:
-
If the sub-device is offline,
QoS=0messages from IoT Platform to the sub-device are immediately discarded. -
If the sub-device is online, IoT Platform sends messages for the sub-device to the corresponding gateway, which then forwards them to the sub-device.
Step 5: Subscribe to a topic for the sub-device
After a sub-device connects to IoT Platform through a gateway, call aiot_mqtt_sub to subscribe to the sub-device topic and receive messages from it.
When you subscribe to a topic, distinguish between the ProductKey and DeviceName of the sub-device and the gateway. Make sure that you subscribe to the correct device topic.
-
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
A topic to which you have subscribe permissions. In this topic:
-
a13FN******is the ProductKey of the sub-device. -
LightSwitch_SubDev_01is the DeviceName of the sub-device.
This example uses a default custom topic for the sub-device to receive messages from IoT Platform.
For more information about topics, see What is a topic?.
-
Step 6: Publish a message from the sub-device
Call aiot_mqtt_pub to publish a message to a specified sub-device 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
A topic to which you have publish permissions. In this topic:
-
a13FN******is the ProductKey of the sub-device. -
LightSwitch_SubDev_01is the DeviceName of the sub-device.
This example uses a default custom topic for the sub-device. The device uses this topic to publish messages to IoT Platform.
For more information about topics, see What is a topic?.
pub_payload
{\"id\":\"1\",\"version\":\"1.0\",\"params\":{\"LightSwitch\":0}}
The content of the message reported to IoT Platform.
Because the topic category for the sample message is custom, the data format can also be custom.
For more information about data formats, see Data formats.
-
Step 7: Disconnect the gateway
MQTT is typically used for devices that require a persistent connection. Therefore, the program usually does not reach this point.
In the sample program, the main thread is responsible for configuring parameters and establishing a connection. After the connection is established, the main thread can enter hibernation.
You can call aiot_mqtt_disconnect to send a disconnection message to IoT Platform and disconnect from the network.
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 to destroy the subdev client instance and release associated 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 file, compile it to generate the executable file ./output/subdev-basic-demo.
For more information, see Compile and run.
-
For more information about the results, see Operational logs.