本文介绍C SDK通过HTTPS方式进行动态注册的使用方法,目前HTTPS方式的动态注册不支持免白名单功能。
API列表
接口名 | 说明 |
---|---|
aiot_dynreg_init | 初始化dynreg实例并设置默认参数。 |
aiot_dynreg_setopt | 配置dynreg实例, 详见选项配置说明。 |
aiot_dynreg_deinit | 释放dynreg实例句柄的资源。 |
aiot_dynreg_send_request | 向dynreg服务器发送请求。 |
aiot_dynreg_recv | 从dynreg服务器接收应答。 |
特别说明
如果设备通过动态注册拿到了设备的DeviceSecret,但是并没有使用该DeviceSecret去连接阿里云物联网平台,这个时候可以再次通过动态注册去获取DeviceSecret,云端将会返回新的DeviceSecret。
如果一个设备通过动态注册获取到了DeviceSecret,并使用该DeviceSecret将设备连接到了阿里云物联网平台,那么再次调用动态注册接口去获取DeviceSecret将会返回失败。因此设备获取到了DeviceSecret之后需要将其持久化保存到设备上,设备重启、重置也不能丢失DeviceSecret。
当设备上电时如果发现自己已经获取到了DeviceSecret,直接使用ProductKey、DeviceName、DeviceSecret连接物联网平台即可,无需再次调用动态注册去获取DeviceSecret。
例程讲解
现对照demos/dynreg_basic_demo.c
例程, 分步骤讲解如何使用API。

