sub_dev001.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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 "lite-utils.h"
  19. #include "qcloud_iot_export.h"
  20. #include "qcloud_iot_import.h"
  21. #include "utils_timer.h"
  22. #include "qcloud_iot_export_data_template.h"
  23. /* anis color control codes */
  24. #define ANSI_COLOR_RED "\x1b[31m"
  25. #define ANSI_COLOR_GREEN "\x1b[32m"
  26. #define ANSI_COLOR_YELLOW "\x1b[33m"
  27. #define ANSI_COLOR_BLUE "\x1b[34m"
  28. #define ANSI_COLOR_RESET "\x1b[0m"
  29. static DeviceInfo sg_devInfo;
  30. static Timer sg_reportTimer;
  31. static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF;
  32. static bool sg_control_msg_arrived = false;
  33. static char sg_data_report_buffer[2048];
  34. size_t sg_data_report_buffersize = sizeof(sg_data_report_buffer) / sizeof(sg_data_report_buffer[0]);
  35. /*data_config.c can be generated by tools/codegen.py -c xx/product.json*/
  36. /*-----------------data config start -------------------*/
  37. #define TOTAL_PROPERTY_COUNT 4
  38. #define MAX_STR_NAME_LEN (64)
  39. static sDataPoint sg_DataTemplate[TOTAL_PROPERTY_COUNT];
  40. typedef enum {
  41. eCOLOR_RED = 0,
  42. eCOLOR_GREEN = 1,
  43. eCOLOR_BLUE = 2,
  44. } eColor;
  45. typedef struct _ProductDataDefine {
  46. TYPE_DEF_TEMPLATE_BOOL m_light_switch;
  47. TYPE_DEF_TEMPLATE_ENUM m_color;
  48. TYPE_DEF_TEMPLATE_INT m_brightness;
  49. TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN + 1];
  50. } ProductDataDefine;
  51. static ProductDataDefine sg_ProductData;
  52. static void _init_data_template(void)
  53. {
  54. memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
  55. sg_ProductData.m_light_switch = 0;
  56. sg_DataTemplate[0].data_property.key = "power_switch";
  57. sg_DataTemplate[0].data_property.data = &sg_ProductData.m_light_switch;
  58. sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_BOOL;
  59. sg_ProductData.m_color = eCOLOR_RED;
  60. sg_DataTemplate[1].data_property.key = "color";
  61. sg_DataTemplate[1].data_property.data = &sg_ProductData.m_color;
  62. sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_ENUM;
  63. sg_ProductData.m_brightness = 0;
  64. sg_DataTemplate[2].data_property.key = "brightness";
  65. sg_DataTemplate[2].data_property.data = &sg_ProductData.m_brightness;
  66. sg_DataTemplate[2].data_property.type = TYPE_TEMPLATE_INT;
  67. strncpy(sg_ProductData.m_name, sg_devInfo.device_name, MAX_STR_NAME_LEN);
  68. sg_ProductData.m_name[strlen(sg_devInfo.device_name)] = '\0';
  69. sg_DataTemplate[3].data_property.key = "name";
  70. sg_DataTemplate[3].data_property.data = sg_ProductData.m_name;
  71. sg_DataTemplate[3].data_property.data_buff_len = MAX_STR_NAME_LEN;
  72. sg_DataTemplate[3].data_property.type = TYPE_TEMPLATE_STRING;
  73. };
  74. /*-----------------data config end -------------------*/
  75. /*event_config.c can be generated by tools/codegen.py -c xx/product.json*/
  76. /*-----------------event config start -------------------*/
  77. #ifdef EVENT_POST_ENABLED
  78. #define EVENT_COUNTS (3)
  79. #define MAX_EVENT_STR_MESSAGE_LEN (64)
  80. #define MAX_EVENT_STR_NAME_LEN (64)
  81. static TYPE_DEF_TEMPLATE_BOOL sg_status;
  82. static TYPE_DEF_TEMPLATE_STRING sg_message[MAX_EVENT_STR_MESSAGE_LEN + 1];
  83. static DeviceProperty g_propertyEvent_status_report[] = {
  84. {.key = "status", .data = &sg_status, .type = TYPE_TEMPLATE_BOOL},
  85. {.key = "message", .data = sg_message, .type = TYPE_TEMPLATE_STRING},
  86. };
  87. static TYPE_DEF_TEMPLATE_FLOAT sg_voltage;
  88. static DeviceProperty g_propertyEvent_low_voltage[] = {
  89. {.key = "voltage", .data = &sg_voltage, .type = TYPE_TEMPLATE_FLOAT},
  90. };
  91. static TYPE_DEF_TEMPLATE_STRING sg_name[MAX_EVENT_STR_NAME_LEN + 1];
  92. static TYPE_DEF_TEMPLATE_INT sg_error_code;
  93. static DeviceProperty g_propertyEvent_hardware_fault[] = {
  94. {.key = "name", .data = sg_name, .type = TYPE_TEMPLATE_STRING},
  95. {.key = "error_code", .data = &sg_error_code, .type = TYPE_TEMPLATE_INT},
  96. };
  97. static sEvent g_events[] = {
  98. {
  99. .event_name = "status_report",
  100. .type = "info",
  101. .timestamp = 0,
  102. .eventDataNum = sizeof(g_propertyEvent_status_report) / sizeof(g_propertyEvent_status_report[0]),
  103. .pEventData = g_propertyEvent_status_report,
  104. },
  105. {
  106. .event_name = "low_voltage",
  107. .type = "alert",
  108. .timestamp = 0,
  109. .eventDataNum = sizeof(g_propertyEvent_low_voltage) / sizeof(g_propertyEvent_low_voltage[0]),
  110. .pEventData = g_propertyEvent_low_voltage,
  111. },
  112. {
  113. .event_name = "hardware_fault",
  114. .type = "fault",
  115. .timestamp = 0,
  116. .eventDataNum = sizeof(g_propertyEvent_hardware_fault) / sizeof(g_propertyEvent_hardware_fault[0]),
  117. .pEventData = g_propertyEvent_hardware_fault,
  118. },
  119. };
  120. /*-----------------event config end -------------------*/
  121. static void update_events_timestamp(sEvent *pEvents, int count)
  122. {
  123. int i;
  124. for (i = 0; i < count; i++) {
  125. if (NULL == (&pEvents[i])) {
  126. Log_e("null event pointer");
  127. return;
  128. }
  129. #ifdef EVENT_TIMESTAMP_USED
  130. pEvents[i].timestamp = HAL_Timer_current_sec(); // should be UTC and
  131. // accurate
  132. #else
  133. pEvents[i].timestamp = 0;
  134. #endif
  135. }
  136. }
  137. static void event_post_cb(void *pClient, MQTTMessage *msg)
  138. {
  139. Log_d("recv event reply, clear event");
  140. IOT_Event_clearFlag(pClient, FLAG_EVENT0);
  141. }
  142. // event check and post
  143. static void eventPostCheck(void *client)
  144. {
  145. int i;
  146. int rc;
  147. uint32_t eflag;
  148. uint8_t EventCont;
  149. sEvent * pEventList[EVENT_COUNTS];
  150. eflag = IOT_Event_getFlag(client);
  151. if ((EVENT_COUNTS > 0) && (eflag > 0)) {
  152. EventCont = 0;
  153. for (i = 0; i < EVENT_COUNTS; i++) {
  154. if ((eflag & (1 << i)) & ALL_EVENTS_MASK) {
  155. pEventList[EventCont++] = &(g_events[i]);
  156. update_events_timestamp(&g_events[i], 1);
  157. }
  158. }
  159. rc = IOT_Post_Event(client, sg_data_report_buffer, sg_data_report_buffersize, EventCont, pEventList,
  160. event_post_cb);
  161. if (rc < 0) {
  162. Log_e("event post failed: %d", rc);
  163. }
  164. }
  165. }
  166. #endif
  167. /*action_config.c can be generated by tools/codegen.py -c xx/product.json*/
  168. /*-----------------action config start -------------------*/
  169. #ifdef ACTION_ENABLED
  170. #define TOTAL_ACTION_COUNTS (1)
  171. static TYPE_DEF_TEMPLATE_INT sg_blink_in_period = 5;
  172. static DeviceProperty g_actionInput_blink[] = {
  173. {.key = "period", .data = &sg_blink_in_period, .type = TYPE_TEMPLATE_INT}};
  174. static TYPE_DEF_TEMPLATE_BOOL sg_blink_out_result = 0;
  175. static DeviceProperty g_actionOutput_blink[] = {
  176. {.key = "result", .data = &sg_blink_out_result, .type = TYPE_TEMPLATE_BOOL},
  177. };
  178. static DeviceAction g_actions[] = {
  179. {
  180. .pActionId = "blink",
  181. .timestamp = 0,
  182. .input_num = sizeof(g_actionInput_blink) / sizeof(g_actionInput_blink[0]),
  183. .output_num = sizeof(g_actionOutput_blink) / sizeof(g_actionOutput_blink[0]),
  184. .pInput = g_actionInput_blink,
  185. .pOutput = g_actionOutput_blink,
  186. },
  187. };
  188. /*-----------------action config end -------------------*/
  189. static void OnActionCallback(void *pClient, const char *pClientToken, DeviceAction *pAction)
  190. {
  191. int i;
  192. sReplyPara replyPara;
  193. // control light blink
  194. int period = 0;
  195. DeviceProperty *pActionInput = pAction->pInput;
  196. for (i = 0; i < pAction->input_num; i++) {
  197. if (!strcmp(pActionInput[i].key, "period")) {
  198. period = *((int *)pActionInput[i].data);
  199. } else {
  200. Log_e("no such input[%s]!", pActionInput[i].key);
  201. }
  202. }
  203. // do blink
  204. HAL_Printf("%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_RED);
  205. HAL_SleepMs(period * 1000);
  206. HAL_Printf("\r%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_GREEN);
  207. HAL_SleepMs(period * 1000);
  208. HAL_Printf("\r%s[lighting blink][****]\n" ANSI_COLOR_RESET, ANSI_COLOR_RED);
  209. // construct output
  210. memset((char *)&replyPara, 0, sizeof(sReplyPara));
  211. replyPara.code = eDEAL_SUCCESS;
  212. replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  213. strcpy(replyPara.status_msg,
  214. "action execute success!"); // add the message about the action resault
  215. DeviceProperty *pActionOutnput = pAction->pOutput;
  216. *(int *)(pActionOutnput[0].data) = 0; // set result
  217. IOT_ACTION_REPLY(pClient, pClientToken, sg_data_report_buffer, sg_data_report_buffersize, pAction, &replyPara);
  218. }
  219. static int _register_data_template_action(void *pTemplate_client)
  220. {
  221. int i, rc;
  222. for (i = 0; i < TOTAL_ACTION_COUNTS; i++) {
  223. rc = IOT_Template_Register_Action(pTemplate_client, &g_actions[i], OnActionCallback);
  224. if (rc != QCLOUD_RET_SUCCESS) {
  225. rc = IOT_Template_Destroy(pTemplate_client);
  226. Log_e("register device data template action failed, err: %d", rc);
  227. return rc;
  228. } else {
  229. Log_i("data template action=%s registered.", g_actions[i].pActionId);
  230. }
  231. }
  232. return QCLOUD_RET_SUCCESS;
  233. }
  234. #endif
  235. static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
  236. {
  237. uintptr_t packet_id = (uintptr_t)msg->msg;
  238. switch (msg->event_type) {
  239. case MQTT_EVENT_UNDEF:
  240. Log_i("undefined event occur.");
  241. break;
  242. case MQTT_EVENT_DISCONNECT:
  243. Log_i("MQTT disconnect.");
  244. break;
  245. case MQTT_EVENT_RECONNECT:
  246. Log_i("MQTT reconnect.");
  247. break;
  248. case MQTT_EVENT_SUBCRIBE_SUCCESS:
  249. sg_subscribe_event_result = msg->event_type;
  250. Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id);
  251. break;
  252. case MQTT_EVENT_SUBCRIBE_TIMEOUT:
  253. sg_subscribe_event_result = msg->event_type;
  254. Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id);
  255. break;
  256. case MQTT_EVENT_SUBCRIBE_NACK:
  257. sg_subscribe_event_result = msg->event_type;
  258. Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id);
  259. break;
  260. case MQTT_EVENT_PUBLISH_SUCCESS:
  261. Log_i("publish success, packet-id=%u", (unsigned int)packet_id);
  262. break;
  263. case MQTT_EVENT_PUBLISH_TIMEOUT:
  264. Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id);
  265. break;
  266. case MQTT_EVENT_PUBLISH_NACK:
  267. Log_i("publish nack, packet-id=%u", (unsigned int)packet_id);
  268. break;
  269. default:
  270. Log_i("Should NOT arrive here.");
  271. break;
  272. }
  273. }
  274. /*add user init code, like sensor init*/
  275. static void _usr_init(void)
  276. {
  277. Log_d("add your init code here");
  278. }
  279. /*control msg from server will trigger this callback*/
  280. static void OnControlMsgCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength,
  281. DeviceProperty *pProperty)
  282. {
  283. int i = 0;
  284. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  285. /* handle self defined string/json here. Other properties are dealed in
  286. * _handle_delta()*/
  287. if (strcmp(sg_DataTemplate[i].data_property.key, pProperty->key) == 0) {
  288. sg_DataTemplate[i].state = eCHANGED;
  289. Log_i("Property=%s changed", pProperty->key);
  290. sg_control_msg_arrived = true;
  291. return;
  292. }
  293. }
  294. Log_e("Property=%s changed no match", pProperty->key);
  295. }
  296. static void OnReportReplyCallback(void *pClient, Method method, ReplyAck replyAck, const char *pJsonDocument,
  297. void *pUserdata)
  298. {
  299. Log_i("recv report_reply(ack=%d): %s", replyAck, pJsonDocument);
  300. }
  301. // register data template properties
  302. static int _register_data_template_property(void *pTemplate_client)
  303. {
  304. int i, rc;
  305. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  306. rc = IOT_Template_Register_Property(pTemplate_client, &sg_DataTemplate[i].data_property, OnControlMsgCallback);
  307. if (rc != QCLOUD_RET_SUCCESS) {
  308. rc = IOT_Template_Destroy(pTemplate_client);
  309. Log_e("register device data template property failed, err: %d", rc);
  310. return rc;
  311. } else {
  312. Log_i("data template property=%s registered.", sg_DataTemplate[i].data_property.key);
  313. }
  314. }
  315. return QCLOUD_RET_SUCCESS;
  316. }
  317. /*get property state, changed or not*/
  318. static eDataState get_property_state(void *pProperyData)
  319. {
  320. int i;
  321. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  322. if (sg_DataTemplate[i].data_property.data == pProperyData) {
  323. return sg_DataTemplate[i].state;
  324. }
  325. }
  326. Log_e("no property matched");
  327. return eNOCHANGE;
  328. }
  329. /*set property state, changed or no change*/
  330. static void set_propery_state(void *pProperyData, eDataState state)
  331. {
  332. int i;
  333. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  334. if (sg_DataTemplate[i].data_property.data == pProperyData) {
  335. sg_DataTemplate[i].state = state;
  336. break;
  337. }
  338. }
  339. }
  340. /* demo for light logic deal */
  341. static void deal_down_stream_user_logic(void *client, ProductDataDefine *light)
  342. {
  343. int i;
  344. const char *ansi_color = NULL;
  345. const char *ansi_color_name = NULL;
  346. char brightness_bar[] = "||||||||||||||||||||";
  347. int brightness_bar_len = strlen(brightness_bar);
  348. /* light color */
  349. switch (light->m_color) {
  350. case eCOLOR_RED:
  351. ansi_color = ANSI_COLOR_RED;
  352. ansi_color_name = " RED ";
  353. break;
  354. case eCOLOR_GREEN:
  355. ansi_color = ANSI_COLOR_GREEN;
  356. ansi_color_name = "GREEN";
  357. break;
  358. case eCOLOR_BLUE:
  359. ansi_color = ANSI_COLOR_BLUE;
  360. ansi_color_name = " BLUE";
  361. break;
  362. default:
  363. ansi_color = ANSI_COLOR_YELLOW;
  364. ansi_color_name = "UNKNOWN";
  365. break;
  366. }
  367. /* light brightness bar */
  368. brightness_bar_len =
  369. (light->m_brightness >= 100) ? brightness_bar_len : (int)((light->m_brightness * brightness_bar_len) / 100);
  370. for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
  371. brightness_bar[i] = '-';
  372. }
  373. if (light->m_light_switch) {
  374. /* light is on , show with the properties*/
  375. HAL_Printf("%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET, ansi_color, ansi_color_name,
  376. brightness_bar, light->m_name);
  377. } else {
  378. /* light is off */
  379. HAL_Printf(ANSI_COLOR_YELLOW "[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,
  380. ansi_color_name, brightness_bar, light->m_name);
  381. }
  382. if (eCHANGED == get_property_state(&light->m_light_switch)) {
  383. #ifdef EVENT_POST_ENABLED
  384. if (light->m_light_switch) {
  385. *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 1;
  386. memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
  387. strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light on");
  388. } else {
  389. *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
  390. memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
  391. strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light off");
  392. }
  393. // switch state changed set EVENT0 flag, the events will be posted by
  394. // eventPostCheck
  395. IOT_Event_setFlag(client, FLAG_EVENT0);
  396. #else
  397. Log_d("light switch state changed");
  398. #endif
  399. }
  400. }
  401. /*example for cycle report, you can delete this for your needs*/
  402. static void cycle_report(Timer *reportTimer)
  403. {
  404. int i;
  405. if (expired(reportTimer)) {
  406. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  407. set_propery_state(sg_DataTemplate[i].data_property.data, eCHANGED);
  408. countdown_ms(reportTimer, 5000);
  409. }
  410. }
  411. }
  412. /*get local property data, like sensor data*/
  413. static void _refresh_local_property(void)
  414. {
  415. // add your local property refresh logic, cycle report for example
  416. cycle_report(&sg_reportTimer);
  417. }
  418. static int find_wait_report_property(DeviceProperty *pReportDataList[])
  419. {
  420. int i, j;
  421. for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  422. if (eCHANGED == sg_DataTemplate[i].state) {
  423. pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
  424. sg_DataTemplate[i].state = eNOCHANGE;
  425. }
  426. }
  427. return j;
  428. }
  429. /* demo for up-stream code */
  430. static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
  431. {
  432. // refresh local property
  433. _refresh_local_property();
  434. /*find propery need report*/
  435. *pCount = find_wait_report_property(pReportDataList);
  436. return (*pCount > 0) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE;
  437. }
  438. /*You should get the real info for your device, here just for example*/
  439. static int _get_sys_info(void *handle, char *pJsonDoc, size_t sizeOfBuffer)
  440. {
  441. /*platform info has at least one of module_hardinfo/module_softinfo/fw_ver
  442. * property*/
  443. DeviceProperty plat_info[] = {
  444. {.key = "module_hardinfo", .type = TYPE_TEMPLATE_STRING, .data = "ESP8266"},
  445. {.key = "module_softinfo", .type = TYPE_TEMPLATE_STRING, .data = "V1.0"},
  446. {.key = "fw_ver", .type = TYPE_TEMPLATE_STRING, .data = QCLOUD_IOT_DEVICE_SDK_VERSION},
  447. {.key = "imei", .type = TYPE_TEMPLATE_STRING, .data = "11-22-33-44"},
  448. {.key = "lat", .type = TYPE_TEMPLATE_STRING, .data = "22.546015"},
  449. {.key = "lon", .type = TYPE_TEMPLATE_STRING, .data = "113.941125"},
  450. {NULL, NULL, 0} // end
  451. };
  452. /*self define info*/
  453. DeviceProperty self_info[] = {
  454. {.key = "append_info", .type = TYPE_TEMPLATE_STRING, .data = "your self define info"}, {NULL, NULL, 0} // end
  455. };
  456. return IOT_Template_JSON_ConstructSysInfo(handle, pJsonDoc, sizeOfBuffer, plat_info, self_info);
  457. }
  458. void *sub_dev1_thread(void *user_arg, char *product_id, char *device_name)
  459. {
  460. DeviceProperty *pReportDataList[TOTAL_PROPERTY_COUNT];
  461. sReplyPara replyPara;
  462. int ReportCont;
  463. int rc;
  464. void * pGateWayClient = user_arg;
  465. Log_d("sub_dev1_thread ...");
  466. // init connection
  467. TemplateInitParams init_params = DEFAULT_TEMPLATE_INIT_PARAMS;
  468. init_params.product_id = product_id;
  469. init_params.device_name = device_name;
  470. init_params.event_handle.h_fp = event_handler;
  471. void *client = IOT_Template_Construct(&init_params, IOT_Gateway_Get_Mqtt_Client(pGateWayClient));
  472. if (client != NULL) {
  473. Log_i("Cloud Device Construct Success");
  474. } else {
  475. Log_e("Cloud Device Construct Failed");
  476. return NULL;
  477. }
  478. #ifdef MULTITHREAD_ENABLED
  479. /*only gateway yield thread read mqtt packet*/
  480. int code;
  481. bool state = IOT_Gateway_Get_Yield_Status(pGateWayClient, &code);
  482. IOT_Template_Set_Yield_Status(client, state, code);
  483. #endif
  484. // usr init
  485. _usr_init();
  486. // init data template
  487. _init_data_template();
  488. // register data template propertys here
  489. rc = _register_data_template_property(client);
  490. if (rc == QCLOUD_RET_SUCCESS) {
  491. Log_i("Register data template propertys Success");
  492. } else {
  493. Log_e("Register data template propertys Failed: %d", rc);
  494. return NULL;
  495. }
  496. // register data template actions here
  497. #ifdef ACTION_ENABLED
  498. rc = _register_data_template_action(client);
  499. if (rc == QCLOUD_RET_SUCCESS) {
  500. Log_i("Register data template actions Success");
  501. } else {
  502. Log_e("Register data template actions Failed: %d", rc);
  503. return NULL;
  504. }
  505. #endif
  506. HAL_SleepMs(1000); // wait subcrible ack
  507. // report device info, then you can manager your product by these info, like
  508. // position
  509. rc = _get_sys_info(client, sg_data_report_buffer, sg_data_report_buffersize);
  510. if (QCLOUD_RET_SUCCESS == rc) {
  511. rc = IOT_Template_Report_SysInfo_Sync(client, sg_data_report_buffer, sg_data_report_buffersize,
  512. QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  513. if (rc != QCLOUD_RET_SUCCESS) {
  514. Log_e("Report system info fail, err: %d", rc);
  515. return NULL;
  516. }
  517. } else {
  518. Log_e("Get system info fail, err: %d", rc);
  519. }
  520. // get the property changed during offline
  521. rc = IOT_Template_GetStatus_sync(client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  522. if (rc != QCLOUD_RET_SUCCESS) {
  523. Log_e("Get data status fail, err: %d", rc);
  524. return NULL;
  525. } else {
  526. Log_d("Get data status success");
  527. }
  528. // init a timer for cycle report, you could delete it or not for your needs
  529. InitTimer(&sg_reportTimer);
  530. while (IOT_Template_IsConnected(client) || QCLOUD_RET_SUCCESS == rc) {
  531. rc = IOT_Template_Yield(client, 200);
  532. if (QCLOUD_RET_SUCCESS != rc) {
  533. Log_d("Template Yield without mqtt err, rc:%d", rc);
  534. }
  535. /* handle control msg from server */
  536. if (sg_control_msg_arrived) {
  537. deal_down_stream_user_logic(client, &sg_ProductData);
  538. /* control msg should reply, otherwise server treat device didn't receive
  539. * and retain the msg which would be get by get status*/
  540. memset((char *)&replyPara, 0, sizeof(sReplyPara));
  541. replyPara.code = eDEAL_SUCCESS;
  542. replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  543. replyPara.status_msg[0] = '\0'; // add extra info to replyPara.status_msg when error occured
  544. rc = IOT_Template_ControlReply(client, sg_data_report_buffer, sg_data_report_buffersize, &replyPara);
  545. if (rc == QCLOUD_RET_SUCCESS) {
  546. Log_d("Contol msg reply success");
  547. sg_control_msg_arrived = false;
  548. } else {
  549. Log_e("Contol msg reply failed, err: %d", rc);
  550. }
  551. }
  552. /*report msg to server*/
  553. /*report the lastest properties's status*/
  554. if (QCLOUD_RET_SUCCESS == deal_up_stream_user_logic(pReportDataList, &ReportCont)) {
  555. rc = IOT_Template_JSON_ConstructReportArray(client, sg_data_report_buffer, sg_data_report_buffersize,
  556. ReportCont, pReportDataList);
  557. if (rc == QCLOUD_RET_SUCCESS) {
  558. rc = IOT_Template_Report(client, sg_data_report_buffer, sg_data_report_buffersize,
  559. OnReportReplyCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  560. if (rc == QCLOUD_RET_SUCCESS) {
  561. Log_i("data template reporte success");
  562. } else {
  563. Log_e("data template reporte failed, err: %d", rc);
  564. }
  565. } else {
  566. Log_e("construct reporte data failed, err: %d", rc);
  567. }
  568. }
  569. #ifdef EVENT_POST_ENABLED
  570. eventPostCheck(client);
  571. #endif
  572. HAL_SleepMs(1000);
  573. }
  574. #ifdef MULTITHREAD_ENABLED
  575. rc = IOT_Template_Destroy_Except_MQTT(client);
  576. #endif
  577. return NULL;
  578. }