Sub-device management

更新时间:
复制 MD 格式

Program a gateway product by using the src/dev_model/examples/linkkit_example_gateway.c example.

Terminology

Term

Description

Gateway

A device that connects directly to IoT Platform. It has sub-device management features and can act as a proxy for sub-devices to connect to the cloud.

Sub-device

A device that cannot connect directly to IoT Platform. It can only connect through a gateway.

Device ID

A device handle that identifies a specific device in a gateway scenario. It is returned when you call IOT_Linkkit_Open.

Topology

The association between a sub-device and a gateway. Once established, the sub-device reuses the gateway's physical channel for data communication.

Dynamic sub-device registration

The sub-device reports its ProductKey and DeviceName to the gateway, which authenticates with the cloud on the sub-device's behalf. The cloud returns a deviceSecret used to bring the sub-device online.

Manage sub-devices

  1. Establish a connection between the gateway and the cloud.

    The connection procedure for a gateway is the same as for a standalone device.

    1. Call IOT_RegisterCallback to register callback functions for connection events, initialization completion, and property settings. The gateway and sub-devices share one set of callbacks, distinguished by the DeviceID parameter.

          IOT_RegisterCallback(ITE_CONNECT_SUCC, user_connected_event_handler);
          IOT_RegisterCallback(ITE_DISCONNECTED, user_disconnected_event_handler);
          IOT_RegisterCallback(ITE_PROPERTY_SET, user_property_set_event_handler);
          IOT_RegisterCallback(ITE_REPORT_REPLY, user_report_reply_event_handler);
          IOT_RegisterCallback(ITE_TIMESTAMP_REPLY, user_timestamp_reply_event_handler);
          IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
          IOT_RegisterCallback(ITE_PERMIT_JOIN, user_permit_join_event_handler);
                                      
    2. Call IOT_Ioctl to configure the server region and whether to use per-device certificates.

          /* Choose Login Server */
          int domain_type = IOTX_CLOUD_REGION_SHANGHAI;
          IOT_Ioctl(IOTX_IOCTL_SET_DOMAIN, (void *)&domain_type);
      
          /* Choose Login Method */
          int dynamic_register = 0;
          IOT_Ioctl(IOTX_IOCTL_SET_DYNAMIC_REGISTER, (void *)&dynamic_register);
                                      
    3. Call IOT_Linkkit_Open with the IOTX_LINKKIT_DEV_TYPE_MASTER parameter to initialize the master device resources.

          iotx_linkkit_dev_meta_info_t master_meta_info;
      
          memset(&master_meta_info, 0, sizeof(iotx_linkkit_dev_meta_info_t));
          memcpy(master_meta_info.product_key, PRODUCT_KEY, strlen(PRODUCT_KEY));
          memcpy(master_meta_info.product_secret, PRODUCT_SECRET, strlen(PRODUCT_SECRET));
          memcpy(master_meta_info.device_name, DEVICE_NAME, strlen(DEVICE_NAME));
          memcpy(master_meta_info.device_secret, DEVICE_SECRET, strlen(DEVICE_SECRET));
      
          /* Create Master Device Resources */
          user_example_ctx->master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, &master_meta_info);
          if (user_example_ctx->master_devid < 0) {
              EXAMPLE_TRACE("IOT_Linkkit_Open Failed\n");
              return -1;
          }
                                      
    4. Call IOT_Linkkit_Connect with the IOTX_LINKKIT_DEV_TYPE_MASTER parameter to establish a connection to the cloud.

          /* Start Connect Aliyun Server */
          res = IOT_Linkkit_Connect(user_example_ctx->master_devid);
          if (res < 0) {
              EXAMPLE_TRACE("IOT_Linkkit_Connect Failed\n");
              return -1;
          }
                                      
    5. In the event handler for ITE_INITIALIZE_COMPLETED, confirm that the gateway connection is initialized. You can then proceed to add sub-devices.

    Note

    Do not perform operations that block threads in the callback functions registered in Step 1. Examples include calling IOT_Linkkit_Connect to connect a sub-device or calling IOT_Linkkit_Report to bring a sub-device online or take it offline.

  2. Add a sub-device.

    This process involves four steps.

    1. Call IOT_Linkkit_Open with the IOTX_LINKKIT_DEV_TYPE_SLAVE parameter to initialize the sub-device resources.

      Note

      For dynamic registration, set device_secret to an empty string and register the sub-device's DeviceName in the IoT Platform console.

    2. Call IOT_Linkkit_Connect to connect the sub-device to the cloud. This synchronous call automatically registers the sub-device and adds the topology.

    3. Call IOT_Linkkit_Report with the ITM_MSG_LOGIN parameter to bring the sub-device online.

    4. In the event handler for ITE_INITIALIZE_COMPLETED, confirm that the sub-device connection is initialized. The sub-device can then exchange data with the cloud.

      int example_add_subdev(iotx_linkkit_dev_meta_info_t *meta_info)
      {
          int res = 0, devid = -1;
          devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_SLAVE, meta_info);
          if (devid == FAIL_RETURN) {
              EXAMPLE_TRACE("subdev open Failed\n");
              return FAIL_RETURN;
          }
          EXAMPLE_TRACE("subdev open succeeded, devid = %d\n", devid);
      
          res = IOT_Linkkit_Connect(devid);
          if (res == FAIL_RETURN) {
              EXAMPLE_TRACE("subdev connect Failed\n");
              return res;
          }
          EXAMPLE_TRACE("subdev connect success: devid = %d\n", devid);
      
          res = IOT_Linkkit_Report(devid, ITM_MSG_LOGIN, NULL, 0);
          if (res == FAIL_RETURN) {
              EXAMPLE_TRACE("subdev login Failed\n");
              return res;
          }
          EXAMPLE_TRACE("subdev login success: devid = %d\n", devid);
          return res;
      }
                                      
    Important

    Calling IOT_Linkkit_Open multiple times with the same ProductKey and DeviceName returns the same devid because the SDK does not create duplicate resources. You can use this behavior to query the devid of an existing sub-device by calling IOT_Linkkit_Open with the corresponding ProductKey and DeviceName.

  3. Perform sub-device management operations.

    1. Log out a sub-device.

      Call IOT_Linkkit_Report with ITM_MSG_LOGOUT to log out the sub-device and notify IoT Platform that it is offline.

          res = IOT_Linkkit_Report(devid, ITM_MSG_LOGOUT, NULL, 0);
          if (res == FAIL_RETURN) {
              EXAMPLE_TRACE("subdev logout Failed\n");
              return res;
          }
          EXAMPLE_TRACE("subdev logout success: devid = %d\n", devid);
                                      
    2. Retrieve the sub-device list.

      Call IOT_Linkkit_Query with ITM_MSG_QUERY_TOPOLIST to retrieve all sub-devices in the topology. Results are returned in the ITE_TOPOLIST_REPLY callback.

    3. Delete a sub-device topology.

      Call IOT_Linkkit_Report with ITM_MSG_DELETE_TOPO to delete the topology for the sub-device specified by devid. The cloud then disassociates the sub-device from this gateway.

    4. Perform a sub-device Over-the-Air (OTA) update.

      Use IOT_Ioctl to configure OTA for the sub-device, then use IOT_Linkkit_Query to trigger the upgrade.

      • Call IOT_RegisterCallback to register the user_fota_event_handler callback function for the firmware upgrade.

        IOT_RegisterCallback(ITE_FOTA, user_fota_event_handler);
        IOT_RegisterCallback(ITE_INITIALIZE_COMPLETED, user_initialized);
                                                
      • Call IOT_Linkkit_Open with the IOTX_LINKKIT_DEV_TYPE_MASTER parameter to initialize the master device resources.

        iotx_linkkit_dev_meta_info_t master_meta_info;
        
        memset(&master_meta_info, 0, sizeof(iotx_linkkit_dev_meta_info_t));
        memcpy(master_meta_info.product_key, PRODUCT_KEY, strlen(PRODUCT_KEY));
        memcpy(master_meta_info.product_secret, PRODUCT_SECRET, strlen(PRODUCT_SECRET));
        memcpy(master_meta_info.device_name, DEVICE_NAME, strlen(DEVICE_NAME));
        memcpy(master_meta_info.device_secret, DEVICE_SECRET, strlen(DEVICE_SECRET));
        
        /* Create Master Device Resources */
        user_example_ctx->master_devid = IOT_Linkkit_Open(IOTX_LINKKIT_DEV_TYPE_MASTER, &master_meta_info); 
        if (user_example_ctx->master_devid < 0) {
            EXAMPLE_TRACE("IOT_Linkkit_Open Failed\n");
            return -1;
        }
                                                
      • Call IOT_Linkkit_Connect to establish a connection to the cloud.

        /* Start Connect Aliyun Server */
        res = IOT_Linkkit_Connect(user_example_ctx->master_devid);
        if (res < 0) {
            EXAMPLE_TRACE("IOT_Linkkit_Connect Failed\n");
            return -1;
        }
                                                
      • Add a sub-device and perform an OTA update.

        /* Add subdev */
        while (user_example_ctx->subdev_index < EXAMPLE_SUBDEV_ADD_NUM) {
            if (user_example_ctx->master_initialized && user_example_ctx->subdev_index >= 0 &&
                (0 == current_ota_running) && (user_example_ctx->auto_add_subdev == 1 || user_example_ctx->permit_join != 0)) {
                /* Add next subdev */
                if (example_add_subdev((iotx_linkkit_dev_meta_info_t *)&subdevArr[user_example_ctx->subdev_index]) == SUCCESS_RETURN) {
                    EXAMPLE_TRACE("subdev %s add succeed", subdevArr[user_example_ctx->subdev_index].device_name);
                } else {
                    EXAMPLE_TRACE("subdev %s add failed", subdevArr[user_example_ctx->subdev_index].device_name);
                }
                user_example_ctx->subdev_index++;
                user_example_ctx->permit_join = 0;
                /* check each sub dev has remote ota message */
                do_subdev_ota(user_example_ctx->subdev_index);
                /* wait remote ota message */
                HAL_SleepMs(10000);
            }
        }
                                                
      • Details of the do_subdev_ota function.

        Use IOT_Ioctl to switch the OTA channel to a specific sub-device (identified by devid). After switching, only upgrade messages for that sub-device are received. Call IOT_Linkkit_Query to query the cloud for available firmware. If a suitable version is available, the OTA process starts and triggers the user_fota_event_handler callback.

        void do_subdev_ota(int devid)
        {
            if (status_list[devid] == SUB_OTA_SUCCESS) {
                HAL_Printf("current devid is %d, its has checked remote ota message, skip\n", devid);
                return;
            }
        
            if (current_ota_running == 1) {
                return;
            }
        
            HAL_Printf("current devid running ota is %d\n", devid);
            int ota_result = 0;
            ota_result = IOT_Ioctl(IOTX_IOCTL_SET_OTA_DEV_ID, (void *)(&devid));
            if (0 != ota_result) {
                status_list[devid] = SUB_OTA_FAILED_SET_DEV_ID;
                HAL_Printf("IOTX_IOCTL_SET_OTA_DEV_ID failed, id is %d\n", devid);
                return;
            }
            ota_result = IOT_Linkkit_Query(devid, ITM_MSG_REQUEST_FOTA_IMAGE, (unsigned char *)current_subdev_version,
                                           strlen(current_subdev_version));
            HAL_Printf("current devid is %d, ITM_MSG_REQUEST_FOTA_IMAGE ret is %d\n", devid, ota_result);
            if (0 != ota_result) {
                status_list[devid] = SUB_OTA_FAILED_QUERY;
                return;
            }
            status_list[devid] = SUB_OTA_SUCCESS;
        } 
                                                    
  4. Exchange data with the sub-device.

    Data exchange between a sub-device and the cloud follows the same procedure as a standalone product. Refer to the Thing Specification Language (TSL) model programming documentation.

    • Call IOT_Linkkit_Report to report properties, report pass-through data, and update or delete device tags.

    • Call IOT_Linkkit_TriggerEvent to proactively report an event.

    • In the ITE_RAWDATA_ARRIVED event callback, receive pass-through data from the cloud.

    • In the ITE_SERVICE_REQUEST event callback, receive service requests for synchronous and asynchronous services.

    • In the ITE_PROPERTY_SET event callback, process property settings from the cloud.

    • In the ITE_PROPERTY_GET event callback, process requests to retrieve properties from local communication.