这个例程演示了用SDK配置dynreg会话实例的参数,并发起请求和接收应答,之后:
- 如果接收应答失败了, 销毁实例, 回收资源, 结束程序退出。
- 如果接收应答成功, 在
demo_dynreg_recv_handler()
的应答处理回调函数中, 演示解析获取服务端应答的内容。
TODO
在注释中标明。
- 设置设备的设备证书
请替换示例程序中如下的
TODO
部分, 传入客户自己设备的ProductKey、ProductSecret和DeviceName:/* TODO: 替换为自己设备的productKey, productSecret和deviceName */ char *product_key = "a13FNXXXXXX"; char *product_secret = "y7GSILD480XXXXXX"; char *device_name = "dynreg_basic_demo";
- 给SDK配置全局的底层依赖和日志回调
底层依赖描述了硬件平台的资源使用方式,比如怎样获取时钟、分配内存等, 日志回调是用户的函数,SDK有log输出的时候会进入这个函数。
int main(int argc, char *argv[]) { ... ... /* 配置SDK的底层依赖 */ aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile); /* 配置SDK的日志输出 */ aiot_state_set_logcb(demo_state_logcb);
- 配置动态注册参数
这些连接参数包含如何建立TLS连接、服务器地址、连接后的数据及事件回调函数等。
/* 创建1个dynreg客户端实例并内部初始化默认参数 */ dynreg_handle = aiot_dynreg_init(); if (dynreg_handle == NULL) { printf("aiot_dynreg_init failed\n"); return -1; } /* 配置连接的服务器地址 */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_HOST, (void *)host); /* 配置连接的服务器端口 */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PORT, (void *)&port); /* 配置设备productKey */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_KEY, (void *)product_key); /* 配置设备productSecret */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_SECRET, (void *)product_secret); /* 配置设备deviceName */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_DEVICE_NAME, (void *)device_name); /* 配置网络连接的安全凭据, 上面已经创建好了 */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_NETWORK_CRED, (void *)&cred); /* 配置DYNREG默认消息接收回调函数 */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_RECV_HANDLER, (void *)demo_dynreg_recv_handler); /* 设置用户上下文,该上下文会在 demo_dynreg_recv_handler 被调用时传回 */ aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_USERDATA, (void *)&demo_info); ... ...
- 向服务器发送服务请求
调用
aiot_dynreg_send_request()
接口,以上面设置的参数,向dynreg服务器发起服务请求。/* 发送动态注册请求 */ res = aiot_dynreg_send_request(dynreg_handle); if (res < STATE_SUCCESS) { printf("aiot_dynreg_send_request failed: -0x%04X\n", -res); return -1; }
- 以下日志对应被发送的服务请求
[1580997987.888][LK-040B] > POST /auth/register/device HTTP/1.1 [1580997987.888][LK-040B] > Host: iot-auth.cn-shanghai.aliyuncs.com [1580997987.888][LK-040B] > Accept: text/xml,text/javascript,text/html,application/json [1580997987.888][LK-040B] > Content-Type: application/x-www-form-urlencoded [1580997987.888][LK-040B] > Content-Length: 160 [1580997987.888][LK-040B] > [LK-040C] > 70 72 6F 64 75 63 74 4B 65 79 3D 61 31 33 46 4E | productKey=a13FN [LK-040C] > 35 54 70 6C 4B 71 26 64 65 76 69 63 65 4E 61 6D | 5TplKq&deviceNam [LK-040C] > 65 3D 64 79 6E 72 65 67 5F 62 61 73 69 63 5F 64 | e=dynreg_basic_d [LK-040C] > 65 6D 6F 26 72 61 6E 64 6F 6D 3D 35 30 35 31 37 | emo&random=50517 [LK-040C] > 31 39 37 33 26 73 69 67 6E 3D 38 32 41 34 30 33 | 1973&sign=82A403 [LK-040C] > 38 46 32 35 37 36 38 34 39 31 32 34 34 36 36 36 | 8F25768491244666 [LK-040C] > 43 30 34 30 46 33 38 46 45 44 42 33 39 30 32 37 | C040F38FEDB39027 [LK-040C] > 37 30 39 35 46 45 46 37 34 43 46 36 43 37 32 34 | 7095FEF74CF6C724 [LK-040C] > 39 43 32 42 41 38 45 31 43 34 26 73 69 67 6E 4D | 9C2BA8E1C4&signM [LK-040C] > 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 32 35 36 | ethod=hmacsha256
- 处理服务应答
使用
aiot_dynreg_recv()
接口, 以上面设置的参数, 从dynreg服务器接收服务应答。/* 接收动态注册请求 */ res = aiot_dynreg_recv(dynreg_handle); if (res < STATE_SUCCESS) { printf("aiot_dynreg_recv failed: -0x%04X\n", -res); return -1; }
服务应答后日志展示如下:
[1580997987.944][LK-040D] < HTTP/1.1 200 OK [1580997987.944][LK-040D] < Server: Tengine [1580997987.944][LK-040D] < Date: Thu, 06 Feb 2020 14:06:27 GMT [1580997987.944][LK-040D] < Content-Type: text/xml [1580997987.944][LK-040D] < Content-Length: 151 [1580997987.944][LK-040D] < Connection: keep-alive [1580997987.944][LK-040D] < [LK-040E] < 7B 22 63 6F 64 65 22 3A 32 30 30 2C 22 64 61 74 | {"code":200,"dat [LK-040E] < 61 22 3A 7B 22 64 65 76 69 63 65 4E 61 6D 65 22 | a":{"deviceName" [LK-040E] < 3A 22 64 79 6E 72 65 67 5F 62 61 73 69 63 5F 64 | :"dynreg_basic_d [LK-040E] < 65 6D 6F 22 2C 22 64 65 76 69 63 65 53 65 63 72 | emo","deviceSecr [LK-040E] < 65 74 22 3A 22 58 6E 59 75 38 36 6B 71 58 54 39 | et":"XnYu8XXXXXX [LK-040E] < 34 6A 6A 32 65 72 5A 58 74 7A 4C 56 58 64 45 77 | 4jj2erZXtzLVXdEw [LK-040E] < 55 49 43 57 48 22 2C 22 70 72 6F 64 75 63 74 4B | UICWH","productK [LK-040E] < 65 79 22 3A 22 61 31 33 46 4E 35 54 70 6C 4B 71 | ey":"a13FN5TplKq [LK-040E] < 22 7D 2C 22 6D 65 73 73 61 67 65 22 3A 22 73 75 | "},"message":"su [LK-040E] < 63 63 65 73 73 22 7D | ccess"}
- 应答接收成功后,在回调函数中解析应答内容
之前已经用
AIOT_DYNREGOPT_RECV_HANDLER
选项设置了,SDK收到应答时应进入的数据处理函数是demo_dynreg_recv_handler()
。/* 数据处理回调, 当SDK从网络上收到dynreg消息时被调用 */ void demo_dynreg_recv_handler(void *handle, const aiot_dynreg_recv_t *packet, void *userdata) { demo_info_t *demo_info = (demo_info_t *)userdata; switch (packet->type) { case AIOT_DYNREGRECV_STATUS_CODE: { demo_info->code = packet->data.status_code.code; } break; /* TODO: 回调中需要将packet指向的空间内容复制保存好, 因为回调返回后, 这些空间就会被SDK释放 */ case AIOT_DYNREGRECV_DEVICE_INFO: { demo_info->device_secret = malloc(strlen(packet->data.device_info.device_secret) + 1); if (demo_info->device_secret != NULL) { memset(demo_info->device_secret, 0, strlen(packet->data.device_info.device_secret) + 1); memcpy(demo_info->device_secret, packet->data.device_info.device_secret, strlen(packet->data.device_info.device_secret)); } } break; default: { } break; } }
动态服务服务应答已经被储存在回调函数的入参
packet
中, 在回调中需要将它的内容复制到demo_info
, 因为回调返回后, SDK就要将相关的内存空间释放掉了。 - 打印服务应答的消息内容
aiot_dynreg_recv()
接口返回后(其中经过了触发并执行demo_dynreg_recv_handler()
), 服务器应答内容已被保存, 将它们打印出来。/* 把服务应答中的 deviceSecret 打印出来 */ if (demo_info.device_secret != NULL) { printf("device secret: %s\n", demo_info.device_secret); free(demo_info.device_secret); }
实际的业务使用中, 应答内容自然不只是被打印出来, 对其中的设备共享密钥
deviceSecret
, 一般会被保存, 然后传给SDK的MQTT接口, 用于建立MQTT长连接。 - 销毁会话实例, 释放资源退出
动态注册的主要功能:获取设备共享密钥(deviceSecret)已经演示完毕, 例程到这里就清理资源, 正常退出了。
/* 销毁动态注册会话实例 */ res = aiot_dynreg_deinit(&dynreg_handle);
在文档使用中是否遇到以下问题
更多建议
匿名提交