light_data_template_sample.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  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 <stdio.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include "ql_api_osi.h"
  22. #include "ql_api_datacall.h"
  23. #include "lite-utils.h"
  24. #include "qcloud_iot_export.h"
  25. #include "qcloud_iot_import.h"
  26. #include "utils_timer.h"
  27. #define PROFILE_IDX 1
  28. #ifdef AUTH_MODE_CERT
  29. static char sg_cert_file[PATH_MAX + 1]; // full path of device cert file
  30. static char sg_key_file[PATH_MAX + 1]; // full path of device key file
  31. #endif
  32. static DeviceInfo sg_devInfo;
  33. static Timer sg_reportTimer;
  34. /* anis color control codes */
  35. #define ANSI_COLOR_RED "\x1b[31m"
  36. #define ANSI_COLOR_GREEN "\x1b[32m"
  37. #define ANSI_COLOR_YELLOW "\x1b[33m"
  38. #define ANSI_COLOR_BLUE "\x1b[34m"
  39. #define ANSI_COLOR_RESET "\x1b[0m"
  40. static MQTTEventType sg_subscribe_event_result = MQTT_EVENT_UNDEF;
  41. static bool sg_control_msg_arrived = false;
  42. static char sg_data_report_buffer[2048];
  43. static size_t sg_data_report_buffersize = sizeof(sg_data_report_buffer) / sizeof(sg_data_report_buffer[0]);
  44. /*data_config.c can be generated by tools/codegen.py -c xx/product.json*/
  45. /*-----------------data config start -------------------*/
  46. #define TOTAL_PROPERTY_COUNT 4
  47. #define MAX_STR_NAME_LEN (64)
  48. static sDataPoint sg_DataTemplate[TOTAL_PROPERTY_COUNT];
  49. typedef enum {
  50. eCOLOR_RED = 0,
  51. eCOLOR_GREEN = 1,
  52. eCOLOR_BLUE = 2,
  53. } eColor;
  54. typedef struct _ProductDataDefine {
  55. TYPE_DEF_TEMPLATE_BOOL m_light_switch;
  56. TYPE_DEF_TEMPLATE_ENUM m_color;
  57. TYPE_DEF_TEMPLATE_INT m_brightness;
  58. TYPE_DEF_TEMPLATE_STRING m_name[MAX_STR_NAME_LEN + 1];
  59. } ProductDataDefine;
  60. static ProductDataDefine sg_ProductData;
  61. static void _init_data_template(void)
  62. {
  63. memset((void *)&sg_ProductData, 0, sizeof(ProductDataDefine));
  64. sg_ProductData.m_light_switch = 0;
  65. sg_DataTemplate[0].data_property.key = "power_switch";
  66. sg_DataTemplate[0].data_property.data = &sg_ProductData.m_light_switch;
  67. sg_DataTemplate[0].data_property.type = TYPE_TEMPLATE_BOOL;
  68. sg_ProductData.m_color = eCOLOR_RED;
  69. sg_DataTemplate[1].data_property.key = "color";
  70. sg_DataTemplate[1].data_property.data = &sg_ProductData.m_color;
  71. sg_DataTemplate[1].data_property.type = TYPE_TEMPLATE_ENUM;
  72. sg_ProductData.m_brightness = 0;
  73. sg_DataTemplate[2].data_property.key = "brightness";
  74. sg_DataTemplate[2].data_property.data = &sg_ProductData.m_brightness;
  75. sg_DataTemplate[2].data_property.type = TYPE_TEMPLATE_INT;
  76. strncpy(sg_ProductData.m_name, sg_devInfo.device_name, MAX_STR_NAME_LEN);
  77. sg_ProductData.m_name[strlen(sg_devInfo.device_name)] = '\0';
  78. sg_DataTemplate[3].data_property.key = "name";
  79. sg_DataTemplate[3].data_property.data = sg_ProductData.m_name;
  80. sg_DataTemplate[3].data_property.data_buff_len = MAX_STR_NAME_LEN;
  81. sg_DataTemplate[3].data_property.type = TYPE_TEMPLATE_STRING;
  82. };
  83. /*-----------------data config end -------------------*/
  84. /*event_config.c can be generated by tools/codegen.py -c xx/product.json*/
  85. /*-----------------event config start -------------------*/
  86. #ifdef EVENT_POST_ENABLED
  87. #define EVENT_COUNTS (3)
  88. #define MAX_EVENT_STR_MESSAGE_LEN (64)
  89. #define MAX_EVENT_STR_NAME_LEN (64)
  90. static TYPE_DEF_TEMPLATE_BOOL sg_status;
  91. static TYPE_DEF_TEMPLATE_STRING sg_message[MAX_EVENT_STR_MESSAGE_LEN + 1];
  92. static DeviceProperty g_propertyEvent_status_report[] = {
  93. {.key = "status", .data = &sg_status, .type = TYPE_TEMPLATE_BOOL},
  94. {.key = "message", .data = sg_message, .type = TYPE_TEMPLATE_STRING},
  95. };
  96. static TYPE_DEF_TEMPLATE_FLOAT sg_voltage;
  97. static DeviceProperty g_propertyEvent_low_voltage[] = {
  98. {.key = "voltage", .data = &sg_voltage, .type = TYPE_TEMPLATE_FLOAT},
  99. };
  100. static TYPE_DEF_TEMPLATE_STRING sg_name[MAX_EVENT_STR_NAME_LEN + 1];
  101. static TYPE_DEF_TEMPLATE_INT sg_error_code;
  102. static DeviceProperty g_propertyEvent_hardware_fault[] = {
  103. {.key = "name", .data = sg_name, .type = TYPE_TEMPLATE_STRING},
  104. {.key = "error_code", .data = &sg_error_code, .type = TYPE_TEMPLATE_INT},
  105. };
  106. static sEvent g_events[] = {
  107. {
  108. .event_name = "status_report",
  109. .type = "info",
  110. .timestamp = 0,
  111. .eventDataNum = sizeof(g_propertyEvent_status_report) / sizeof(g_propertyEvent_status_report[0]),
  112. .pEventData = g_propertyEvent_status_report,
  113. },
  114. {
  115. .event_name = "low_voltage",
  116. .type = "alert",
  117. .timestamp = 0,
  118. .eventDataNum = sizeof(g_propertyEvent_low_voltage) / sizeof(g_propertyEvent_low_voltage[0]),
  119. .pEventData = g_propertyEvent_low_voltage,
  120. },
  121. {
  122. .event_name = "hardware_fault",
  123. .type = "fault",
  124. .timestamp = 0,
  125. .eventDataNum = sizeof(g_propertyEvent_hardware_fault) / sizeof(g_propertyEvent_hardware_fault[0]),
  126. .pEventData = g_propertyEvent_hardware_fault,
  127. },
  128. };
  129. /*-----------------event config end -------------------*/
  130. static void update_events_timestamp(sEvent *pEvents, int count)
  131. {
  132. int i;
  133. for (i = 0; i < count; i++) {
  134. if (NULL == (&pEvents[i])) {
  135. Log_e("null event pointer");
  136. return;
  137. }
  138. #ifdef EVENT_TIMESTAMP_USED
  139. pEvents[i].timestamp = HAL_Timer_current_sec(); // should be UTC and
  140. // accurate
  141. #else
  142. pEvents[i].timestamp = 0;
  143. #endif
  144. }
  145. }
  146. static void event_post_cb(void *pClient, MQTTMessage *msg)
  147. {
  148. Log_d("recv event reply, clear event");
  149. // IOT_Event_clearFlag(pClient, FLAG_EVENT0);
  150. }
  151. // event check and post
  152. static void eventPostCheck(void *client)
  153. {
  154. int i;
  155. int rc;
  156. uint32_t eflag;
  157. uint8_t EventCont;
  158. sEvent * pEventList[EVENT_COUNTS];
  159. eflag = IOT_Event_getFlag(client);
  160. if ((EVENT_COUNTS > 0) && (eflag > 0)) {
  161. EventCont = 0;
  162. for (i = 0; i < EVENT_COUNTS; i++) {
  163. if ((eflag & (1 << i)) & ALL_EVENTS_MASK) {
  164. pEventList[EventCont++] = &(g_events[i]);
  165. update_events_timestamp(&g_events[i], 1);
  166. IOT_Event_clearFlag(client, (1 << i) & ALL_EVENTS_MASK);
  167. }
  168. }
  169. rc = IOT_Post_Event(client, sg_data_report_buffer, sg_data_report_buffersize, EventCont, pEventList,
  170. event_post_cb);
  171. if (rc < 0) {
  172. Log_e("event post failed: %d", rc);
  173. }
  174. }
  175. }
  176. #endif
  177. /*action_config.c can be generated by tools/codegen.py -c xx/product.json*/
  178. /*-----------------action config start -------------------*/
  179. #ifdef ACTION_ENABLED
  180. #define TOTAL_ACTION_COUNTS (1)
  181. static TYPE_DEF_TEMPLATE_INT sg_blink_in_period = 5;
  182. static DeviceProperty g_actionInput_blink[] = {
  183. {.key = "period", .data = &sg_blink_in_period, .type = TYPE_TEMPLATE_INT}};
  184. static TYPE_DEF_TEMPLATE_BOOL sg_blink_out_result = 0;
  185. static DeviceProperty g_actionOutput_blink[] = {
  186. {.key = "result", .data = &sg_blink_out_result, .type = TYPE_TEMPLATE_BOOL},
  187. };
  188. static DeviceAction g_actions[] = {
  189. {
  190. .pActionId = "blink",
  191. .timestamp = 0,
  192. .input_num = sizeof(g_actionInput_blink) / sizeof(g_actionInput_blink[0]),
  193. .output_num = sizeof(g_actionOutput_blink) / sizeof(g_actionOutput_blink[0]),
  194. .pInput = g_actionInput_blink,
  195. .pOutput = g_actionOutput_blink,
  196. },
  197. };
  198. /*-----------------action config end -------------------*/
  199. static void OnActionCallback(void *pClient, const char *pClientToken, DeviceAction *pAction)
  200. {
  201. int i;
  202. sReplyPara replyPara;
  203. // control light blink
  204. int period = 0;
  205. DeviceProperty *pActionInput = pAction->pInput;
  206. for (i = 0; i < pAction->input_num; i++) {
  207. if (!strcmp(pActionInput[i].key, "period")) {
  208. period = *((int *)pActionInput[i].data);
  209. } else {
  210. Log_e("no such input[%s]!", pActionInput[i].key);
  211. }
  212. }
  213. // do blink
  214. HAL_Printf("%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_RED);
  215. HAL_SleepMs(period * 1000);
  216. HAL_Printf("\r%s[lighting blink][****]" ANSI_COLOR_RESET, ANSI_COLOR_GREEN);
  217. HAL_SleepMs(period * 1000);
  218. HAL_Printf("\r%s[lighting blink][****]\n" ANSI_COLOR_RESET, ANSI_COLOR_RED);
  219. // construct output
  220. memset((char *)&replyPara, 0, sizeof(sReplyPara));
  221. replyPara.code = eDEAL_SUCCESS;
  222. replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  223. strcpy(replyPara.status_msg,
  224. "action execute success!"); // add the message about the action resault
  225. DeviceProperty *pActionOutnput = pAction->pOutput;
  226. *(int *)(pActionOutnput[0].data) = 0; // set result
  227. IOT_ACTION_REPLY(pClient, pClientToken, sg_data_report_buffer, sg_data_report_buffersize, pAction, &replyPara);
  228. }
  229. static int _register_data_template_action(void *pTemplate_client)
  230. {
  231. int i, rc;
  232. for (i = 0; i < TOTAL_ACTION_COUNTS; i++) {
  233. rc = IOT_Template_Register_Action(pTemplate_client, &g_actions[i], OnActionCallback);
  234. if (rc != QCLOUD_RET_SUCCESS) {
  235. rc = IOT_Template_Destroy(pTemplate_client);
  236. Log_e("register device data template action failed, err: %d", rc);
  237. return rc;
  238. } else {
  239. Log_i("data template action=%s registered.", g_actions[i].pActionId);
  240. }
  241. }
  242. return QCLOUD_RET_SUCCESS;
  243. }
  244. #endif
  245. static void event_handler(void *pclient, void *handle_context, MQTTEventMsg *msg)
  246. {
  247. uintptr_t packet_id = (uintptr_t)msg->msg;
  248. switch (msg->event_type) {
  249. case MQTT_EVENT_UNDEF:
  250. Log_i("undefined event occur.");
  251. break;
  252. case MQTT_EVENT_DISCONNECT:
  253. Log_i("MQTT disconnect.");
  254. break;
  255. case MQTT_EVENT_RECONNECT:
  256. Log_i("MQTT reconnect.");
  257. break;
  258. case MQTT_EVENT_SUBCRIBE_SUCCESS:
  259. sg_subscribe_event_result = msg->event_type;
  260. Log_i("subscribe success, packet-id=%u", (unsigned int)packet_id);
  261. break;
  262. case MQTT_EVENT_SUBCRIBE_TIMEOUT:
  263. sg_subscribe_event_result = msg->event_type;
  264. Log_i("subscribe wait ack timeout, packet-id=%u", (unsigned int)packet_id);
  265. break;
  266. case MQTT_EVENT_SUBCRIBE_NACK:
  267. sg_subscribe_event_result = msg->event_type;
  268. Log_i("subscribe nack, packet-id=%u", (unsigned int)packet_id);
  269. break;
  270. case MQTT_EVENT_PUBLISH_SUCCESS:
  271. Log_i("publish success, packet-id=%u", (unsigned int)packet_id);
  272. break;
  273. case MQTT_EVENT_PUBLISH_TIMEOUT:
  274. Log_i("publish timeout, packet-id=%u", (unsigned int)packet_id);
  275. break;
  276. case MQTT_EVENT_PUBLISH_NACK:
  277. Log_i("publish nack, packet-id=%u", (unsigned int)packet_id);
  278. break;
  279. default:
  280. Log_i("Should NOT arrive here.");
  281. break;
  282. }
  283. }
  284. /*add user init code, like sensor init*/
  285. static void _usr_init(void)
  286. {
  287. Log_d("add your init code here");
  288. }
  289. // Setup MQTT construct parameters
  290. static int _setup_connect_init_params(TemplateInitParams *initParams)
  291. {
  292. int ret;
  293. ret = HAL_GetDevInfo((void *)&sg_devInfo);
  294. if (QCLOUD_RET_SUCCESS != ret) {
  295. return ret;
  296. }
  297. initParams->region = sg_devInfo.region;
  298. initParams->device_name = sg_devInfo.device_name;
  299. initParams->product_id = sg_devInfo.product_id;
  300. #ifdef AUTH_MODE_CERT
  301. /* TLS with certs*/
  302. // char certs_dir[PATH_MAX + 1] = "certs";
  303. // char current_path[PATH_MAX + 1];
  304. // char *cwd = getcwd(current_path, sizeof(current_path));
  305. // if (cwd == NULL) {
  306. // Log_e("getcwd return NULL");
  307. // return QCLOUD_ERR_FAILURE;
  308. // }
  309. // sprintf(sg_cert_file, "%s/%s/%s", current_path, certs_dir, sg_devInfo.dev_cert_file_name);
  310. // sprintf(sg_key_file, "%s/%s/%s", current_path, certs_dir, sg_devInfo.dev_key_file_name);
  311. sprintf(sg_cert_file, "%s", sg_devInfo.dev_cert_file_name);
  312. sprintf(sg_key_file, "%s", sg_devInfo.dev_key_file_name);
  313. Log_i("sg_cert_file:%s",sg_cert_file);
  314. Log_i("sg_key_file:%s",sg_key_file);
  315. initParams->cert_file = sg_cert_file;
  316. initParams->key_file = sg_key_file;
  317. #else
  318. initParams->device_secret = sg_devInfo.device_secret;
  319. #endif
  320. initParams->command_timeout = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  321. initParams->keep_alive_interval_ms = QCLOUD_IOT_MQTT_KEEP_ALIVE_INTERNAL;
  322. initParams->auto_connect_enable = 1;
  323. initParams->event_handle.h_fp = event_handler;
  324. return QCLOUD_RET_SUCCESS;
  325. }
  326. /*control msg from server will trigger this callback*/
  327. static void OnControlMsgCallback(void *pClient, const char *pJsonValueBuffer, uint32_t valueLength,
  328. DeviceProperty *pProperty)
  329. {
  330. int i = 0;
  331. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  332. /* handle self defined string/json here. Other properties are dealed in
  333. * _handle_delta()*/
  334. if (strcmp(sg_DataTemplate[i].data_property.key, pProperty->key) == 0) {
  335. sg_DataTemplate[i].state = eCHANGED;
  336. Log_i("Property=%s changed", pProperty->key);
  337. sg_control_msg_arrived = true;
  338. return;
  339. }
  340. }
  341. Log_e("Property=%s changed no match", pProperty->key);
  342. }
  343. static void OnReportReplyCallback(void *pClient, Method method, ReplyAck replyAck, const char *pJsonDocument,
  344. void *pUserdata)
  345. {
  346. Log_i("recv report_reply(ack=%d): %s", replyAck, pJsonDocument);
  347. }
  348. // register data template properties
  349. static int _register_data_template_property(void *pTemplate_client)
  350. {
  351. int i, rc;
  352. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  353. rc = IOT_Template_Register_Property(pTemplate_client, &sg_DataTemplate[i].data_property, OnControlMsgCallback);
  354. if (rc != QCLOUD_RET_SUCCESS) {
  355. rc = IOT_Template_Destroy(pTemplate_client);
  356. Log_e("register device data template property failed, err: %d", rc);
  357. return rc;
  358. } else {
  359. Log_i("data template property=%s registered.", sg_DataTemplate[i].data_property.key);
  360. }
  361. }
  362. return QCLOUD_RET_SUCCESS;
  363. }
  364. /*get property state, changed or not*/
  365. static eDataState get_property_state(void *pProperyData)
  366. {
  367. int i;
  368. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  369. if (sg_DataTemplate[i].data_property.data == pProperyData) {
  370. return sg_DataTemplate[i].state;
  371. }
  372. }
  373. Log_e("no property matched");
  374. return eNOCHANGE;
  375. }
  376. /*set property state, changed or no change*/
  377. static void set_property_state(void *pProperyData, eDataState state)
  378. {
  379. int i;
  380. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  381. if (sg_DataTemplate[i].data_property.data == pProperyData) {
  382. sg_DataTemplate[i].state = state;
  383. break;
  384. }
  385. }
  386. }
  387. /* demo for light logic deal */
  388. static void deal_down_stream_user_logic(void *client, ProductDataDefine *light)
  389. {
  390. int i;
  391. const char *ansi_color = NULL;
  392. const char *ansi_color_name = NULL;
  393. char brightness_bar[] = "||||||||||||||||||||";
  394. int brightness_bar_len = strlen(brightness_bar);
  395. /* light color */
  396. switch (light->m_color) {
  397. case eCOLOR_RED:
  398. ansi_color = ANSI_COLOR_RED;
  399. ansi_color_name = " RED ";
  400. break;
  401. case eCOLOR_GREEN:
  402. ansi_color = ANSI_COLOR_GREEN;
  403. ansi_color_name = "GREEN";
  404. break;
  405. case eCOLOR_BLUE:
  406. ansi_color = ANSI_COLOR_BLUE;
  407. ansi_color_name = " BLUE";
  408. break;
  409. default:
  410. ansi_color = ANSI_COLOR_YELLOW;
  411. ansi_color_name = "UNKNOWN";
  412. break;
  413. }
  414. /* light brightness bar */
  415. brightness_bar_len =
  416. (light->m_brightness >= 100) ? brightness_bar_len : (int)((light->m_brightness * brightness_bar_len) / 100);
  417. for (i = brightness_bar_len; i < strlen(brightness_bar); i++) {
  418. brightness_bar[i] = '-';
  419. }
  420. if (light->m_light_switch) {
  421. /* light is on , show with the properties*/
  422. HAL_Printf("%s[ lighting ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET, ansi_color, ansi_color_name,
  423. brightness_bar, light->m_name);
  424. } else {
  425. /* light is off */
  426. HAL_Printf(ANSI_COLOR_YELLOW "[ light is off ]|[color:%s]|[brightness:%s]|[%s]\n" ANSI_COLOR_RESET,
  427. ansi_color_name, brightness_bar, light->m_name);
  428. }
  429. if (eCHANGED == get_property_state(&light->m_light_switch)) {
  430. #ifdef EVENT_POST_ENABLED
  431. if (light->m_light_switch) {
  432. *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
  433. memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
  434. strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light on");
  435. } else {
  436. *(TYPE_DEF_TEMPLATE_BOOL *)g_events[0].pEventData[0].data = 0;
  437. memset((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, 0, MAX_EVENT_STR_MESSAGE_LEN);
  438. strcpy((TYPE_DEF_TEMPLATE_STRING *)g_events[0].pEventData[1].data, "light off");
  439. }
  440. // switch state changed set EVENT0 flag, the events will be posted by
  441. // eventPostCheck
  442. IOT_Event_setFlag(client, FLAG_EVENT0);
  443. #else
  444. Log_d("light switch state changed");
  445. #endif
  446. }
  447. }
  448. /*example for cycle report, you can delete this for your needs*/
  449. static void cycle_report(Timer *reportTimer)
  450. {
  451. int i;
  452. if (expired(reportTimer)) {
  453. for (i = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  454. set_property_state(sg_DataTemplate[i].data_property.data, eCHANGED);
  455. countdown_ms(reportTimer, 5000);
  456. }
  457. }
  458. }
  459. /*get local property data, like sensor data*/
  460. static void _refresh_local_property(void)
  461. {
  462. // add your local property refresh logic, cycle report for example
  463. cycle_report(&sg_reportTimer);
  464. }
  465. /*find propery need report*/
  466. static int find_wait_report_property(DeviceProperty *pReportDataList[])
  467. {
  468. int i, j;
  469. for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
  470. if (eCHANGED == sg_DataTemplate[i].state) {
  471. pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
  472. sg_DataTemplate[i].state = eNOCHANGE;
  473. }
  474. }
  475. return j;
  476. }
  477. /* demo for up-stream code */
  478. static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
  479. {
  480. // refresh local property
  481. _refresh_local_property();
  482. /*find propery need report*/
  483. *pCount = find_wait_report_property(pReportDataList);
  484. return (*pCount > 0) ? QCLOUD_RET_SUCCESS : QCLOUD_ERR_FAILURE;
  485. }
  486. /*You should get the real info for your device, here just for example*/
  487. static int _get_sys_info(void *handle, char *pJsonDoc, size_t sizeOfBuffer)
  488. {
  489. /*platform info has at least one of module_hardinfo/module_softinfo/fw_ver
  490. * property*/
  491. DeviceProperty plat_info[] = {
  492. {.key = "module_hardinfo", .type = TYPE_TEMPLATE_STRING, .data = "ESP8266"},
  493. {.key = "module_softinfo", .type = TYPE_TEMPLATE_STRING, .data = "V1.0"},
  494. {.key = "fw_ver", .type = TYPE_TEMPLATE_STRING, .data = QCLOUD_IOT_DEVICE_SDK_VERSION},
  495. {.key = "imei", .type = TYPE_TEMPLATE_STRING, .data = "11-22-33-44"},
  496. {.key = "lat", .type = TYPE_TEMPLATE_STRING, .data = "22.546015"},
  497. {.key = "lon", .type = TYPE_TEMPLATE_STRING, .data = "113.941125"},
  498. {NULL, NULL, 0} // end
  499. };
  500. /*self define info*/
  501. DeviceProperty self_info[] = {
  502. {.key = "append_info", .type = TYPE_TEMPLATE_STRING, .data = "your self define info"}, {NULL, NULL, 0} // end
  503. };
  504. return IOT_Template_JSON_ConstructSysInfo(handle, pJsonDoc, sizeOfBuffer, plat_info, self_info);
  505. }
  506. static int datacall_satrt(void)
  507. {
  508. int ret = 0;
  509. int i = 0;
  510. ql_data_call_info_s info;
  511. char ip4_addr_str[16] = {0};
  512. uint8_t nSim = 0;
  513. ql_rtos_task_sleep_s(10);
  514. Log_e("wait for network register done");
  515. while ((ret = ql_network_register_wait(nSim, 120)) != 0 && i < 10)
  516. {
  517. i++;
  518. ql_rtos_task_sleep_s(1);
  519. }
  520. if (ret == 0)
  521. {
  522. i = 0;
  523. Log_e("====network registered!!!!====");
  524. }
  525. else
  526. {
  527. Log_e("====network register failure!!!!!====");
  528. goto exit;
  529. }
  530. ql_set_data_call_asyn_mode(nSim, PROFILE_IDX, 0);
  531. Log_e("===start data call====");
  532. ret = ql_start_data_call(nSim, PROFILE_IDX, QL_PDP_TYPE_IP, "uninet", NULL, NULL, 0);
  533. Log_e("===data call result:%d", ret);
  534. if (ret != 0)
  535. {
  536. Log_e("====data call failure!!!!=====");
  537. }
  538. memset(&info, 0x00, sizeof(ql_data_call_info_s));
  539. ret = ql_get_data_call_info(nSim, PROFILE_IDX, &info);
  540. if (ret != 0)
  541. {
  542. Log_e("ql_get_data_call_info ret: %d", ret);
  543. ql_stop_data_call(nSim, PROFILE_IDX);
  544. goto exit;
  545. }
  546. Log_i("info.profile_idx: %d", info.profile_idx);
  547. Log_i("info.ip_version: %d", info.ip_version);
  548. Log_i("info.v4.state: %d", info.v4.state);
  549. //Log_i("info.v4.reconnect: %d", info.v4.reconnect);
  550. inet_ntop(AF_INET, &info.v4.addr.ip, ip4_addr_str, sizeof(ip4_addr_str));
  551. Log_i("info.v4.addr.ip: %s", ip4_addr_str);
  552. inet_ntop(AF_INET, &info.v4.addr.pri_dns, ip4_addr_str, sizeof(ip4_addr_str));
  553. Log_i("info.v4.addr.pri_dns: %s", ip4_addr_str);
  554. inet_ntop(AF_INET, &info.v4.addr.sec_dns, ip4_addr_str, sizeof(ip4_addr_str));
  555. Log_i("info.v4.addr.sec_dns: %s", ip4_addr_str);
  556. return 0;
  557. exit:
  558. return -1;
  559. }
  560. void light_data_template_sample(void *arg)
  561. {
  562. DeviceProperty *pReportDataList[TOTAL_PROPERTY_COUNT];
  563. sReplyPara replyPara;
  564. int ReportCont;
  565. int rc;
  566. void *client=NULL;
  567. // init log level
  568. IOT_Log_Set_Level(eLOG_DEBUG);
  569. /*执行拨号操作,设备联网*/
  570. if(datacall_satrt() != 0)
  571. {
  572. Log_e("Cloud Device datacall Failed");
  573. goto exit;
  574. }
  575. // init connection
  576. TemplateInitParams init_params = DEFAULT_TEMPLATE_INIT_PARAMS;
  577. rc = _setup_connect_init_params(&init_params);
  578. if (rc != QCLOUD_RET_SUCCESS) {
  579. Log_e("init params err,rc=%d", rc);
  580. goto exit;
  581. }
  582. client = IOT_Template_Construct(&init_params, NULL);
  583. if (client != NULL) {
  584. Log_i("Cloud Device Construct Success");
  585. } else {
  586. Log_e("Cloud Device Construct Failed");
  587. goto exit;
  588. }
  589. #ifdef MULTITHREAD_ENABLED
  590. if (QCLOUD_RET_SUCCESS != IOT_Template_Start_Yield_Thread(client)) {
  591. Log_e("start template yield thread fail");
  592. goto exit;
  593. }
  594. #endif
  595. // usr init
  596. _usr_init();
  597. // init data template
  598. _init_data_template();
  599. // register data template propertys here
  600. rc = _register_data_template_property(client);
  601. if (rc == QCLOUD_RET_SUCCESS) {
  602. Log_i("Register data template propertys Success");
  603. } else {
  604. Log_e("Register data template propertys Failed: %d", rc);
  605. goto exit;
  606. }
  607. // register data template actions here
  608. #ifdef ACTION_ENABLED
  609. rc = _register_data_template_action(client);
  610. if (rc == QCLOUD_RET_SUCCESS) {
  611. Log_i("Register data template actions Success");
  612. } else {
  613. Log_e("Register data template actions Failed: %d", rc);
  614. goto exit;
  615. }
  616. #endif
  617. // report device info, then you can manager your product by these info, like
  618. // position
  619. rc = _get_sys_info(client, sg_data_report_buffer, sg_data_report_buffersize);
  620. if (QCLOUD_RET_SUCCESS == rc) {
  621. rc = IOT_Template_Report_SysInfo_Sync(client, sg_data_report_buffer, sg_data_report_buffersize,
  622. QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  623. if (rc != QCLOUD_RET_SUCCESS) {
  624. Log_e("Report system info fail, err: %d", rc);
  625. }
  626. } else {
  627. Log_e("Get system info fail, err: %d", rc);
  628. }
  629. // get the property changed during offline
  630. rc = IOT_Template_GetStatus_sync(client, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  631. if (rc != QCLOUD_RET_SUCCESS) {
  632. Log_e("Get data status fail, err: %d", rc);
  633. } else {
  634. Log_d("Get data status success");
  635. }
  636. // init a timer for cycle report, you could delete it or not for your needs
  637. InitTimer(&sg_reportTimer);
  638. while (IOT_Template_IsConnected(client) || rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT ||
  639. rc == QCLOUD_RET_MQTT_RECONNECTED || QCLOUD_RET_SUCCESS == rc) {
  640. #ifndef MULTITHREAD_ENABLED
  641. rc = IOT_Template_Yield(client, 200);
  642. if (rc == QCLOUD_ERR_MQTT_ATTEMPTING_RECONNECT) {
  643. HAL_SleepMs(1000);
  644. continue;
  645. } else if (rc != QCLOUD_RET_SUCCESS) {
  646. Log_e("Exit loop caused of errCode: %d", rc);
  647. }
  648. #endif
  649. /* handle control msg from server */
  650. if (sg_control_msg_arrived) {
  651. deal_down_stream_user_logic(client, &sg_ProductData);
  652. /* control msg should reply, otherwise server treat device didn't receive
  653. * and retain the msg which would be get by get status*/
  654. memset((char *)&replyPara, 0, sizeof(sReplyPara));
  655. replyPara.code = eDEAL_SUCCESS;
  656. replyPara.timeout_ms = QCLOUD_IOT_MQTT_COMMAND_TIMEOUT;
  657. replyPara.status_msg[0] = '\0'; // add extra info to replyPara.status_msg when error occured
  658. rc = IOT_Template_ControlReply(client, sg_data_report_buffer, sg_data_report_buffersize, &replyPara);
  659. if (rc == QCLOUD_RET_SUCCESS) {
  660. Log_d("Contol msg reply success");
  661. sg_control_msg_arrived = false;
  662. } else {
  663. Log_e("Contol msg reply failed, err: %d", rc);
  664. }
  665. }
  666. /*report msg to server*/
  667. /*report the lastest properties's status*/
  668. if (QCLOUD_RET_SUCCESS == deal_up_stream_user_logic(pReportDataList, &ReportCont)) {
  669. rc = IOT_Template_JSON_ConstructReportArray(client, sg_data_report_buffer, sg_data_report_buffersize,
  670. ReportCont, pReportDataList);
  671. if (rc == QCLOUD_RET_SUCCESS) {
  672. rc = IOT_Template_Report(client, sg_data_report_buffer, sg_data_report_buffersize,
  673. OnReportReplyCallback, NULL, QCLOUD_IOT_MQTT_COMMAND_TIMEOUT);
  674. if (rc == QCLOUD_RET_SUCCESS) {
  675. Log_i("data template reporte success");
  676. } else {
  677. Log_e("data template reporte failed, err: %d", rc);
  678. }
  679. } else {
  680. Log_e("construct reporte data failed, err: %d", rc);
  681. }
  682. }
  683. #ifdef EVENT_POST_ENABLED
  684. eventPostCheck(client);
  685. #endif
  686. HAL_SleepMs(1000);
  687. }
  688. exit:
  689. #ifdef MULTITHREAD_ENABLED
  690. IOT_Template_Stop_Yield_Thread(client);
  691. #endif
  692. if(client!=NULL)
  693. {
  694. rc = IOT_Template_Destroy(client);
  695. }
  696. ql_rtos_task_delete(NULL);
  697. }
  698. int light_data_template_sample_start(void)
  699. {
  700. int err = 0;
  701. int count = 0;
  702. ql_task_t light_data_template_sample_task = NULL;
  703. /* 主循环进入休眠 */
  704. while (count < 10)
  705. {
  706. count++;
  707. ql_rtos_task_sleep_s(1);
  708. Log_i("ql_qcloud_sdk_light_data_template_sample_start_init -0x%04X\n", err);
  709. }
  710. err = ql_rtos_task_create(&light_data_template_sample_task, 10*1024, APP_PRIORITY_NORMAL, "light_data", light_data_template_sample, NULL, 5);
  711. if (err != QL_OSI_SUCCESS)
  712. {
  713. Log_e("light_data_template sample task created failed");
  714. return -1;
  715. }
  716. return 0;
  717. }