Usage notes

  1. The gateway must be multi-threaded. Run IOT_Linkkit_Yield in a dedicated thread.

     void *user_dispatch_yield(void *args) 
     {
         while (1){
             IOT_Linkkit_Yield(USER_EXAMPLE_YIELD_TIMEOUT_MS);
         }
    
         return NULL;
     }
    
     res = HAL_ThreadCreate(&g_user_dispatch_thread, user_dispatch_yield, NULL, NULL, NULL);
     if (res < 0) {
         EXAMPLE_TRACE("HAL_ThreadCreate Failed\n");
         IOT_Linkkit_Close(user_example_ctx->master_devid);
         return -1;
     }
  2. On the Smart Life Open Platform, add a sub-device only after receiving the ITE_PERMIT_JOIN event from the cloud.

    When a user scans a QR code in the app to add a sub-device, the app sends a PermitJoin command to the cloud, which forwards it to the gateway. The ITE_PERMIT_JOIN event provides the sub-device's ProductKey and a time window (timeoutSec, typically 60 seconds). Within this window, discover and attach the sub-device, then add it and report to the cloud. The sub-device then appears in the app. Example handler: int user_permit_join_event_handler(const char *product_key, const int time){ user_example_ctx_t *user_example_ctx = user_example_get_ctx();.

    EXAMPLE_TRACE(“Product Key: %s, Time: %d”, product_key, time);
    user_example_ctx->permit_join = 1;
    return 0;
    }
    ```
  3. Add FEATURE_DEVICE_MODEL_GATEWAY=y to the make.setting file in the SDK root directory, then run make to compile the gateway example.