1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include "amp_platform.h"
6 #include "aos_system.h"
7 #include "amp_defines.h"
8 #include "aiot_state_api.h"
9 #include "aiot_sysdep_api.h"
10 #include "aiot_dynreg_api.h"
11 #include "aiot_mqtt_api.h"
12 #include "module_aiot.h"
13 
14 #define MOD_STR "AIOT_DYNREG"
15 
16 /* 位于portfiles/aiot_port文件夹下的系统适配函数集合 */
17 extern aiot_sysdep_portfile_t g_aiot_sysdep_portfile;
18 
19 /* 位于external/ali_ca_cert.c中的服务器证书 */
20 extern const char *ali_ca_cert;
21 
aiot_app_dynreg_recv_handler(void * handle,const aiot_dynreg_recv_t * packet,void * userdata)22 void aiot_app_dynreg_recv_handler(void *handle, const aiot_dynreg_recv_t *packet, void *userdata)
23 {
24     JSValue *js_cb_ref = (JSValue *)userdata;
25     JSContext *ctx = js_get_context();
26     if (packet->type == AIOT_DYNREGRECV_STATUS_CODE) {
27         amp_debug(MOD_STR, "dynreg rsp code = %d", packet->data.status_code.code);
28     } else {
29         if (packet->type == AIOT_DYNREGRECV_DEVICE_INFO) {
30             amp_debug(MOD_STR, "dynreg DS = %s", packet->data.device_info.device_secret);
31             aos_kv_set(AMP_CUSTOMER_DEVICESECRET, packet->data.device_info.device_secret, strlen(packet->data.device_info.device_secret), 1);
32             JSValue sec = JS_NewString(ctx, packet->data.device_info.device_secret);
33             JSValue val = JS_Call(ctx, *js_cb_ref, JS_UNDEFINED, 1, &sec);
34             JS_FreeValue(ctx, val);
35             JS_FreeValue(ctx, sec);
36             JS_FreeValue(ctx, *js_cb_ref);
37         }
38     }
39 }
40 
aiot_dynreg_http(JSValue * js_cb_ref)41 int32_t aiot_dynreg_http(JSValue *js_cb_ref)
42 {
43     int32_t res = STATE_SUCCESS;
44     char *auth_url = "iot-auth.cn-shanghai.aliyuncs.com";    /* 阿里云平台上海站点的域名后缀 */
45     char host[100] = {0};                                    /* 用这个数组拼接设备连接的云平台站点全地址, 规则是 ${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com */
46     uint16_t port = 443;                                     /* 无论设备是否使用TLS连接阿里云平台, 目的端口都是443 */
47     aiot_sysdep_network_cred_t cred;                         /* 安全凭据结构体, 如果要用TLS, 这个结构体中配置CA证书等参数 */
48     /* get device tripple info */
49     char product_key[IOTX_PRODUCT_KEY_LEN] = {0};
50     char product_secret[IOTX_PRODUCT_SECRET_LEN] = {0};
51     char device_name[IOTX_DEVICE_NAME_LEN] = {0};
52     char device_secret[IOTX_DEVICE_SECRET_LEN] = {0};
53     int productkey_len = IOTX_PRODUCT_KEY_LEN;
54     int productsecret_len = IOTX_PRODUCT_SECRET_LEN;
55     int devicename_len = IOTX_DEVICE_NAME_LEN;
56     int devicesecret_len = IOTX_DEVICE_SECRET_LEN;
57     aos_kv_get(AMP_CUSTOMER_PRODUCTKEY, product_key, &productkey_len);
58     aos_kv_get(AMP_CUSTOMER_PRODUCTSECRET, product_secret, &productsecret_len);
59     aos_kv_get(AMP_CUSTOMER_DEVICENAME, device_name, &devicename_len);
60     amp_debug(MOD_STR, "dev info pk: %s, ps: %s, dn: %s", product_key, product_secret, device_name);
61     /* end get device tripple info */
62     /* 配置SDK的底层依赖 */
63     aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
64     /* 配置SDK的日志输出 */
65     // aiot_state_set_logcb(demo_state_logcb);
66     /* 创建SDK的安全凭据, 用于建立TLS连接 */
67     memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
68     cred.option = AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA; /* 使用RSA证书校验MQTT服务端 */
69     cred.max_tls_fragment = 16384;                     /* 最大的分片长度为16K, 其它可选值还有4K, 2K, 1K, 0.5K */
70     cred.sni_enabled = 1;                              /* TLS建连时, 支持Server Name Indicator */
71     cred.x509_server_cert = ali_ca_cert;               /* 用来验证MQTT服务端的RSA根证书 */
72     cred.x509_server_cert_len = strlen(ali_ca_cert);   /* 用来验证MQTT服务端的RSA根证书长度 */
73     aos_kv_get(AMP_CUSTOMER_DEVICESECRET, device_secret, &devicesecret_len);
74     if (device_secret[0] == '\0' || device_secret[IOTX_DEVICE_SECRET_LEN] != '\0') {
75         if (product_secret[0] == '\0' || product_secret[IOTX_PRODUCT_SECRET_LEN] != '\0') {
76             amp_error(MOD_STR, "need dynamic register, product secret is null");
77             return -1;
78         }
79         void *dynreg_handle = NULL;
80         dynreg_handle = aiot_dynreg_init();
81         if (dynreg_handle == NULL) {
82             amp_error(MOD_STR, "dynreg handle is null");
83             aos_task_exit(0);
84             return NULL;
85         }
86         /* 配置网络连接的安全凭据, 上面已经创建好了 */
87         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_NETWORK_CRED, (void *)&cred);
88         /* 配置MQTT服务器地址 */
89         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_HOST, (void *)auth_url);
90         /* 配置MQTT服务器端口 */
91         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PORT, (void *)&port);
92         /* 配置设备productKey */
93         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_KEY, (void *)product_key);
94         /* 配置设备productSecret */
95         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_PRODUCT_SECRET, (void *)product_secret);
96         /* 配置设备deviceName */
97         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_DEVICE_NAME, (void *)device_name);
98         /* 配置DYNREG默认消息接收回调函数 */
99         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_RECV_HANDLER, (void *)aiot_app_dynreg_recv_handler);
100         /* 配置DYNREG默认消息接收回调函数参数 */
101         aiot_dynreg_setopt(dynreg_handle, AIOT_DYNREGOPT_USERDATA, js_cb_ref);
102         res = aiot_dynreg_send_request(dynreg_handle);
103         if (res < STATE_SUCCESS) {
104             amp_error(MOD_STR, "dynamic register send  fail res = %d\n\r", res);
105             aiot_dynreg_deinit(&dynreg_handle);
106             return -1;
107         }
108         res = aiot_dynreg_recv(dynreg_handle);
109         if (res < STATE_SUCCESS) {
110             amp_error(MOD_STR, "dynamic register recv fail res = %d\n\r", res);
111             aiot_dynreg_deinit(&dynreg_handle);
112             return -1;
113         }
114         aos_kv_get(AMP_CUSTOMER_DEVICESECRET, device_secret, &devicesecret_len);
115         res = aiot_dynreg_deinit(&dynreg_handle);
116         if (res < STATE_SUCCESS) {
117             amp_error(MOD_STR, "dynamic register deinit fail res = %d\n\r", res);
118             return -1;
119         }
120     } else {
121         amp_debug(MOD_STR, "device is already activated");
122         return -1;
123     }
124     return STATE_SUCCESS;
125 }
126