mqtt_sample.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. /*
  2. * Tencent is pleased to support the open source community by making IoT Hub
  3. available.
  4. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved.
  5. * Licensed under the MIT License (the "License"); you may not use this file
  6. except in
  7. * compliance with the License. You may obtain a copy of the License at
  8. * http://opensource.org/licenses/MIT
  9. * Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is
  11. * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  12. KIND,
  13. * either express or implied. See the License for the specific language
  14. governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. #include <signal.h>
  19. #include <stdbool.h>
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include "ql_api_osi.h"
  24. #include "ql_api_datacall.h"
  25. #include "qcloud_iot_export.h"
  26. #include "qcloud_iot_import.h"
  27. #include "utils_getopt.h"
  28. #define PROFILE_IDX 1
  29. #ifdef DEBUG_DEV_INFO_USED
  30. #define PRODUCT_ID "KSS57PUDXP"
  31. #define DEVICE_NAME "Smart_light_02"
  32. #define DEVICE_SECRET "mndRH7Y75zyFbXIvb5H2Yw=="
  33. #define DEVICE_CERT "./certs/Smart_light_01_cert.crt"
  34. #define DEVICE_PRIVATE "./certs/Smart_light_01_private.key"
  35. #define REGION "china"
  36. #else
  37. #define DEVICE_INFO_JSON_DOC "UFS:device_info.json"
  38. #endif
  39. #ifdef AUTH_MODE_CERT
  40. static char sg_cert_file[PATH_MAX + 1]; // full path of device cert file
  41. static char sg_key_file[PATH_MAX + 1]; // full path of device key file
  42. #endif
  43. static DeviceInfo sg_devInfo;
  44. static int sg_count = 0;
  45. static int sg_sub_packet_id = -1;
  46. ql_task_t mqtt_sample_task = NULL;
  47. #ifdef DEBUG_DEV_INFO_USED
  48. extern int device_info_copy(void *pdst, void *psrc, uint8_t max_len);
  49. #endif
  50. // user's log print callback
  51. static bool log_handler(const char *message)
  52. {
  53. // return true if print success
  54. return false;
  55. }
  56. // MQTT event callback
  57. static void _mqtt_event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
  58. {
  59. MQTTMessage *mqtt_messge = (MQTTMessage *)msg->msg;
  60. uintptr_t packet_id = (uintptr_t)msg->msg;
  61. switch (msg->event_type) {
  62. case MQTT_EVENT_UNDEF:
  63. Log_i("undefined event occur.");
  64. break;
  65. case MQTT_EVENT_DISCONNECT:
  66. Log_i("MQTT disconnect.");
  67. break;
  68. case MQTT_EVENT_RECONNECT:
  69. Log_i("MQTT reconnect.");
  70. break;
  71. case MQTT_EVENT_PUBLISH_RECVEIVED:
  72. Log_i(
  73. "topic message arrived but without any related handle: topic=%.*s, "
  74. "topic_msg=%.*s",
  75. mqtt_messge->topic_len, mqtt_messge->ptopic, mqtt_messge->payload_len, mqtt_messge->payload);
  76. break;
  77. case MQTT_EVENT_SUBCRIBE_SUCCESS:
  78. Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id);
  79. sg_sub_packet_id = packet_id;
  80. break;
  81. case MQTT_EVENT_SUBCRIBE_TIMEOUT:
  82. Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id);
  83. sg_sub_packet_id = packet_id;
  84. break;
  85. case MQTT_EVENT_SUBCRIBE_NACK:
  86. Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id);
  87. sg_sub_packet_id = packet_id;
  88. break;
  89. case MQTT_EVENT_UNSUBCRIBE_SUCCESS:
  90. Log_i("unsubscribe success, packet-id=%u", (unsigned int)packet_id);
  91. break;
  92. case MQTT_EVENT_UNSUBCRIBE_TIMEOUT:
  93. Log_i("unsubscribe timeout, packet-id=%u", (unsigned int)packet_id);
  94. break;
  95. case MQTT_EVENT_UNSUBCRIBE_NACK:
  96. Log_i("unsubscribe nack, packet-id=%u", (unsigned int)packet_id);
  97. break;
  98. case MQTT_EVENT_PUBLISH_SUCCESS:
  99. Log_i("publish success, packet-id=%u", (unsigned int)packet_id);
  100. break;
  101. case MQTT_EVENT_PUBLISH_TIMEOUT:
  102. Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id);
  103. break;
  104. case MQTT_EVENT_PUBLISH_NACK:
  105. Log_i("publish nack, packet-id=%u", (unsigned int)packet_id);
  106. break;
  107. default:
  108. Log_i("Should NOT arrive here.");
  109. break;
  110. }
  111. }
  112. // Setup MQTT construct parameters
  113. static int _setup_connect_init_params(MQTTInitParams *initParams)
  114. {
  115. int ret;
  116. #ifdef DEBUG_DEV_INFO_USED
  117. ret = HAL_GetDevInfo((void *)&sg_devInfo);
  118. #else
  119. ret = HAL_GetDevInfoFromFile(DEVICE_INFO_JSON_DOC, (void *)&sg_devInfo);
  120. #endif
  121. if (QCLOUD_RET_SUCCESS != ret) {
  122. return ret;
  123. }
  124. initParams->region = sg_devInfo.region;
  125. initParams->device_name = sg_devInfo.device_name;
  126. initParams->product_id = sg_devInfo.product_id;
  127. #ifdef AUTH_MODE_CERT
  128. // char certs_dir[PATH_MAX + 1] = "certs";
  129. // char current_path[PATH_MAX + 1];
  130. // char *cwd = getcwd(current_path, sizeof(current_path));
  131. //
  132. // if (cwd == NULL) {
  133. // Log_e("getcwd return NULL");
  134. // return QCLOUD_ERR_FAILURE;
  135. // }
  136. //#ifdef WIN32
  137. // sprintf(sg_cert_file, "%s\\%s\\%s", current_path, certs_dir, sg_devInfo.dev_cert_file_name);
  138. // sprintf(sg_key_file, "%s\\%s\\%s", current_path, certs_dir, sg_devInfo.dev_key_file_name);
  139. //#else
  140. // sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, sg_devInfo.dev_cert_file_name);
  141. // sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, sg_devInfo.dev_key_file_name);
  142. //#endif
  143. sprintf(sg_cert_file, "%s", sg_devInfo.dev_cert_file_name);
  144. sprintf(sg_key_file, "%s", sg_devInfo.dev_key_file_name);
  145. initParams->cert_file = sg_cert_file;
  146. initParams->key_file = sg_key_file;
  147. #else
  148. initParams->device_secret = sg_devInfo.device_secret;
  149. #endif
  150. initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  151. initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL;
  152. initParams->auto_connect_enable = 1;
  153. initParams->event_handle.h_fp = _mqtt_event_handler;
  154. initParams->event_handle.context = NULL;
  155. return QCLOUD_RET_SUCCESS;
  156. }
  157. #define MAX_SIZE_OF_TOPIC_CONTENT 100
  158. // publish MQTT msg
  159. static int _publish_test_msg(void *client, char *topic_keyword, QoS qos)
  160. {
  161. char topicName[128] = {0};
  162. sprintf(topicName, "%s/%s/%s", sg_devInfo.product_id, sg_devInfo.device_name, topic_keyword);
  163. PublishParams pub_params = DEFAULT_PUB_PARAMS;
  164. pub_params.qos = qos;
  165. char topic_content[MAX_SIZE_OF_TOPIC_CONTENT + 1] = {0};
  166. int size = HAL_Snprintf(topic_content, sizeof(topic_content), "{\"action\": \"publish_test\", \"count\": \"%d\"}",
  167. sg_count++);
  168. if (size < 0 || size > sizeof(topic_content) - 1) {
  169. Log_e("payload content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_content));
  170. return -3;
  171. }
  172. pub_params.payload = topic_content;
  173. pub_params.payload_len = strlen(topic_content);
  174. return IOT_MQTT_Publish(client, topicName, &pub_params);
  175. }
  176. // callback when MQTT msg arrives
  177. static void on_message_callback(void *pClient, MQTTMessage *message, void *userData)
  178. {
  179. if (message == NULL) {
  180. return;
  181. }
  182. Log_i("Receive Message With topicName:%.*s, payload:%.*s", (int)message->topic_len, message->ptopic,
  183. (int)message->payload_len, (char *)message->payload);
  184. }
  185. // subscribe MQTT topic and wait for sub result
  186. static int subscribe_topic_wait_result(void *client, char *topic_keyword, QoS qos)
  187. {
  188. char topic_name[128] = {0};
  189. int size = HAL_Snprintf(topic_name, sizeof(topic_name), "%s/%s/%s", sg_devInfo.product_id, \
  190. sg_devInfo.device_name, topic_keyword);
  191. if (size < 0 || size > sizeof(topic_name) - 1) {
  192. Log_e("topic content length not enough! content size:%d buf size:%d", size, (int)sizeof(topic_name));
  193. return QCLOUD_ERR_FAILURE;
  194. }
  195. SubscribeParams sub_params = DEFAULT_SUB_PARAMS;
  196. sub_params.qos = qos;
  197. sub_params.on_message_handler = on_message_callback;
  198. int rc = IOT_MQTT_Subscribe(client, topic_name, &sub_params);
  199. if (rc < 0) {
  200. Log_e("MQTT subscribe FAILED: %d", rc);
  201. return rc;
  202. }
  203. int wait_cnt = 10;
  204. while (!IOT_MQTT_IsSubReady(client, topic_name) && (wait_cnt > 0)) {
  205. // wait for subscription result
  206. rc = IOT_MQTT_Yield(client, 1000);
  207. if (rc) {
  208. Log_e("MQTT error: %d", rc);
  209. return rc;
  210. }
  211. wait_cnt--;
  212. }
  213. if (wait_cnt > 0) {
  214. return QCLOUD_RET_SUCCESS;
  215. } else {
  216. Log_e("wait for subscribe result timeout!");
  217. return QCLOUD_ERR_FAILURE;
  218. }
  219. }
  220. #ifdef LOG_UPLOAD
  221. // init log upload module
  222. static int _init_log_upload(MQTTInitParams *init_params)
  223. {
  224. LogUploadInitParams log_init_params;
  225. memset(&log_init_params, 0, sizeof(LogUploadInitParams));
  226. log_init_params.product_id = init_params->product_id;
  227. log_init_params.device_name = init_params->device_name;
  228. #ifdef AUTH_MODE_CERT
  229. log_init_params.sign_key = init_params->cert_file;
  230. #else
  231. log_init_params.sign_key = init_params->device_secret;
  232. #endif
  233. #if defined(__linux__) || defined(WIN32)
  234. log_init_params.read_func = HAL_Log_Read;
  235. log_init_params.save_func = HAL_Log_Save;
  236. log_init_params.del_func = HAL_Log_Del;
  237. log_init_params.get_size_func = HAL_Log_Get_Size;
  238. #endif
  239. log_init_params.profile_idx = init_params->profile_idx;
  240. return IOT_Log_Init_Uploader(&log_init_params);
  241. }
  242. #endif
  243. //static bool sg_loop_test = false;
  244. static bool sg_loop_test = true;
  245. //static int parse_arguments(int argc, char **argv)
  246. //{
  247. // int c;
  248. // while ((c = utils_getopt(argc, argv, "c:l")) != EOF) switch (c) {
  249. // case 'c':
  250. // if (HAL_SetDevInfoFile(utils_optarg))
  251. // return -1;
  252. // break;
  253. //
  254. // case 'l':
  255. // sg_loop_test = true;
  256. // break;
  257. //
  258. // default:
  259. // HAL_Printf(
  260. // "usage: %s [options]\n"
  261. // " [-c <config file for DeviceInfo>] \n"
  262. // " [-l ] loop test or not\n",
  263. // argv[0]);
  264. // return -1;
  265. // }
  266. // return 0;
  267. //}
  268. static int datacall_satrt(void)
  269. {
  270. int ret = 0;
  271. int i = 0;
  272. ql_data_call_info_s info;
  273. char ip4_addr_str[16] = {0};
  274. uint8_t nSim = 0;
  275. ql_rtos_task_sleep_s(10);
  276. Log_e("wait for network register done");
  277. while ((ret = ql_network_register_wait(nSim, 120)) != 0 && i < 10)
  278. {
  279. i++;
  280. ql_rtos_task_sleep_s(1);
  281. }
  282. if (ret == 0)
  283. {
  284. i = 0;
  285. Log_e("====network registered!!!!====");
  286. }
  287. else
  288. {
  289. Log_e("====network register failure!!!!!====");
  290. goto exit;
  291. }
  292. ql_set_data_call_asyn_mode(nSim, PROFILE_IDX, 0);
  293. Log_e("===start data call====");
  294. ret = ql_start_data_call(nSim, PROFILE_IDX, QL_PDP_TYPE_IP, "uninet", NULL, NULL, 0);
  295. Log_e("===data call result:%d", ret);
  296. if (ret != 0)
  297. {
  298. Log_e("====data call failure!!!!=====");
  299. }
  300. memset(&info, 0x00, sizeof(ql_data_call_info_s));
  301. ret = ql_get_data_call_info(nSim, PROFILE_IDX, &info);
  302. if (ret != 0)
  303. {
  304. Log_e("ql_get_data_call_info ret: %d", ret);
  305. ql_stop_data_call(nSim, PROFILE_IDX);
  306. goto exit;
  307. }
  308. Log_i("info.profile_idx: %d", info.profile_idx);
  309. Log_i("info.ip_version: %d", info.ip_version);
  310. Log_i("info.v4.state: %d", info.v4.state);
  311. //Log_i("info.v4.reconnect: %d", info.v4.reconnect);
  312. inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));
  313. Log_i("info.v4.addr.ip: %s", ip4_addr_str);
  314. inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_addr_str, sizeof(ip4_addr_str));
  315. Log_i("info.v4.addr.pri_dns: %s", ip4_addr_str);
  316. inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_addr_str, sizeof(ip4_addr_str));
  317. Log_i("info.v4.addr.sec_dns: %s", ip4_addr_str);
  318. return 0;
  319. exit:
  320. return -1;
  321. }
  322. static void mqtt_sample(void *argv)
  323. {
  324. int rc;
  325. void *client =NULL;
  326. // init log level
  327. IOT_Log_Set_Level(eLOG_DEBUG);
  328. IOT_Log_Set_MessageHandler(log_handler);
  329. /*执行拨号操作,设备联网*/
  330. if(datacall_satrt() != 0)
  331. {
  332. goto exit;
  333. }
  334. #ifdef DEBUG_DEV_INFO_USED
  335. DeviceInfo devInfo =
  336. {
  337. .product_id = PRODUCT_ID,
  338. .device_name = DEVICE_NAME,
  339. .client_id = ""PRODUCT_ID"_"DEVICE_NAME"",
  340. .region = REGION,
  341. .dev_type = eCOMMON_DEV,
  342. };
  343. #ifndef AUTH_MODE_CERT
  344. device_info_copy(devInfo.device_secret, DEVICE_SECRET,MAX_SIZE_OF_DEVICE_SECRET); // set dev cert file name,
  345. #else
  346. device_info_copy(devInfo.dev_cert_file_name, DEVICE_CERT,MAX_SIZE_OF_DEVICE_CERT_FILE_NAME); // set dev cert file name
  347. device_info_copy(devInfo.dev_key_file_name, DEVICE_PRIVATE,MAX_SIZE_OF_DEVICE_SECRET_FILE_NAME); // set dev cert file name
  348. #endif
  349. HAL_SetDevInfo(&devInfo);
  350. #endif
  351. // init connection
  352. MQTTInitParams init_params = DEFAULT_MQTTINIT_PARAMS;
  353. rc = _setup_connect_init_params(&init_params);
  354. if (rc != QCLOUD_RET_SUCCESS) {
  355. Log_e("init params error, rc = %d", rc);
  356. goto exit;
  357. }
  358. #ifdef LOG_UPLOAD
  359. // _init_log_upload should be done after _setup_connect_init_params and before
  360. // IOT_MQTT_Construct
  361. rc = _init_log_upload(&init_params);
  362. if (rc != QCLOUD_RET_SUCCESS)
  363. Log_e("init log upload error, rc = %d", rc);
  364. #endif
  365. // create MQTT client and connect with server
  366. client = IOT_MQTT_Construct(&init_params);
  367. if (client != NULL) {
  368. Log_i("Cloud Device Construct Success");
  369. } else {
  370. rc = IOT_MQTT_GetErrCode();
  371. Log_e("MQTT Construct failed, rc = %d", rc);
  372. goto exit;
  373. }
  374. #ifdef SYSTEM_COMM
  375. long time = 0;
  376. // get system timestamp from server
  377. rc = IOT_Get_Sys_Resource(client, eRESOURCE_TIME, &sg_devInfo, &time);
  378. if (QCLOUD_RET_SUCCESS == rc) {
  379. Log_i("system time is %ld", time);
  380. } else {
  381. Log_e("get system time failed!");
  382. }
  383. #endif
  384. // subscribe normal topics here
  385. rc = subscribe_topic_wait_result(client, "data", QOS0);
  386. if (rc < 0) {
  387. Log_e("Client Subscribe Topic Failed: %d", rc);
  388. goto exit;
  389. }
  390. // wait for subscription result
  391. IOT_MQTT_Yield(client, 500);
  392. do {
  393. if (sg_sub_packet_id > 0) {
  394. rc = _publish_test_msg(client, "data", QOS1);
  395. if (rc < 0) {
  396. Log_e("client publish topic failed :%d.", rc);
  397. }
  398. }
  399. rc = IOT_MQTT_Yield(client, 500);
  400. if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) {
  401. HAL_SleepMs(1000);
  402. continue;
  403. } else if (rc != QCLOUD_RET_SUCCESS && rc != QCLOUD_RET_MQTT_RECONNECTED) {
  404. Log_e("exit with error: %d", rc);
  405. break;
  406. }
  407. if (sg_loop_test)
  408. HAL_SleepMs(1000);
  409. } while (sg_loop_test);
  410. rc = IOT_MQTT_Destroy(&client);
  411. IOT_Log_Upload(true);
  412. #ifdef LOG_UPLOAD
  413. IOT_Log_Fini_Uploader();
  414. #endif
  415. exit:
  416. Log_e("task exit!");
  417. if(client!=NULL)
  418. {
  419. rc = IOT_MQTT_Destroy(&client);
  420. }
  421. ql_rtos_task_delete(NULL);
  422. }
  423. //static void ql_nw_status_callback(int profile_idx, int nw_status)
  424. //{
  425. // Log_i("profile(%d) status: %d", profile_idx, nw_status);
  426. //}
  427. //static int datacall_satrt(void)
  428. //{
  429. // ql_data_call_info_s info ;
  430. // memset(&info, 0x00, sizeof(ql_data_call_info_s));
  431. // char ip4_addr_str[16] = {0};
  432. // uint8_t nSim = 0;
  433. //
  434. // Log_d("wait for network register done");
  435. //
  436. // if(ql_network_register_wait(nSim,120) != 0)
  437. // {
  438. // Log_e("*** network register fail ***");
  439. // return -1;
  440. // }
  441. // else
  442. // {
  443. // Log_d("doing network activating ...");
  444. //
  445. // ql_nw_register_cb(ql_nw_status_callback);
  446. // ql_set_data_call_asyn_mode(nSim, PROFILE_IDX, 1);
  447. // if(ql_start_data_call(PROFILE_IDX, 0, "3gnet.mnc001.mcc460.gprs", NULL, NULL, 0) == 0)
  448. // {
  449. // ql_get_data_call_info(PROFILE_IDX, 0, &info);
  450. //
  451. // Log_i("info.profile_idx: %d", info.profile_idx);
  452. // Log_i("info.ip_version: %d", info.ip_version);
  453. // Log_i("info.v4.state: %d", info.v4.state);
  454. // //Log_i("info.v4.reconnect: %d", info.v4.reconnect);
  455. //
  456. // inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));
  457. // Log_i("info.v4.addr.ip: %s", ip4_addr_str);
  458. //
  459. // inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_addr_str, sizeof(ip4_addr_str));
  460. // Log_i("info.v4.addr.pri_dns: %s", ip4_addr_str);
  461. //
  462. // inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_addr_str, sizeof(ip4_addr_str));
  463. // Log_i("info.v4.addr.sec_dns: %s", ip4_addr_str);
  464. //
  465. // return 0;
  466. // }
  467. //
  468. // Log_e("*** network activated fail ***");
  469. // return -1;
  470. // }
  471. //}
  472. //int mqtt_sample_start(void)
  473. //{
  474. // ql_task_t mqtt_sample_task = NULL;
  475. //
  476. // if(datacall_satrt() == 0)
  477. // return ql_rtos_task_create(&mqtt_sample_task, 8*1024, 100, "mqtt_sample", main_entry, NULL);
  478. //
  479. // return -1;
  480. //}
  481. int mqtt_sample_start(void)
  482. {
  483. int err = 0;
  484. int count = 0;
  485. /* 主循环进入休眠 */
  486. while (count < 10)
  487. {
  488. count++;
  489. ql_rtos_task_sleep_s(1);
  490. Log_e("ql_qcloud_sdk_mqtt_sample_start_init -0x%04X\n", err);
  491. }
  492. err = ql_rtos_task_create(&mqtt_sample_task, 10*1024, APP_PRIORITY_NORMAL, "mqtt_sample", mqtt_sample, NULL, 5);
  493. if (err != QL_OSI_SUCCESS)
  494. {
  495. return -1;
  496. }
  497. return 0;
  498. }