更新硬件SDK

This commit is contained in:
kerwincui
2023-03-04 03:44:56 +08:00
parent dcdf6e1b7c
commit e39d3d2f03
1900 changed files with 663153 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
Name: 基于MQTT的动态注册
MQTT-dynreg Component for Link Kit SDK V4.0.0

View File

@@ -0,0 +1,543 @@
/**
* @file aiot_dynregmq_api.c
* @brief dynregmq模块的API接口实现, 提供获取设备信息的能力
*
* @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
*
*/
#include "dynregmq_private.h"
#include "core_string.h"
#include "core_log.h"
#include "core_auth.h"
static void _dynregmq_exec_inc(dynregmq_handle_t *dynregmq_handle)
{
dynregmq_handle->sysdep->core_sysdep_mutex_lock(dynregmq_handle->data_mutex);
dynregmq_handle->exec_count++;
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
}
static void _dynregmq_exec_dec(dynregmq_handle_t *dynregmq_handle)
{
dynregmq_handle->sysdep->core_sysdep_mutex_lock(dynregmq_handle->data_mutex);
dynregmq_handle->exec_count--;
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
}
static void _dynregmq_recv_handler(void *handle, const aiot_mqtt_recv_t *packet, void *userdata)
{
dynregmq_handle_t *dynregmq_handle = (dynregmq_handle_t *)userdata;
if (dynregmq_handle->recv_handler == NULL) {
return;
}
switch (packet->type) {
case AIOT_MQTTRECV_PUB: {
char *topic = packet->data.pub.topic;
uint32_t topic_len = packet->data.pub.topic_len;
char *payload = (char *)packet->data.pub.payload;
uint32_t payload_len = packet->data.pub.payload_len;
const char *topic_register = "/ext/register";
const char *topic_regnwl = "/ext/regnwl";
int32_t res = STATE_SUCCESS;
if (strlen(topic_register) == topic_len && !memcmp(topic_register, topic, topic_len)) {
const char *key_ds = "deviceSecret";
char *ds = NULL;
uint32_t ds_len = 0;
res = core_json_value(payload, payload_len, key_ds, strlen(key_ds),
&ds, &ds_len);
if (res != STATE_SUCCESS || ds == NULL || ds_len == 0) {
break;
}
dynregmq_handle->flag_completed = 1;
if (dynregmq_handle->recv_handler) {
aiot_dynregmq_recv_t recv_data;
memset(&recv_data, 0, sizeof(aiot_dynregmq_recv_t));
*(ds + ds_len) = 0;
recv_data.type = AIOT_DYNREGMQRECV_DEVICEINFO_WL;
recv_data.data.deviceinfo_wl.device_secret = ds;
dynregmq_handle->recv_handler(dynregmq_handle, &recv_data, dynregmq_handle->userdata);
}
} else if (strlen(topic_regnwl) == topic_len && !memcmp(topic_regnwl, topic, topic_len)) {
const char *key_clientid = "clientId";
const char *key_devicetoken = "deviceToken";
char *client_id = NULL;
char *device_token = NULL;
uint32_t client_id_len = 0;
uint32_t device_token_len = 0;
int32_t res = STATE_SUCCESS;
if ((res = core_json_value(payload, payload_len, key_clientid, strlen(key_clientid), &client_id,
&client_id_len)) != STATE_SUCCESS ||
(res = core_json_value(payload, payload_len, key_devicetoken, strlen(key_devicetoken), &device_token,
&device_token_len)) != STATE_SUCCESS) {
break;
}
if (client_id == NULL || device_token == NULL || client_id_len == 0 || device_token_len == 0) {
break;
}
dynregmq_handle->flag_completed = 1;
if (dynregmq_handle->recv_handler) {
aiot_dynregmq_recv_t recv_data;
char *conn_clientid = NULL;
char *conn_username = NULL;
char *conn_username_fmt[] = { dynregmq_handle->device_name, dynregmq_handle->product_key };
*(client_id + client_id_len) = 0;
*(device_token + device_token_len) = 0;
core_sprintf(dynregmq_handle->sysdep, &conn_clientid,
"%s|authType=connwl,securemode=-2,_ss=1,ext=3,_v="CORE_AUTH_SDK_VERSION"|",
&client_id, 1, DYNREGMQ_MODULE_NAME);
core_sprintf(dynregmq_handle->sysdep, &conn_username, "%s&%s",
conn_username_fmt, sizeof(conn_username_fmt) / sizeof(char *), DYNREGMQ_MODULE_NAME);
memset(&recv_data, 0, sizeof(aiot_dynregmq_recv_t));
recv_data.type = AIOT_DYNREGMQRECV_DEVICEINFO_NWL;
recv_data.data.deviceinfo_nwl.clientid = conn_clientid;
recv_data.data.deviceinfo_nwl.username = conn_username;
recv_data.data.deviceinfo_nwl.password = device_token;
dynregmq_handle->recv_handler(dynregmq_handle, &recv_data, dynregmq_handle->userdata);
dynregmq_handle->sysdep->core_sysdep_free(conn_clientid);
dynregmq_handle->sysdep->core_sysdep_free(conn_username);
}
}
}
break;
default:
break;
}
}
void *aiot_dynregmq_init(void)
{
dynregmq_handle_t *dynregmq_handle = NULL;
aiot_sysdep_portfile_t *sysdep = NULL;
sysdep = aiot_sysdep_get_portfile();
if (sysdep == NULL) {
return NULL;
}
dynregmq_handle = sysdep->core_sysdep_malloc(sizeof(dynregmq_handle_t), DYNREGMQ_MODULE_NAME);
if (dynregmq_handle == NULL) {
return NULL;
}
memset(dynregmq_handle, 0, sizeof(dynregmq_handle_t));
dynregmq_handle->sysdep = sysdep;
dynregmq_handle->timeout_ms = DYNREGMQ_DEFAULT_TIMEOUT_MS;
dynregmq_handle->deinit_timeout_ms = DYNREGMQ_DEFAULT_DEINIT_TIMEOUT_MS;
dynregmq_handle->send_timeout_ms = DYNREGMQ_DEFAULT_SEND_TIMEOUT;
dynregmq_handle->recv_timeout_ms = DYNREGMQ_DEFAULT_RECV_TIMEOUT;
dynregmq_handle->data_mutex = dynregmq_handle->sysdep->core_sysdep_mutex_init();
dynregmq_handle->exec_enabled = 1;
return dynregmq_handle;
}
int32_t aiot_dynregmq_setopt(void *handle, aiot_dynregmq_option_t option, void *data)
{
int32_t res = STATE_SUCCESS;
dynregmq_handle_t *dynregmq_handle = (dynregmq_handle_t *)handle;
if (dynregmq_handle == NULL || data == NULL) {
return STATE_USER_INPUT_NULL_POINTER;
}
if (option >= AIOT_DYNREGMQOPT_MAX) {
return STATE_USER_INPUT_OUT_RANGE;
}
if (dynregmq_handle->exec_enabled == 0) {
return STATE_USER_INPUT_EXEC_DISABLED;
}
_dynregmq_exec_inc(dynregmq_handle);
dynregmq_handle->sysdep->core_sysdep_mutex_lock(dynregmq_handle->data_mutex);
switch (option) {
case AIOT_DYNREGMQOPT_NETWORK_CRED: {
if (dynregmq_handle->cred != NULL) {
dynregmq_handle->sysdep->core_sysdep_free(dynregmq_handle->cred);
dynregmq_handle->cred = NULL;
}
dynregmq_handle->cred = dynregmq_handle->sysdep->core_sysdep_malloc(sizeof(aiot_sysdep_network_cred_t),
DYNREGMQ_MODULE_NAME);
if (dynregmq_handle->cred != NULL) {
memset(dynregmq_handle->cred, 0, sizeof(aiot_sysdep_network_cred_t));
memcpy(dynregmq_handle->cred, data, sizeof(aiot_sysdep_network_cred_t));
} else {
res = STATE_SYS_DEPEND_MALLOC_FAILED;
}
}
break;
case AIOT_DYNREGMQOPT_HOST: {
res = core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->host, data, DYNREGMQ_MODULE_NAME);
}
break;
case AIOT_DYNREGMQOPT_PORT: {
dynregmq_handle->port = *(uint16_t *)data;
}
break;
case AIOT_DYNREGMQOPT_PRODUCT_KEY: {
res = core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->product_key, data, DYNREGMQ_MODULE_NAME);
}
break;
case AIOT_DYNREGMQOPT_PRODUCT_SECRET: {
res = core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->product_secret, data, DYNREGMQ_MODULE_NAME);
}
break;
case AIOT_DYNREGMQOPT_DEVICE_NAME: {
res = core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->device_name, data, DYNREGMQ_MODULE_NAME);
}
break;
case AIOT_DYNREGMQOPT_SEND_TIMEOUT_MS: {
dynregmq_handle->send_timeout_ms = *(uint32_t *)data;
}
break;
case AIOT_DYNREGMQOPT_RECV_TIMEOUT_MS: {
dynregmq_handle->recv_timeout_ms = *(uint32_t *)data;
}
break;
case AIOT_DYNREGMQOPT_RECV_HANDLER: {
dynregmq_handle->recv_handler = (aiot_dynregmq_recv_handler_t)data;
}
break;
case AIOT_DYNREGMQOPT_USERDATA: {
dynregmq_handle->userdata = data;
}
break;
case AIOT_DYNREGMQOPT_TIMEOUT_MS: {
dynregmq_handle->timeout_ms = *(uint32_t *)data;
}
break;
case AIOT_DYNREGMQOPT_DEINIT_TIMEOUT_MS: {
dynregmq_handle->deinit_timeout_ms = *(uint32_t *)data;
}
break;
case AIOT_DYNREGMQOPT_NO_WHITELIST: {
dynregmq_handle->flag_nowhitelist = *(uint8_t *)data;
}
break;
case AIOT_DYNREGMQOPT_INSTANCE_ID: {
res = core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->instance_id, data, DYNREGMQ_MODULE_NAME);
}
break;
default: {
res = STATE_USER_INPUT_UNKNOWN_OPTION;
}
break;
}
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
_dynregmq_exec_dec(dynregmq_handle);
return res;
}
int32_t aiot_dynregmq_deinit(void **handle)
{
uint32_t deinit_timeout_ms = 0;
dynregmq_handle_t *dynregmq_handle = NULL;
aiot_sysdep_portfile_t *sysdep = NULL;
if (handle == NULL || *handle == NULL) {
return STATE_USER_INPUT_NULL_POINTER;
}
dynregmq_handle = *(dynregmq_handle_t **)handle;
sysdep = dynregmq_handle->sysdep;
if (dynregmq_handle->exec_enabled == 0) {
return STATE_USER_INPUT_EXEC_DISABLED;
}
dynregmq_handle->exec_enabled = 0;
deinit_timeout_ms = dynregmq_handle->deinit_timeout_ms;
do {
if (dynregmq_handle->exec_count == 0) {
break;
}
dynregmq_handle->sysdep->core_sysdep_sleep(DYNREGMQ_DEINIT_INTERVAL_MS);
} while ((deinit_timeout_ms > DYNREGMQ_DEINIT_INTERVAL_MS) && (deinit_timeout_ms - DYNREGMQ_DEINIT_INTERVAL_MS > 0));
if (dynregmq_handle->exec_count != 0) {
return STATE_DYNREGMQ_DEINIT_TIMEOUT;
}
*handle = NULL;
if (dynregmq_handle->mqtt_handle != NULL) {
aiot_mqtt_deinit(&dynregmq_handle->mqtt_handle);
}
if (dynregmq_handle->host != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->host);
}
if (dynregmq_handle->product_key != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->product_key);
}
if (dynregmq_handle->product_secret != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->product_secret);
}
if (dynregmq_handle->device_name != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->device_name);
}
if (dynregmq_handle->cred != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->cred);
}
if (dynregmq_handle->instance_id != NULL) {
sysdep->core_sysdep_free(dynregmq_handle->instance_id);
}
sysdep->core_sysdep_mutex_deinit(&dynregmq_handle->data_mutex);
sysdep->core_sysdep_free(dynregmq_handle);
return STATE_SUCCESS;
}
static void _core_append_instance_id(dynregmq_handle_t *dynregmq_handle)
{
const char *INSTANCE_PATTERN = ".mqtt.iothub.aliyuncs.com";
char *host = NULL;
char *ptr = NULL;
int total_len = 0;
int instance_id_len = 0;
void *content = NULL;
if (NULL == dynregmq_handle || NULL == dynregmq_handle->host) {
return;
}
host = dynregmq_handle->host;
if (NULL == host) {
return;
}
ptr = strstr(host, INSTANCE_PATTERN);
if (NULL == ptr) {
return;
}
total_len = ptr - host + 1;
instance_id_len = ptr - host;
if (instance_id_len <= 0) {
return;
}
content = dynregmq_handle->sysdep->core_sysdep_malloc(total_len, DYNREGMQ_MODULE_NAME);
if (content == NULL) {
return;
}
memset(content, 0, total_len);
memcpy(content, host, instance_id_len);
if (NULL == dynregmq_handle->instance_id) {
core_strdup(dynregmq_handle->sysdep, &dynregmq_handle->instance_id, content, DYNREGMQ_MODULE_NAME);
}
dynregmq_handle->sysdep->core_sysdep_free(content);
}
int32_t aiot_dynregmq_send_request(void *handle)
{
int32_t res = STATE_SUCCESS;
dynregmq_handle_t *dynregmq_handle = (dynregmq_handle_t *)handle;
char *auth_clientid = NULL;
char *auth_username = NULL;
char auth_password[65] = {0};
char *sign_input = NULL;
uint32_t random_num = 0;
char random[11] = {0};
char *auth_type = NULL;
uint8_t reconnect = 0;
if (dynregmq_handle == NULL) {
return STATE_USER_INPUT_NULL_POINTER;
}
if (dynregmq_handle->host == NULL) {
return STATE_USER_INPUT_MISSING_HOST;
}
if (dynregmq_handle->product_key == NULL) {
return STATE_USER_INPUT_MISSING_PRODUCT_KEY;
}
if (dynregmq_handle->product_secret == NULL) {
return STATE_USER_INPUT_MISSING_PRODUCT_SECRET;
}
if (dynregmq_handle->device_name == NULL) {
return STATE_USER_INPUT_MISSING_DEVICE_NAME;
}
if (dynregmq_handle->exec_enabled == 0) {
return STATE_USER_INPUT_EXEC_DISABLED;
}
_dynregmq_exec_inc(dynregmq_handle);
dynregmq_handle->sysdep->core_sysdep_mutex_lock(dynregmq_handle->data_mutex);
if (dynregmq_handle->mqtt_handle != NULL) {
aiot_mqtt_deinit(&dynregmq_handle->mqtt_handle);
}
dynregmq_handle->mqtt_handle = aiot_mqtt_init();
if (dynregmq_handle->mqtt_handle == NULL) {
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
_dynregmq_exec_dec(dynregmq_handle);
return STATE_SYS_DEPEND_MALLOC_FAILED;
}
/* setup auth_type */
auth_type = (dynregmq_handle->flag_nowhitelist) ? "regnwl" : "register";
/* generate random string */
dynregmq_handle->sysdep->core_sysdep_rand((uint8_t *)&random_num, 4);
core_uint2str(random_num, random, NULL);
/* assamble clientid, username and password */
{
/* generate client_id automatically */
_core_append_instance_id(dynregmq_handle);
uint8_t has_instance_id = (dynregmq_handle->instance_id != NULL) ? 1 : 0;
char *client_fmt = (has_instance_id) ?
"%s.%s|random=%s,authType=%s,securemode=2,signmethod=hmacsha256,instanceId=%s|" :
"%s.%s|random=%s,authType=%s,securemode=2,signmethod=hmacsha256|";
char *client_src[] = { dynregmq_handle->device_name, dynregmq_handle->product_key,
random, auth_type, dynregmq_handle->instance_id
};
char *username_fmt = "%s&%s";
char *username_src[] = { dynregmq_handle->device_name, dynregmq_handle->product_key };
char *sign_input_fmt = "deviceName%sproductKey%srandom%s";
uint8_t sign_output[32] = {0};
core_sprintf(dynregmq_handle->sysdep, &auth_clientid, client_fmt, client_src,
has_instance_id ? 5 : 4, DYNREGMQ_MODULE_NAME);
core_sprintf(dynregmq_handle->sysdep, &auth_username, username_fmt, username_src,
sizeof(username_src) / sizeof(char *), DYNREGMQ_MODULE_NAME);
core_sprintf(dynregmq_handle->sysdep, &sign_input, sign_input_fmt, client_src,
3, DYNREGMQ_MODULE_NAME);
core_hmac_sha256((const uint8_t *)sign_input, (uint32_t)strlen(sign_input),
(const uint8_t *)dynregmq_handle->product_secret,
(uint32_t)strlen(dynregmq_handle->product_secret), sign_output);
core_hex2str(sign_output, sizeof(sign_output), auth_password, 0);
}
if (((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_HOST,
(void *)dynregmq_handle->host)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_PORT,
(void *)&dynregmq_handle->port)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_CLIENTID,
(void *)auth_clientid)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_USERNAME,
(void *)auth_username)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_PASSWORD,
(void *)auth_password)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED,
(void *)dynregmq_handle->cred)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_SEND_TIMEOUT_MS,
(void *)&dynregmq_handle->send_timeout_ms)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_RECV_TIMEOUT_MS,
(void *)&dynregmq_handle->recv_timeout_ms)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_RECV_HANDLER,
(void *)_dynregmq_recv_handler)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_USERDATA,
(void *)dynregmq_handle)) < STATE_SUCCESS) ||
((res = aiot_mqtt_setopt(dynregmq_handle->mqtt_handle, AIOT_MQTTOPT_RECONN_ENABLED,
(void *)&reconnect)) < STATE_SUCCESS)) {
aiot_mqtt_deinit(&dynregmq_handle->mqtt_handle);
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
_dynregmq_exec_dec(dynregmq_handle);
dynregmq_handle->sysdep->core_sysdep_free(auth_clientid);
dynregmq_handle->sysdep->core_sysdep_free(auth_username);
dynregmq_handle->sysdep->core_sysdep_free(sign_input);
return res;
}
res = aiot_mqtt_connect(dynregmq_handle->mqtt_handle);
if (res < STATE_SUCCESS) {
aiot_mqtt_deinit(&dynregmq_handle->mqtt_handle);
}
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
_dynregmq_exec_dec(dynregmq_handle);
dynregmq_handle->sysdep->core_sysdep_free(auth_clientid);
dynregmq_handle->sysdep->core_sysdep_free(auth_username);
dynregmq_handle->sysdep->core_sysdep_free(sign_input);
return res;
}
int32_t aiot_dynregmq_recv(void *handle)
{
int32_t res = STATE_SUCCESS;
uint64_t timenow_ms = 0;
dynregmq_handle_t *dynregmq_handle = (dynregmq_handle_t *)handle;
if (dynregmq_handle == NULL) {
return STATE_USER_INPUT_NULL_POINTER;
}
if (dynregmq_handle->mqtt_handle == NULL) {
return STATE_DYNREGMQ_NEED_SEND_REQUEST;
}
if (dynregmq_handle->exec_enabled == 0) {
return STATE_USER_INPUT_EXEC_DISABLED;
}
_dynregmq_exec_inc(dynregmq_handle);
dynregmq_handle->sysdep->core_sysdep_mutex_lock(dynregmq_handle->data_mutex);
timenow_ms = dynregmq_handle->sysdep->core_sysdep_time();
while (1) {
if (timenow_ms >= dynregmq_handle->sysdep->core_sysdep_time()) {
timenow_ms = dynregmq_handle->sysdep->core_sysdep_time();
}
if (dynregmq_handle->sysdep->core_sysdep_time() - timenow_ms >= dynregmq_handle->timeout_ms) {
res = STATE_DYNREGMQ_AUTH_TIMEOUT;
break;
}
res = aiot_mqtt_recv(dynregmq_handle->mqtt_handle);
if (res < 0) {
break;
}
if (dynregmq_handle->flag_completed == 1) {
dynregmq_handle->flag_completed = 0;
res = STATE_SUCCESS;
break;
}
}
dynregmq_handle->sysdep->core_sysdep_mutex_unlock(dynregmq_handle->data_mutex);
_dynregmq_exec_dec(dynregmq_handle);
return res;
}

