1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "aiot_dm_api.h"
6 #include "aiot_mqtt_api.h"
7 #include "aiot_state_api.h"
8 #include "aiot_sysdep_api.h"
9 #include "py/builtin.h"
10 #include "py/obj.h"
11 #include "py/runtime.h"
12 #include "py/stackctrl.h"
13 
14 /* 位于portfiles/aiot_port文件夹下的系统适配函数集合 */
15 extern aiot_sysdep_portfile_t g_aiot_sysdep_portfile;
16 
17 /* 位于external/ali_ca_cert.c中的服务器证书 */
18 extern const char *ali_ca_cert;
19 
20 static uint8_t g_mqtt_process_thread_running = 0;
21 static uint8_t g_mqtt_recv_thread_running = 0;
22 
23 void *dm_handle = NULL;
24 void *mqtt_handle = NULL;
25 
26 #define EXAMPLE_MASTER_DEVID     (0)
27 
28 #define EXAMPLE_YIELD_TIMEOUT_MS (200)
29 
30 #define RETRY_NUM                5
31 
32 typedef struct {
33     int master_devid;
34     int cloud_connected;
35     int master_initialized;
36 } user_example_ctx_t;
37 
38 typedef enum {
39     ON_CONNECT = 1,
40     ON_DISCONNECT = 3,
41     ON_SERVICE = 5,
42     ON_PROPS = 7,
43     ON_CLOSE = 2,
44     ON_ERROR = 4,
45 } lk_callback_func_t;
46 
47 typedef enum {
48     ITE_CONNECT_SUCC = 1,
49     ITE_DISCONNECTED = 3,
50     ITE_SERVICE_REQUEST = 5,
51     ITE_PROPERTY_SET = 7,
52     ITE_REPORT_REPLY = 2,
53     ITE_TRIGGER_EVENT_REPLY = 4,
54 } lk_callback_reg_func_t;
55 
56 static user_example_ctx_t g_user_example_ctx;
57 
58 static mp_obj_t on_connected;
59 static mp_obj_t on_disconnect;
60 static mp_obj_t on_report_reply;
61 static mp_obj_t on_event_reply;
62 static mp_obj_t on_property_set;
63 static mp_obj_t on_async_service;
64 
65 /* 日志回调函数, SDK的日志会从这里输出 */
py_demo_state_logcb(int32_t code,char * message)66 int32_t py_demo_state_logcb(int32_t code, char *message)
67 {
68     printf("%s", message);
69     return 0;
70 }
71 
user_service_request_event_handler(const int devid,const char * serviceid,const int serviceid_len,const char * request,const int request_len,char ** response,int * response_len)72 static int user_service_request_event_handler(
73     const int devid, const char *serviceid, const int serviceid_len,
74     const char *request, const int request_len, char **response,
75     int *response_len)
76 {
77     return 0;
78 }
79 
80 /** recv property post response message from cloud **/
user_report_reply_event_handler(const int devid,const int msgid,const int code,const char * reply,const int reply_len)81 static int user_report_reply_event_handler(const int devid, const int msgid,
82                                            const int code, const char *reply,
83                                            const int reply_len)
84 {
85     return 0;
86 }
87 
88 /** recv event post response message from cloud **/
user_trigger_event_reply_event_handler(const int devid,const int msgid,const int code,const char * eventid,const int eventid_len,const char * message,const int message_len)89 static int user_trigger_event_reply_event_handler(
90     const int devid, const int msgid, const int code, const char *eventid,
91     const int eventid_len, const char *message, const int message_len)
92 {
93     return 0;
94 }
95 
user_property_set_event_handler(const int devid,const char * request,const int request_len)96 static int user_property_set_event_handler(const int devid, const char *request,
97                                            const int request_len)
98 {
99     return 0;
100 }
101 
102 /* MQTT事件回调函数, 当网络连接/重连/断开时被触发,
103  * 事件定义见core/aiot_mqtt_api.h */
demo_mqtt_event_handler(void * handle,const aiot_mqtt_event_t * event,void * userdata)104 void demo_mqtt_event_handler(void *handle, const aiot_mqtt_event_t *event,
105                              void *userdata)
106 {
107     switch (event->type) {
108     /* SDK因为用户调用了aiot_mqtt_connect()接口, 与mqtt服务器建立连接已成功
109      */
110     case AIOT_MQTTEVT_CONNECT:
111         {
112             printf("AIOT_MQTTEVT_CONNECT\n");
113             if (mp_obj_is_fun(on_connected)) {
114                 mp_call_function_0(on_connected);
115             }
116         }
117         break;
118 
119     /* SDK因为网络状况被动断连后, 自动发起重连已成功 */
120     case AIOT_MQTTEVT_RECONNECT:
121         {
122             printf("AIOT_MQTTEVT_RECONNECT\n");
123         }
124         break;
125 
126     /* SDK因为网络的状况而被动断开了连接, network是底层读写失败,
127      * heartbeat是没有按预期得到服务端心跳应答 */
128     case AIOT_MQTTEVT_DISCONNECT:
129         {
130             char *cause = (event->data.disconnect ==
131                            AIOT_MQTTDISCONNEVT_NETWORK_DISCONNECT)
132                               ? ("network disconnect")
133                               : ("heartbeat disconnect");
134             printf("AIOT_MQTTEVT_DISCONNECT: %s\n", cause);
135         }
136         break;
137 
138     default:
139         {
140         }
141     }
142 }
143 
144 /* 执行aiot_mqtt_process的线程, 包含心跳发送和QoS1消息重发 */
demo_mqtt_process_thread(void * args)145 void *demo_mqtt_process_thread(void *args)
146 {
147     int32_t res = STATE_SUCCESS;
148 
149     printf("********aiot_mqtt_process******\r\n");
150 
151     while (g_mqtt_process_thread_running) {
152         res = aiot_mqtt_process(args);
153         if (res == STATE_USER_INPUT_EXEC_DISABLED) {
154             break;
155         }
156         aos_msleep(1000);
157     }
158     return NULL;
159 }
160 
161 /* 执行aiot_mqtt_recv的线程, 包含网络自动重连和从服务器收取MQTT消息 */
demo_mqtt_recv_thread(void * args)162 void *demo_mqtt_recv_thread(void *args)
163 {
164     int32_t res = STATE_SUCCESS;
165 
166     while (g_mqtt_recv_thread_running) {
167         res = aiot_mqtt_recv(args);
168         if (res < STATE_SUCCESS) {
169             if (res == STATE_USER_INPUT_EXEC_DISABLED) {
170                 break;
171             }
172             aos_msleep(1000);
173         }
174     }
175     return NULL;
176 }
177 
178 /* 用户数据接收处理回调函数 */
demo_dm_recv_handler(void * dm_handle,const aiot_dm_recv_t * recv,void * userdata)179 static void demo_dm_recv_handler(void *dm_handle, const aiot_dm_recv_t *recv,
180                                  void *userdata)
181 {
182     printf("demo_dm_recv_handler, type = %d\r\n", recv->type);
183 
184     switch (recv->type) {
185     /* 属性上报, 事件上报, 获取期望属性值或者删除期望属性值的应答 */
186     case AIOT_DMRECV_GENERIC_REPLY:
187         {
188             printf("msg_id = %d, code = %d, data = %.*s, message = %.*s\r\n",
189                    recv->data.generic_reply.msg_id,
190                    recv->data.generic_reply.code,
191                    recv->data.generic_reply.data_len,
192                    recv->data.generic_reply.data,
193                    recv->data.generic_reply.message_len,
194                    recv->data.generic_reply.message);
195         }
196         break;
197 
198     /* 属性设置 */
199     case AIOT_DMRECV_PROPERTY_SET:
200         {
201             printf("msg_id = %ld, params = %.*s\r\n",
202                    (unsigned long)recv->data.property_set.msg_id,
203                    recv->data.property_set.params_len,
204                    recv->data.property_set.params);
205 
206             if (mp_obj_is_fun(on_property_set)) {
207                 callback_to_python(
208                     on_property_set,
209                     mp_obj_new_str(recv->data.property_set.params,
210                                    recv->data.property_set.params_len));
211             } else {
212                 printf("on_property_set is not function \r\n");
213             }
214             /* TODO: 以下代码演示如何对来自云平台的属性设置指令进行应答,
215              * 用户可取消注释查看演示效果 */
216 
217             {
218                 aiot_dm_msg_t msg;
219 
220                 memset(&msg, 0, sizeof(aiot_dm_msg_t));
221                 msg.type = AIOT_DMMSG_PROPERTY_SET_REPLY;
222                 msg.data.property_set_reply.msg_id =
223                     recv->data.property_set.msg_id;
224                 msg.data.property_set_reply.code = 200;
225                 msg.data.property_set_reply.data = "{}";
226                 int32_t res = aiot_dm_send(dm_handle, &msg);
227                 if (res < 0) {
228                     printf("aiot_dm_send failed\r\n");
229                 }
230             }
231         }
232         break;
233 
234     /* 异步服务调用 */
235     case AIOT_DMRECV_ASYNC_SERVICE_INVOKE:
236         {
237             printf("msg_id = %ld, service_id = %s, params = %.*s\r\n",
238                    (unsigned long)recv->data.async_service_invoke.msg_id,
239                    recv->data.async_service_invoke.service_id,
240                    recv->data.async_service_invoke.params_len,
241                    recv->data.async_service_invoke.params);
242 
243             if (mp_obj_is_fun(on_async_service)) {
244                 mp_obj_t dict = mp_obj_new_dict(2);
245                 mp_obj_dict_store(
246                     dict, MP_OBJ_NEW_QSTR(qstr_from_str("id")),
247                     mp_obj_new_strn(
248                         recv->data.async_service_invoke.service_id));
249                 mp_obj_dict_store(
250                     dict, MP_OBJ_NEW_QSTR(qstr_from_str("param")),
251                     mp_obj_new_str(recv->data.async_service_invoke.params,
252                                    recv->data.async_service_invoke.params_len));
253                 callback_to_python(on_async_service, dict);
254             }
255 
256             /* TODO: 以下代码演示如何对来自云平台的异步服务调用进行应答,
257              * 用户可取消注释查看演示效果
258              *
259              * 注意: 如果用户在回调函数外进行应答, 需要自行保存msg_id,
260              * 因为回调函数入参在退出回调函数后将被SDK销毁, 不可以再访问到
261              */
262 
263             /*
264                 {
265                     aiot_dm_msg_t msg;
266 
267                     memset(&msg, 0, sizeof(aiot_dm_msg_t));
268                     msg.type = AIOT_DMMSG_ASYNC_SERVICE_REPLY;
269                     msg.data.async_service_reply.msg_id =
270                 recv->data.async_service_invoke.msg_id;
271                     msg.data.async_service_reply.code = 200;
272                     msg.data.async_service_reply.service_id =
273                "ToggleLightSwitch"; msg.data.async_service_reply.data =
274                "{\"dataA\": 20}"; int32_t res = aiot_dm_send(dm_handle,
275                &msg); if (res < 0) { printf("aiot_dm_send failed\r\n");
276                     }
277                 }
278                 */
279         }
280         break;
281 
282     /* 同步服务调用 */
283     case AIOT_DMRECV_SYNC_SERVICE_INVOKE:
284         {
285             printf(
286                 "msg_id = %ld, rrpc_id = %s, service_id = %s, params = "
287                 "%.*s\r\n",
288                 (unsigned long)recv->data.sync_service_invoke.msg_id,
289                 recv->data.sync_service_invoke.rrpc_id,
290                 recv->data.sync_service_invoke.service_id,
291                 recv->data.sync_service_invoke.params_len,
292                 recv->data.sync_service_invoke.params);
293 
294             /* TODO: 以下代码演示如何对来自云平台的同步服务调用进行应答,
295              * 用户可取消注释查看演示效果
296              *
297              * 注意: 如果用户在回调函数外进行应答,
298              * 需要自行保存msg_id和rrpc_id字符串,
299              * 因为回调函数入参在退出回调函数后将被SDK销毁, 不可以再访问到
300              */
301 
302             /*
303                 {
304                     aiot_dm_msg_t msg;
305 
306                     memset(&msg, 0, sizeof(aiot_dm_msg_t));
307                     msg.type = AIOT_DMMSG_SYNC_SERVICE_REPLY;
308                     msg.data.sync_service_reply.rrpc_id =
309                 recv->data.sync_service_invoke.rrpc_id;
310                     msg.data.sync_service_reply.msg_id =
311                 recv->data.sync_service_invoke.msg_id;
312                     msg.data.sync_service_reply.code = 200;
313                     msg.data.sync_service_reply.service_id =
314                "SetLightSwitchTimer"; msg.data.sync_service_reply.data =
315                "{}"; int32_t res = aiot_dm_send(dm_handle, &msg); if (res <
316                0) { printf("aiot_dm_send failed\r\n");
317                     }
318                 }
319                 */
320         }
321         break;
322 
323     /* 下行二进制数据 */
324     case AIOT_DMRECV_RAW_DATA:
325         {
326             printf("raw data len = %d\r\n", recv->data.raw_data.data_len);
327             /* TODO: 以下代码演示如何发送二进制格式数据,
328              * 若使用需要有相应的数据透传脚本部署在云端 */
329             /*
330                 {
331                     aiot_dm_msg_t msg;
332                     uint8_t raw_data[] = {0x01, 0x02};
333 
334                     memset(&msg, 0, sizeof(aiot_dm_msg_t));
335                     msg.type = AIOT_DMMSG_RAW_DATA;
336                     msg.data.raw_data.data = raw_data;
337                     msg.data.raw_data.data_len = sizeof(raw_data);
338                     aiot_dm_send(dm_handle, &msg);
339                 }
340                 */
341         }
342         break;
343 
344     /* 二进制格式的同步服务调用, 比单纯的二进制数据消息多了个rrpc_id */
345     case AIOT_DMRECV_RAW_SYNC_SERVICE_INVOKE:
346         {
347             printf("raw sync service rrpc_id = %s, data_len = %d\r\n",
348                    recv->data.raw_service_invoke.rrpc_id,
349                    recv->data.raw_service_invoke.data_len);
350         }
351         break;
352 
353     default:
354         break;
355     }
356 }
357 
358 /* 属性上报函数演示 */
demo_send_property_post(void * dm_handle,char * params)359 int32_t demo_send_property_post(void *dm_handle, char *params)
360 {
361     aiot_dm_msg_t msg;
362 
363     memset(&msg, 0, sizeof(aiot_dm_msg_t));
364     msg.type = AIOT_DMMSG_PROPERTY_POST;
365     msg.data.property_post.params = params;
366 
367     return aiot_dm_send(dm_handle, &msg);
368 }
369 
370 /* 事件上报函数演示 */
demo_send_event_post(void * dm_handle,char * event_id,char * params)371 int32_t demo_send_event_post(void *dm_handle, char *event_id, char *params)
372 {
373     aiot_dm_msg_t msg;
374 
375     memset(&msg, 0, sizeof(aiot_dm_msg_t));
376     msg.type = AIOT_DMMSG_EVENT_POST;
377     msg.data.event_post.event_id = event_id;
378     msg.data.event_post.params = params;
379 
380     return aiot_dm_send(dm_handle, &msg);
381 }
382 
383 /** cloud connected event callback */
user_connected_event_handler(void)384 static int user_connected_event_handler(void)
385 {
386     if (mp_obj_is_fun(on_connected)) {
387         mp_call_function_0(on_connected);
388     } else {
389         printf("Error : on_connected : is not function\n");
390     }
391     g_user_example_ctx.cloud_connected = 1;
392     return 0;
393 }
394 
395 /** cloud disconnected event callback */
user_disconnected_event_handler(void)396 static int user_disconnected_event_handler(void)
397 {
398     if (mp_obj_is_fun(on_connected)) {
399         mp_call_function_0(on_disconnect);
400     } else {
401         printf("Error:on_connected : is not function\n");
402     }
403     g_user_example_ctx.cloud_connected = 0;
404     return 0;
405 }
406 
linkkit_init(size_t n_args,const mp_obj_t * args)407 STATIC mp_obj_t linkkit_init(size_t n_args, const mp_obj_t *args)
408 {
409     int32_t res = STATE_SUCCESS;
410 
411     char *url =
412         "iot-as-mqtt.cn-shanghai.aliyuncs.com"; /* 阿里云平台上海站点的域名后缀
413                                                  */
414     char host[100] = { 0 }; /* 用这个数组拼接设备连接的云平台站点全地址, 规则是
415                ${productKey}.iot-as-mqtt.cn-shanghai.aliyuncs.com */
416     uint16_t port =
417         443; /* 无论设备是否使用TLS连接阿里云平台, 目的端口都是443 */
418     aiot_sysdep_network_cred_t
419         cred; /* 安全凭据结构体, 如果要用TLS, 这个结构体中配置CA证书等参数 */
420 
421     char *product_key = "a18wPzZJzNG";
422     char *device_name = "data_model_basic_demo";
423     char *device_secret = "uwMTmVAMnGGHaAkqmeDY6cHxxBMTP3TD";
424 
425     int ret = -1;
426     if (n_args < 5) {
427         printf("%s: args num is illegal :n_args = %d;\n", __func__, n_args);
428         return mp_const_none;
429     }
430 
431     // iot_host_name = mp_obj_str_get_str(args[0]);
432     product_key = mp_obj_str_get_str(args[1]);
433     device_name = mp_obj_str_get_str(args[2]);
434     device_secret = mp_obj_str_get_str(args[3]);
435     //  iot_product_sec = mp_obj_str_get_str(args[4]);
436 
437     /* 配置SDK的底层依赖 */
438     aiot_sysdep_set_portfile(&g_aiot_sysdep_portfile);
439     /* 配置SDK的日志输出 */
440     aiot_state_set_logcb(py_demo_state_logcb);
441 
442     /* 创建SDK的安全凭据, 用于建立TLS连接 */
443     memset(&cred, 0, sizeof(aiot_sysdep_network_cred_t));
444     cred.option =
445         AIOT_SYSDEP_NETWORK_CRED_SVRCERT_CA; /* 使用RSA证书校验MQTT服务端 */
446     cred.max_tls_fragment =
447         16384; /* 最大的分片长度为16K, 其它可选值还有4K, 2K, 1K, 0.5K */
448     cred.sni_enabled = 1; /* TLS建连时, 支持Server Name Indicator */
449     cred.x509_server_cert = ali_ca_cert; /* 用来验证MQTT服务端的RSA根证书 */
450     cred.x509_server_cert_len =
451         strlen(ali_ca_cert); /* 用来验证MQTT服务端的RSA根证书长度 */
452 
453     /* 创建1个MQTT客户端实例并内部初始化默认参数 */
454     mqtt_handle = aiot_mqtt_init();
455     if (mqtt_handle == NULL) {
456         printf("aiot_mqtt_init failed\n");
457         return -1;
458     }
459 
460     snprintf(host, 100, "%s.%s", product_key, url);
461     /* 配置MQTT服务器地址 */
462     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_HOST, (void *)host);
463     /* 配置MQTT服务器端口 */
464     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PORT, (void *)&port);
465     /* 配置设备productKey */
466     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_PRODUCT_KEY,
467                      (void *)product_key);
468     /* 配置设备deviceName */
469     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_NAME,
470                      (void *)device_name);
471     /* 配置设备deviceSecret */
472     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_DEVICE_SECRET,
473                      (void *)device_secret);
474     /* 配置网络连接的安全凭据, 上面已经创建好了 */
475     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_NETWORK_CRED, (void *)&cred);
476     /* 配置MQTT事件回调函数 */
477     aiot_mqtt_setopt(mqtt_handle, AIOT_MQTTOPT_EVENT_HANDLER,
478                      (void *)demo_mqtt_event_handler);
479 
480     /* 创建DATA-MODEL实例 */
481     dm_handle = aiot_dm_init();
482     if (dm_handle == NULL) {
483         printf("aiot_dm_init failed\n");
484         return -1;
485     }
486     /* 配置MQTT实例句柄 */
487     aiot_dm_setopt(dm_handle, AIOT_DMOPT_MQTT_HANDLE, mqtt_handle);
488     /* 配置消息接收处理回调函数 */
489     aiot_dm_setopt(dm_handle, AIOT_DMOPT_RECV_HANDLER,
490                    (void *)demo_dm_recv_handler);
491 
492     /* 与服务器建立MQTT连接 */
493     res = aiot_mqtt_connect(mqtt_handle);
494     if (res < STATE_SUCCESS) {
495         /* 尝试建立连接失败, 销毁MQTT实例, 回收资源 */
496         aiot_mqtt_deinit(&mqtt_handle);
497         printf("aiot_mqtt_connect failed: -0x%04X\n", -res);
498         return -1;
499     }
500 
501 #ifdef AOS_COMP_UAGENT
502     res = uagent_mqtt_client_set(mqtt_handle);
503     if (res != 0) {
504         printf("uAgent mqtt handle set failed ret = %d\n", res);
505     }
506 
507     res = uagent_ext_comm_start(product_key, device_name);
508     if (res != 0) {
509         printf("uAgent ext comm  start failed ret = %d\n", res);
510     }
511 #endif
512 
513     /* 创建一个单独的线程, 专用于执行aiot_mqtt_process, 它会自动发送心跳保活,
514      * 以及重发QoS1的未应答报文 */
515     g_mqtt_process_thread_running = 1;
516     res = aos_task_new("demo_mqtt_process", demo_mqtt_process_thread,
517                        mqtt_handle, 4096);
518     if (res != 0) {
519         printf("create demo_mqtt_recv_thread failed: %d\n", res);
520         return mp_const_false;
521     }
522 
523     /* 创建一个单独的线程用于执行aiot_mqtt_recv,
524      * 它会循环收取服务器下发的MQTT消息, 并在断线时自动重连 */
525     g_mqtt_recv_thread_running = 1;
526     res = aos_task_new("demo_mqtt_process", demo_mqtt_recv_thread, mqtt_handle,
527                        4096);
528     // res = pthread_create(&g_mqtt_recv_thread, NULL, demo_mqtt_recv_thread,
529     // mqtt_handle);
530     if (res != 0) {
531         printf("create demo_mqtt_recv_thread failed: %d\n", res);
532         return mp_const_false;
533     }
534     return mp_const_true;
535 }
536 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(mp_obj_link_init, 5, linkkit_init);
537 
register_dyn_dev(void)538 STATIC mp_obj_t register_dyn_dev(void)
539 {
540     return mp_const_true;
541 }
542 MP_DEFINE_CONST_FUN_OBJ_0(mp_obj_register_dyn_dev, register_dyn_dev);
543 
connect_lp(void)544 STATIC mp_obj_t connect_lp(void)
545 {
546     return mp_const_none;
547 }
548 MP_DEFINE_CONST_FUN_OBJ_0(mp_obj_connect_lp, connect_lp);
549 
register_call_back(mp_obj_t id,mp_obj_t func)550 STATIC mp_obj_t register_call_back(mp_obj_t id, mp_obj_t func)
551 {
552     int callback_id = mp_obj_get_int(id);
553     switch (callback_id) {
554     case ITE_CONNECT_SUCC:
555         on_connected = func;
556         break;
557     case ITE_DISCONNECTED:
558         break;
559     case ITE_SERVICE_REQUEST:
560         on_async_service = func;
561         break;
562     case ITE_PROPERTY_SET:
563         on_property_set = func;
564         break;
565     case ITE_REPORT_REPLY:
566         on_report_reply = func;
567         break;
568     case ITE_TRIGGER_EVENT_REPLY:
569         on_event_reply = func;
570         break;
571 
572     default:
573         break;
574     }
575     return mp_const_none;
576 }
577 MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_register_call_back, register_call_back);
578 
post_property(mp_obj_t data)579 STATIC mp_obj_t post_property(mp_obj_t data)
580 {
581     size_t len;
582     const char *payload = mp_obj_str_get_data(data, &len);
583     size_t ret = demo_send_property_post(dm_handle, payload);
584     return mp_obj_new_int(ret);
585 }
586 MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_post_property, post_property);
587 
post_event(mp_obj_t eventid,mp_obj_t data)588 STATIC mp_obj_t post_event(mp_obj_t eventid, mp_obj_t data)
589 {
590     size_t payload_len;
591     size_t id_len;
592     const char *event_id = mp_obj_str_get_data(eventid, &id_len);
593     const char *payload = mp_obj_str_get_data(data, &payload_len);
594     size_t ret = demo_send_event_post(dm_handle, event_id, payload);
595     return mp_obj_new_int(ret);
596 }
597 MP_DEFINE_CONST_FUN_OBJ_2(mp_obj_post_event, post_event);
598 
linkkit_yield(mp_obj_t time)599 STATIC mp_obj_t linkkit_yield(mp_obj_t time)
600 {
601     return mp_const_none;
602 }
603 MP_DEFINE_CONST_FUN_OBJ_1(mp_obj_linkkit_yield, linkkit_yield);
604 
linkkit_close()605 STATIC mp_obj_t linkkit_close()
606 {
607     int res = aiot_mqtt_disconnect(mqtt_handle);
608     if (res < STATE_SUCCESS) {
609         aiot_mqtt_deinit(&mqtt_handle);
610         printf("aiot_mqtt_disconnect failed: -0x%04X\n", -res);
611         return -1;
612     }
613 
614     /* 销毁DATA-MODEL实例, 一般不会运行到这里 */
615     res = aiot_dm_deinit(&dm_handle);
616     if (res < STATE_SUCCESS) {
617         printf("aiot_dm_deinit failed: -0x%04X\n", -res);
618         return -1;
619     }
620 
621     /* 销毁MQTT实例, 一般不会运行到这里 */
622     res = aiot_mqtt_deinit(&mqtt_handle);
623     if (res < STATE_SUCCESS) {
624         printf("aiot_mqtt_deinit failed: -0x%04X\n", -res);
625         return -1;
626     }
627     return mp_const_none;
628 }
629 MP_DEFINE_CONST_FUN_OBJ_0(mp_obj_linkkit_close, linkkit_close);
630 
631 STATIC const mp_rom_map_elem_t linkkit_module_globals_table[] = {
632     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__linkkit) },
633     { MP_OBJ_NEW_QSTR(MP_QSTR_init), MP_ROM_PTR(&mp_obj_link_init) },
634     { MP_OBJ_NEW_QSTR(MP_QSTR_register_dyn_dev),
635       MP_ROM_PTR(&mp_obj_register_dyn_dev) },
636     { MP_OBJ_NEW_QSTR(MP_QSTR_connect), MP_ROM_PTR(&mp_obj_connect_lp) },
637     { MP_OBJ_NEW_QSTR(MP_QSTR_register_call_back),
638       MP_ROM_PTR(&mp_obj_register_call_back) },
639     { MP_OBJ_NEW_QSTR(MP_QSTR_post_property),
640       MP_ROM_PTR(&mp_obj_post_property) },
641     { MP_OBJ_NEW_QSTR(MP_QSTR_post_event), MP_ROM_PTR(&mp_obj_post_event) },
642     { MP_OBJ_NEW_QSTR(MP_QSTR_do_yield), MP_ROM_PTR(&mp_obj_linkkit_yield) },
643     { MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_obj_linkkit_close) },
644     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_CONNECT), MP_ROM_INT(ON_CONNECT) },
645     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_DISCONNECT), MP_ROM_INT(ON_DISCONNECT) },
646     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_SERVICE), MP_ROM_INT(ON_SERVICE) },
647     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_PROPS), MP_ROM_INT(ON_PROPS) },
648     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_CLOSE), MP_ROM_INT(ON_CLOSE) },
649     { MP_OBJ_NEW_QSTR(MP_QSTR_ON_ERROR), MP_ROM_INT(ON_ERROR) },
650 };
651 
652 STATIC MP_DEFINE_CONST_DICT(linkkit_module_globals,
653                             linkkit_module_globals_table);
654 
655 const mp_obj_module_t linkkit_module = {
656     .base = { &mp_type_module },
657     .globals = (mp_obj_dict_t *)&linkkit_module_globals,
658 };
659