View File

@@ -0,0 +1,336 @@
/**
* @file aiot_dynregmq_api.h
* @brief dynregmq模块头文件, 提供了基于MQTT的设备信息动态注册能力
*
* @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
*
*/
#ifndef __AIOT_DYNREGMQ_API_H__
#define __AIOT_DYNREGMQ_API_H__
#if defined(__cplusplus)
extern "C" {
#endif
#include <stdint.h>
/**
* @brief -0x0500~-0x05FF表达SDK在dynregmq模块内的状态码
*/
#define STATE_DYNREGMQ_BASE (-0x0500)
/**
* @brief 执行@ref aiot_dynregmq_deinit 时, 等待其他API执行结束的超过设定的超时时间, DYNREGMQ实例销毁失败
*/
#define STATE_DYNREGMQ_DEINIT_TIMEOUT (-0x0501)
/**
* @brief 需要首先执行@ref aiot_dynregmq_send_request 发送动态注册请求
*/
#define STATE_DYNREGMQ_NEED_SEND_REQUEST (-0x0502)
/**
* @brief 接收服务器应答超时
*/
#define STATE_DYNREGMQ_AUTH_TIMEOUT (-0x0503)
/**
* @brief @ref aiot_dynregmq_setopt 接口的option参数可选值.
*
* @details 下文每个选项中的数据类型, 指的是@ref aiot_dynregmq_setopt 中, data参数的数据类型
*
* 1. data的数据类型是char *时, 以配置@ref AIOT_DYNREGMQOPT_HOST 为例:
*
* char *host = "xxx";
* aiot_dynregmq_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_HOST, host);
*
* 2. data的数据类型是其他数据类型时, 以配置@ref AIOT_DYNREGMQOPT_PORT 为例:
*
* uint16_t port = 443;
* aiot_mqtt_setopt(dynregmq_handle, AIOT_DYNREGMQOPT_PORT, (void *)&port);
*/
typedef enum {
/**
* @brief mqtt动态注册 服务器建联时, 网络使用的安全凭据, 动态注册必需使用TLS方式建连
*
* @details
*
* 该配置项用于为底层网络配置@ref aiot_sysdep_network_cred_t 安全凭据数据
*
* 应当把 @ref aiot_sysdep_network_cred_t 中option配置为@ref AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA , 以tls方式建联
*
* 数据类型: (aiot_sysdep_network_cred_t *)
*/
AIOT_DYNREGMQOPT_NETWORK_CRED,
/**
* @brief mqtt动态注册 服务器的域名地址或者ip地址
*
* @details
*
* 阿里云物联网平台域名地址列表(必须使用自己的product key替换${pk}):
*
* 使用tls证书方式建联:
*
* | 域名地址 | 区域 | 端口号
* |-------------------------------------------------|---------|---------
* | ${pk}.iot-as-mqtt.cn-shanghai.aliyuncs.com | 上海 | 443
* | ${pk}.iot-as-mqtt.ap-southeast-1.aliyuncs.com | 新加坡 | 443
* | ${pk}.iot-as-mqtt.ap-northeast-1.aliyuncs.com | 日本 | 443
* | ${pk}.iot-as-mqtt.us-west-1.aliyuncs.com | 美西 | 443
* | ${pk}.iot-as-mqtt.eu-central-1.aliyuncs.com | 德国 | 443
*
* 数据类型: (char *)
*/
AIOT_DYNREGMQOPT_HOST,
/**
* @brief mqtt动态注册 服务器的端口号
*
* @details
*
* 连接阿里云物联网平台 mqtt动态注册 服务器时:
*
* 必须使用tls方式建联, 端口号设置为443
*
* 数据类型: (uint16_t *)
*/
AIOT_DYNREGMQOPT_PORT,
/**
* @brief 设备的productKey, 可从<a href="http://iot.console.aliyun.com/">阿里云物联网平台控制台</a>获取
*
* @details
*
* 数据类型: (char *)
*/
AIOT_DYNREGMQOPT_PRODUCT_KEY,
/**
* @brief 设备的productSecret, 可从<a href="http://iot.console.aliyun.com/">阿里云物联网平台控制台</a>获取
*
* @details
*
* 数据类型: (char *)
*/
AIOT_DYNREGMQOPT_PRODUCT_SECRET,
/**
* @brief 设备的deviceName, 可从<a href="http://iot.console.aliyun.com/">阿里云物联网平台控制台</a>获取
*
* @details
*
* 数据类型: (char *)
*/
AIOT_DYNREGMQOPT_DEVICE_NAME,
/**
* @brief dynregmq会话发送消息时可消费的最长时间间隔
*
* @details
*
* 数据类型: (uint32_t) 默认值: (5 * 1000) ms
*/
AIOT_DYNREGMQOPT_SEND_TIMEOUT_MS,
/**
* @brief dynregmq会话接收消息时可消费的最长时间间隔
*
* @details
*
* 数据类型: (uint32_t) 默认值: (5 * 1000) ms
*/
AIOT_DYNREGMQOPT_RECV_TIMEOUT_MS,
/**
* @brief 设置回调, 它在SDK收到网络报文的时候被调用, 告知用户
*
* @details
*
* 数据类型: (aiot_dynregmq_http_recv_handler_t)
*/
AIOT_DYNREGMQOPT_RECV_HANDLER,
/**
* @brief 用户需要SDK暂存的上下文
*
* @details
*
* 这个上下文指针会在 AIOT_DYNREGMQOPT_RECV_HANDLER 和 AIOT_DYNREGMQOPT_EVENT_HANDLER 设置的回调被调用时, 由SDK传给用户
*
* 数据类型: (void *)
*/
AIOT_DYNREGMQOPT_USERDATA,
/**
* @brief dynregmq模块接收消息的超时时间
*
* @details
*
* 数据类型: (uint32_t) 默认值: (5 * 1000) ms
*/
AIOT_DYNREGMQOPT_TIMEOUT_MS,
/**
* @brief 销毁dynregmq实例时, 等待其他api执行完毕的时间
*
* @details
*
* 当调用@ref aiot_dynregmq_deinit 销毁MQTT实例时, 若继续调用其他aiot_dynregmq_xxx API, API会返回@ref STATE_USER_INPUT_EXEC_DISABLED 错误
*
* 此时, 用户应该停止调用其他aiot_dynregmq_xxx API
*
* 数据类型: (uint32_t *) 默认值: (2 * 1000) ms
*/
AIOT_DYNREGMQOPT_DEINIT_TIMEOUT_MS,
/**
* @brief 是否使用免白名单功能
*
* @details
*
* 1. 配置为 0 则为白名单模式, 使用这种模式用户必须提前在控制台录入deviceName, 动态注册完成后服务会返回deviceSecret, 用户可通过
* AIOT_DYNREGMQRECV_DEVICEINFO_WL类型数据回调获取到deviceSecret.
* 2. 配置为 1 则为免白名单模式, 使用这种模式用户无需提前在控制台录入deviceName, 动态注册完成后服务会返回MQTT建连信息, 用户可通过
* AIOT_DYNREGMQRECV_DEVICEINFO_NWL类型数据回调获取到clientid, username, password. 用户需要将这三个参数通过
* aiot_mqtt_setopt接口以AIOT_MQTTOPT_CLIENTID, AIOT_MQTTOPT_USERNAME, AIOT_MQTTOPT_PASSWORD配置选项
* 配置到MQTT句柄中。
*
* 数据类型: (uint8_t *) 默认值: (0)
*
*/
AIOT_DYNREGMQOPT_NO_WHITELIST,
/**
* @brief 用户购买的物联网平台实例ID. 当用户使用自购实例, 且使用免白名单方式时, 必须设置实例ID
*
* @details
*
* 数据类型: (char *)
*
*/
AIOT_DYNREGMQOPT_INSTANCE_ID,
AIOT_DYNREGMQOPT_MAX
} aiot_dynregmq_option_t;
/**
* @brief dynregmq模块收到从网络上来的报文时, 通知用户的报文类型
*/
typedef enum {
/**
* @brief 白名单模式下服务器返回的设备信息
*/
AIOT_DYNREGMQRECV_DEVICEINFO_WL,
/**
* @brief 免白名单模式下服务器返回的设备信息
*/
AIOT_DYNREGMQRECV_DEVICEINFO_NWL,
} aiot_dynregmq_recv_type_t;
/**
* @brief dynregmq模块收到从网络上来的报文时, 通知用户的报文内容
*/
typedef struct {
/**
* @brief 报文内容所对应的报文类型, 更多信息请参考@ref aiot_dynregmq_recv_type_t
*/
aiot_dynregmq_recv_type_t type;
union {
/**
* @brief 白名单模式下服务器返回的设备信息
*/
struct {
char *device_secret;
} deviceinfo_wl;
/**
* @brief 免白名单模式下服务器返回的设备信息
*/
struct {
char *clientid;
char *username;
char *password;
} deviceinfo_nwl;
} data;
} aiot_dynregmq_recv_t;
/**
* @brief dynregmq模块收到从网络上来的报文时, 通知用户所调用的数据回调函数
*
* @param[in] handle dynregmq会话句柄
* @param[in] packet dynregmq消息结构体, 存放收到的dynregmq报文内容
* @param[in] userdata 用户上下文
*
* @return void
*/
typedef void (* aiot_dynregmq_recv_handler_t)(void *handle,
const aiot_dynregmq_recv_t *packet, void *userdata);
/**
* @brief 创建dynregmq会话实例, 并以默认值配置会话参数
*
* @return void *
* @retval 非NULL dynregmq实例的句柄
* @retval NULL 初始化失败, 一般是内存分配失败导致
*
*/
void *aiot_dynregmq_init(void);
/**
* @brief 配置dynregmq会话
*
* @param[in] handle dynregmq会话句柄
* @param[in] option 配置选项, 更多信息请参考@ref aiot_dynregmq_option_t
* @param[in] data 配置选项数据, 更多信息请参考@ref aiot_dynregmq_option_t
*
* @return int32_t
* @retval <STATE_SUCCESS 参数配置失败
* @retval >=STATE_SUCCESS 参数配置成功
*
*/
int32_t aiot_dynregmq_setopt(void *handle, aiot_dynregmq_option_t option, void *data);
/**
* @brief 结束dynregmq会话, 销毁实例并回收资源
*
* @param[in] handle 指向dynregmq会话句柄的指针
*
* @return int32_t
* @retval <STATE_SUCCESS 执行失败
* @retval >=STATE_SUCCESS 执行成功
*
*/
int32_t aiot_dynregmq_deinit(void **handle);
/**
* @brief 向dynregmq服务器发送dynregmq消息请求
*
* @param handle dynregmq会话句柄
*
* @return int32_t
* @retval <STATE_SUCCESS 请求发送失败
* @retval >=STATE_SUCCESS 请求发送成功
*/
int32_t aiot_dynregmq_send_request(void *handle);
/**
* @brief 从网络上收取dynregmq消息
*
* @param handle dynregmq会话句柄
*
* @return int32_t
* @retval <STATE_SUCCESS 数据接收失败
* @retval >=STATE_SUCCESS 数据接收成功
*/
int32_t aiot_dynregmq_recv(void *handle);
#if defined(__cplusplus)
}
#endif
#endif /* __AIOT_DYNREGMQMQ_API_H__ */

View File

@@ -0,0 +1,78 @@
/**
* @file dynregmq_private.h
* @brief dynregmq模块内部的宏定义和数据结构声明, 不面向其它模块, 更不面向用户
*
* @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
*
*/
#ifndef __DYNREGMQ_PRIVATE_H__
#define __DYNREGMQ_PRIVATE_H__
#if defined(__cplusplus)
extern "C" {
#endif
/* 用这种方式包含标准C库的头文件 */
#include "core_stdinc.h"
#include "aiot_state_api.h"
#include "aiot_sysdep_api.h"
#include "aiot_mqtt_api.h"
#include "aiot_dynregmq_api.h" /* 内部头文件是用户可见头文件的超集 */
typedef struct {
uint32_t code;
uint8_t *content;
uint32_t content_len;
uint32_t content_total_len;
} core_mqtt_response_t;
/* 定义dynregmq模块内部的会话句柄结构体, SDK用户不可见, 只能得到void *handle类型的指针 */
typedef struct {
aiot_sysdep_portfile_t *sysdep; /* 底层依赖回调合集的引用指针 */
aiot_sysdep_network_cred_t *cred; /* 指向当前连接使用的安全凭据 */
char *host; /* 会话目标服务器域名 */
uint16_t port; /* 会话目标服务器端口 */
char *product_key;
char *product_secret;
char *device_name;
uint8_t flag_nowhitelist; /* 是否使用免白名单功能 */
char
*instance_id; /* 实例ID当用户使用自购实例且使用免白名单方式时需设置实例ID */
aiot_dynregmq_recv_handler_t recv_handler; /* 组件从协议栈读到内容时, 通知用户的回调 */
void *userdata; /* 组件调用以上2个 dynregmq_handler 时的入参之一 */
uint32_t recv_timeout_ms; /* 从协议栈收包时最长等待时间 */
uint32_t send_timeout_ms; /* 向协议栈写入时最长花费时间 */
uint32_t timeout_ms;
uint32_t deinit_timeout_ms;
/*---- 以上都是用户在API可配 ----*/
/*---- 以下都是DYNREGMQ在内部使用, 用户无感知 ----*/
void *mqtt_handle;
uint8_t flag_completed;
uint8_t exec_enabled;
uint32_t exec_count;
void *data_mutex; /* 保护本地的数据结构 */
} dynregmq_handle_t;
#define DYNREGMQ_MODULE_NAME "dynregmq" /* 用于内存统计的模块名字符串 */
#define DYNREGMQ_DEFAULT_TIMEOUT_MS (5 * 1000)
#define DYNREGMQ_DEFAULT_DEINIT_TIMEOUT_MS (2 * 1000)
#define DYNREGMQ_DEFAULT_RECV_TIMEOUT (5 * 1000)
#define DYNREGMQ_DEFAULT_SEND_TIMEOUT (5 * 1000)
#define DYNREGMQ_DEINIT_INTERVAL_MS (100)
#if defined(__cplusplus)
}
#endif
#endif /* __DYNREGMQ_PRIVATE_H__ */