ble_qiot_template.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*
  2. * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
  3. * Licensed under the MIT License (the "License"); you may not use this file except in
  4. * compliance with the License. You may obtain a copy of the License at
  5. * http://opensource.org/licenses/MIT
  6. * Unless required by applicable law or agreed to in writing, software distributed under the License is
  7. * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  8. * either express or implied. See the License for the specific language governing permissions and
  9. * limitations under the License.
  10. *
  11. */
  12. #ifdef __cplusplus
  13. extern "C" {
  14. #endif
  15. #include "ble_qiot_template.h"
  16. #include <stdio.h>
  17. #include <stdbool.h>
  18. #include <string.h>
  19. #include "ble_qiot_export.h"
  20. #include "ble_qiot_common.h"
  21. #include "ble_qiot_param_check.h"
  22. #include "ble_qiot_ble_device.h"
  23. static uint8_t sg_test_power_switch = false;
  24. static int ble_property_power_switch_set(const char *data, uint16_t len)
  25. {
  26. ble_qiot_log_d("set property power_switch %d", *(uint8_t *)data);
  27. property_power_switch(data, len);
  28. sg_test_power_switch = data[0];
  29. return 0;
  30. }
  31. static int ble_property_power_switch_get(char *data, uint16_t buf_len)
  32. {
  33. ble_qiot_log_d("get property power_switch %d", sg_test_power_switch);
  34. data[0] = sg_test_power_switch;
  35. return sizeof(uint8_t);
  36. }
  37. static uint16_t sg_test_color = 0;
  38. static int ble_property_color_set(const char *data, uint16_t len)
  39. {
  40. uint16_t color_value = 0;
  41. memcpy(&color_value, data, sizeof(uint16_t));
  42. color_value = NTOHS(color_value);
  43. ble_qiot_log_d("set property color %d", color_value);
  44. sg_test_color = color_value;
  45. return 0;
  46. }
  47. static int ble_property_color_get(char *data, uint16_t buf_len)
  48. {
  49. uint16_t color_value = 0;
  50. ble_qiot_log_d("get property color %d", color_value);
  51. color_value = HTONS(sg_test_color);
  52. memcpy(data, &color_value, sizeof(uint16_t));
  53. return sizeof(uint16_t);
  54. }
  55. static int sg_test_brightness = 0;
  56. static int ble_property_brightness_set(const char *data, uint16_t len)
  57. {
  58. int brightness_value = 0;
  59. memcpy(&brightness_value, data, sizeof(int));
  60. brightness_value = NTOHL(brightness_value);
  61. if ((brightness_value < BLE_QIOT_PROPERTY_BRIGHTNESS_MIN) ||
  62. (brightness_value > BLE_QIOT_PROPERTY_BRIGHTNESS_MAX)) {
  63. ble_qiot_log_e("invalid brightness value %d", brightness_value);
  64. return -1;
  65. }
  66. ble_qiot_log_d("set property brightness %d", brightness_value);
  67. sg_test_brightness = brightness_value;
  68. return 0;
  69. }
  70. static int ble_property_brightness_get(char *data, uint16_t buf_len)
  71. {
  72. int brightness_value = 0;
  73. ble_qiot_log_d("get property brightness %d", sg_test_brightness);
  74. brightness_value = HTONL(sg_test_brightness);
  75. memcpy(data, &brightness_value, sizeof(int));
  76. return sizeof(uint32_t);
  77. }
  78. static char sg_test_name[100 + 1] = "default name";
  79. static int ble_property_name_set(const char *data, uint16_t len)
  80. {
  81. ble_qiot_log_d("set property name %.*s", len, data);
  82. if (len > sizeof(sg_test_name) - 1) {
  83. ble_qiot_log_d("too long name");
  84. return -1;
  85. }
  86. memset(sg_test_name, 0, sizeof(sg_test_name));
  87. memcpy(sg_test_name, data, len);
  88. return 0;
  89. }
  90. static int ble_property_name_get(char *data, uint16_t buf_len)
  91. {
  92. int i = 0;
  93. ble_qiot_log_d("get property name %s", sg_test_name);
  94. if (0 == strncmp("default name", sg_test_name, sizeof("default name") - 1)) {
  95. for (i = 0; i < 26 * 3; i++) {
  96. data[i] = 'a' + (i % 26);
  97. }
  98. return i;
  99. } else {
  100. memcpy(data, sg_test_name, strlen(sg_test_name));
  101. return strlen(sg_test_name);
  102. }
  103. }
  104. static ble_property_t sg_ble_property_array[BLE_QIOT_PROPERTY_ID_BUTT] = {
  105. {ble_property_power_switch_set, ble_property_power_switch_get, BLE_QIOT_PROPERTY_AUTH_RW, BLE_QIOT_DATA_TYPE_BOOL},
  106. {ble_property_color_set, ble_property_color_get, BLE_QIOT_PROPERTY_AUTH_RW, BLE_QIOT_DATA_TYPE_ENUM},
  107. {ble_property_brightness_set, ble_property_brightness_get, BLE_QIOT_PROPERTY_AUTH_RW, BLE_QIOT_DATA_TYPE_INT},
  108. {ble_property_name_set, ble_property_name_get, BLE_QIOT_PROPERTY_AUTH_RW, BLE_QIOT_DATA_TYPE_STRING},
  109. };
  110. static bool ble_check_space_enough_by_type(uint8_t type, uint16_t left_size)
  111. {
  112. switch (type) {
  113. case BLE_QIOT_DATA_TYPE_BOOL:
  114. return left_size >= sizeof(uint8_t);
  115. case BLE_QIOT_DATA_TYPE_INT:
  116. case BLE_QIOT_DATA_TYPE_FLOAT:
  117. case BLE_QIOT_DATA_TYPE_TIME:
  118. return left_size >= sizeof(uint32_t);
  119. case BLE_QIOT_DATA_TYPE_ENUM:
  120. return left_size >= sizeof(uint16_t);
  121. default:
  122. // string length is unknow, default true
  123. return true;
  124. }
  125. }
  126. static uint16_t ble_check_ret_value_by_type(uint8_t type, uint16_t buf_len, uint16_t ret_val)
  127. {
  128. switch (type) {
  129. case BLE_QIOT_DATA_TYPE_BOOL:
  130. return ret_val <= sizeof(uint8_t);
  131. case BLE_QIOT_DATA_TYPE_INT:
  132. case BLE_QIOT_DATA_TYPE_FLOAT:
  133. case BLE_QIOT_DATA_TYPE_TIME:
  134. return ret_val <= sizeof(uint32_t);
  135. case BLE_QIOT_DATA_TYPE_ENUM:
  136. return ret_val <= sizeof(uint16_t);
  137. default:
  138. // string length is unknow, default true
  139. return ret_val <= buf_len;
  140. }
  141. }
  142. uint8_t ble_get_property_type_by_id(uint8_t id)
  143. {
  144. if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
  145. ble_qiot_log_e("invalid property id %d", id);
  146. return BLE_QIOT_DATA_TYPE_BUTT;
  147. }
  148. return sg_ble_property_array[id].type;
  149. }
  150. int ble_user_property_set_data(const e_ble_tlv *tlv)
  151. {
  152. POINTER_SANITY_CHECK(tlv, BLE_QIOT_RS_ERR_PARA);
  153. if (tlv->id >= BLE_QIOT_PROPERTY_ID_BUTT) {
  154. ble_qiot_log_e("invalid property id %d", tlv->id);
  155. return BLE_QIOT_RS_ERR;
  156. }
  157. if (NULL != sg_ble_property_array[tlv->id].set_cb) {
  158. if (0 != sg_ble_property_array[tlv->id].set_cb(tlv->val, tlv->len)) {
  159. ble_qiot_log_e("set property id %d failed", tlv->id);
  160. return BLE_QIOT_RS_ERR;
  161. } else {
  162. return BLE_QIOT_RS_OK;
  163. }
  164. }
  165. ble_qiot_log_e("invalid set callback, id %d", tlv->id);
  166. return BLE_QIOT_RS_ERR;
  167. }
  168. int ble_user_property_get_data_by_id(uint8_t id, char *buf, uint16_t buf_len)
  169. {
  170. int ret_len = 0;
  171. POINTER_SANITY_CHECK(buf, BLE_QIOT_RS_ERR_PARA);
  172. if (id >= BLE_QIOT_PROPERTY_ID_BUTT) {
  173. ble_qiot_log_e("invalid property id %d", id);
  174. return -1;
  175. }
  176. if (NULL != sg_ble_property_array[id].get_cb) {
  177. if (!ble_check_space_enough_by_type(sg_ble_property_array[id].type, buf_len)) {
  178. ble_qiot_log_e("not enough space get property id %d data", id);
  179. return -1;
  180. }
  181. ret_len = sg_ble_property_array[id].get_cb(buf, buf_len);
  182. if (ret_len < 0) {
  183. ble_qiot_log_e("get property id %d data failed", id);
  184. return -1;
  185. } else {
  186. if (ble_check_ret_value_by_type(sg_ble_property_array[id].type, buf_len, ret_len)) {
  187. return ret_len;
  188. } else {
  189. ble_qiot_log_e("property id %d length invalid, type %d", id, sg_ble_property_array[id].type);
  190. return -1;
  191. }
  192. }
  193. }
  194. ble_qiot_log_e("invalid callback, property id %d", id);
  195. return 0;
  196. }
  197. int ble_user_property_report_reply_handle(uint8_t result)
  198. {
  199. ble_qiot_log_d("report reply result %d", result);
  200. if (0 == result) {
  201. report_reply_blink();
  202. }
  203. return BLE_QIOT_RS_OK;
  204. }
  205. int ble_user_property_struct_handle(const char *in_buf, uint16_t buf_len, ble_property_t struct_arr[], uint8_t arr_size)
  206. {
  207. uint16_t parse_len = 0;
  208. uint16_t ret_len = 0;
  209. e_ble_tlv tlv;
  210. while (parse_len < buf_len) {
  211. memset(&tlv, 0, sizeof(e_ble_tlv));
  212. ret_len = ble_lldata_parse_tlv(in_buf + parse_len, buf_len - parse_len, &tlv);
  213. parse_len += ret_len;
  214. if (parse_len > buf_len) {
  215. ble_qiot_log_e("parse struct failed");
  216. return parse_len;
  217. }
  218. if (tlv.id >= arr_size){
  219. ble_qiot_log_e("invalid array index %d", tlv.id);
  220. return parse_len;
  221. }
  222. if (NULL == struct_arr[tlv.id].set_cb){
  223. ble_qiot_log_e("invalid member id %d", tlv.id);
  224. return parse_len;
  225. }
  226. if (BLE_QIOT_RS_OK != struct_arr[tlv.id].set_cb(tlv.val, tlv.len)) {
  227. ble_qiot_log_e("user handle property error, member id %d, type %d, len %d", tlv.id, tlv.type, tlv.len);
  228. return parse_len;
  229. }
  230. }
  231. return 0;
  232. }
  233. int ble_user_property_struct_get_data(char *in_buf, uint16_t buf_len, ble_property_t struct_arr[], uint8_t arr_size)
  234. {
  235. uint8_t property_id = 0;
  236. uint8_t property_type = 0;
  237. int property_len = 0;
  238. char *data_buf = in_buf;
  239. uint16_t data_len = 0;
  240. uint16_t string_len = 0;
  241. for (property_id = 0; property_id < arr_size; property_id++) {
  242. property_type = struct_arr[property_id].type;
  243. if (property_type >= BLE_QIOT_DATA_TYPE_BUTT) {
  244. ble_qiot_log_e("member id %d type %d invalid", property_id, property_type);
  245. return BLE_QIOT_RS_ERR;
  246. }
  247. data_buf[data_len++] = BLE_QIOT_PACKAGE_TLV_HEAD(property_type, property_id);
  248. if (BLE_QIOT_DATA_TYPE_STRING == property_type) {
  249. // reserved 2 bytes for string length
  250. property_len = struct_arr[property_id].get_cb((char *)data_buf + data_len + 2, buf_len - data_len - 2);
  251. } else {
  252. property_len = struct_arr[property_id].get_cb((char *)data_buf + data_len, buf_len - data_len);
  253. }
  254. if (property_len < 0) {
  255. ble_qiot_log_e("too long data, member id %d, data length %d", property_id, data_len);
  256. return BLE_QIOT_RS_ERR;
  257. } else if (property_len == 0) {
  258. // no data to post
  259. data_len--;
  260. data_buf[data_len] = '0';
  261. ble_qiot_log_d("member id %d no data to post", property_id);
  262. } else {
  263. if (BLE_QIOT_DATA_TYPE_STRING == property_type) {
  264. string_len = HTONS(property_len);
  265. memcpy(data_buf + data_len, &string_len, sizeof(uint16_t));
  266. data_len += sizeof(uint16_t);
  267. }
  268. data_len += property_len;
  269. }
  270. }
  271. return data_len;
  272. }
  273. static int ble_event_get_status_report_status(char *buf, uint16_t buf_len)
  274. {
  275. buf[0] = 1;
  276. return 1;
  277. }
  278. static int ble_event_get_status_report_message(char *buf, uint16_t buf_len)
  279. {
  280. int i = 0;
  281. for (i = 0; i < 26 * 3; i++) {
  282. buf[i] = 'a' + (i % 26);
  283. }
  284. return i;
  285. }
  286. static ble_event_param sg_ble_event_status_report_array[BLE_QIOT_EVENT_STATUS_REPORT_PARAM_ID_BUTT] = {
  287. {ble_event_get_status_report_status, BLE_QIOT_DATA_TYPE_BOOL},
  288. {ble_event_get_status_report_message, BLE_QIOT_DATA_TYPE_STRING},
  289. };
  290. static int ble_event_get_low_voltage_voltage(char *data, uint16_t buf_len)
  291. {
  292. float tmp = 1.0;
  293. memcpy(data, &tmp, sizeof(float));
  294. return sizeof(float);
  295. }
  296. static ble_event_param sg_ble_event_low_voltage_array[BLE_QIOT_EVENT_LOW_VOLTAGE_PARAM_ID_BUTT] = {
  297. {ble_event_get_low_voltage_voltage, BLE_QIOT_DATA_TYPE_FLOAT},
  298. };
  299. static int ble_event_get_hardware_fault_name(char *data, uint16_t buf_len)
  300. {
  301. memcpy(data, "hardware_fault", sizeof("hardware_fault") - 1);
  302. return sizeof("hardware_fault") - 1;
  303. }
  304. static int ble_event_get_hardware_fault_error_code(char *data, uint16_t buf_len)
  305. {
  306. int error_code = HTONL(1024);
  307. memcpy(data, &error_code, sizeof(int));
  308. return sizeof(int);
  309. }
  310. static ble_event_param sg_ble_event_hardware_fault_array[BLE_QIOT_EVENT_HARDWARE_FAULT_PARAM_ID_BUTT] = {
  311. {ble_event_get_hardware_fault_name, BLE_QIOT_DATA_TYPE_STRING},
  312. {ble_event_get_hardware_fault_error_code, BLE_QIOT_DATA_TYPE_INT},
  313. };
  314. static ble_event_t sg_ble_event_array[BLE_QIOT_EVENT_ID_BUTT] = {
  315. {sg_ble_event_status_report_array, sizeof(sg_ble_event_status_report_array) / sizeof(ble_event_param)},
  316. {sg_ble_event_low_voltage_array, sizeof(sg_ble_event_low_voltage_array) / sizeof(ble_event_param)},
  317. {sg_ble_event_hardware_fault_array, sizeof(sg_ble_event_hardware_fault_array) / sizeof(ble_event_param)},
  318. };
  319. int ble_event_get_id_array_size(uint8_t event_id)
  320. {
  321. if (event_id >= BLE_QIOT_EVENT_ID_BUTT) {
  322. ble_qiot_log_e("invalid event id %d", event_id);
  323. return -1;
  324. }
  325. return sg_ble_event_array[event_id].array_size;
  326. }
  327. uint8_t ble_event_get_param_id_type(uint8_t event_id, uint8_t param_id)
  328. {
  329. if (event_id >= BLE_QIOT_EVENT_ID_BUTT) {
  330. ble_qiot_log_e("invalid event id %d", event_id);
  331. return BLE_QIOT_DATA_TYPE_BUTT;
  332. }
  333. if (param_id >= sg_ble_event_array[event_id].array_size) {
  334. ble_qiot_log_e("invalid param id %d", param_id);
  335. return BLE_QIOT_DATA_TYPE_BUTT;
  336. }
  337. return sg_ble_event_array[event_id].event_array[param_id].type;
  338. }
  339. int ble_event_get_data_by_id(uint8_t event_id, uint8_t param_id, char *out_buf, uint16_t buf_len)
  340. {
  341. int ret_len = 0;
  342. if (event_id >= BLE_QIOT_EVENT_ID_BUTT) {
  343. ble_qiot_log_e("invalid event id %d", event_id);
  344. return -1;
  345. }
  346. if (param_id >= sg_ble_event_array[event_id].array_size) {
  347. ble_qiot_log_e("invalid param id %d", param_id);
  348. return -1;
  349. }
  350. if (NULL == sg_ble_event_array[event_id].event_array[param_id].get_cb) {
  351. ble_qiot_log_e("invalid callback, event id %d, param id %d", event_id, param_id);
  352. return 0;
  353. }
  354. if (!ble_check_space_enough_by_type(sg_ble_event_array[event_id].event_array[param_id].type, buf_len)) {
  355. ble_qiot_log_e("not enough space get data, event id %d, param id %d", event_id, param_id);
  356. return -1;
  357. }
  358. ret_len = sg_ble_event_array[event_id].event_array[param_id].get_cb(out_buf, buf_len);
  359. if (ret_len < 0) {
  360. ble_qiot_log_e("get event data failed, event id %d, param id %d", event_id, param_id);
  361. return -1;
  362. } else {
  363. if (ble_check_ret_value_by_type(sg_ble_event_array[event_id].event_array[param_id].type, buf_len, ret_len)) {
  364. return ret_len;
  365. } else {
  366. ble_qiot_log_e("evnet data length invalid, event id %d, param id %d, type %d", event_id, param_id,
  367. sg_ble_event_array[event_id].event_array[param_id].type);
  368. return -1;
  369. }
  370. }
  371. }
  372. int ble_user_event_reply_handle(uint8_t event_id, uint8_t result)
  373. {
  374. ble_qiot_log_d("event id %d, reply result %d", event_id, result);
  375. return BLE_QIOT_RS_OK;
  376. }
  377. static int ble_action_handle_loop_input_cb(e_ble_tlv *input_param_array, uint8_t input_array_size,
  378. uint8_t *output_id_array)
  379. {
  380. int result = 0;
  381. if (NULL == input_param_array || NULL == output_id_array) {
  382. ble_qiot_log_e("invalid param");
  383. return -1;
  384. }
  385. report_reply_blink();
  386. for (int i = 0; i < input_array_size; i++) {
  387. ble_qiot_log_d("id %d", input_param_array[i].id);
  388. }
  389. memcpy(&result, input_param_array[0].val, sizeof(int));
  390. result = NTOHL(result);
  391. ble_qiot_log_d("id %d, val %d", input_param_array[0].id, result);
  392. action_led_blink(result);
  393. output_id_array[BLE_QIOT_ACTION_LOOP_OUTPUT_ID_RESULT] = true;
  394. return 0;
  395. }
  396. static int ble_action_handle_loop_output_cb(uint8_t output_id, char *buf, uint16_t buf_len)
  397. {
  398. int data_len = 0;
  399. int i = 0;
  400. switch (output_id) {
  401. case BLE_QIOT_ACTION_LOOP_OUTPUT_ID_RESULT:
  402. for (i = 0; i < 26 * 3; i++) {
  403. buf[i] = 'a' + (i % 26);
  404. }
  405. data_len = i;
  406. break;
  407. default:
  408. break;
  409. }
  410. return data_len;
  411. }
  412. static uint8_t sg_ble_action_loop_input_type_array[BLE_QIOT_ACTION_LOOP_INPUT_ID_BUTT] = {
  413. BLE_QIOT_DATA_TYPE_INT,
  414. };
  415. static uint8_t sg_ble_action_loop_output_type_array[BLE_QIOT_ACTION_LOOP_OUTPUT_ID_BUTT] = {
  416. BLE_QIOT_DATA_TYPE_STRING,
  417. };
  418. static ble_action_t sg_ble_action_array[BLE_QIOT_ACTION_ID_BUTT] = {
  419. {ble_action_handle_loop_input_cb, ble_action_handle_loop_output_cb, sg_ble_action_loop_input_type_array,
  420. sg_ble_action_loop_output_type_array, sizeof(sg_ble_action_loop_input_type_array) / sizeof(uint8_t),
  421. sizeof(sg_ble_action_loop_output_type_array) / sizeof(uint8_t)},
  422. };
  423. uint8_t ble_action_get_intput_type_by_id(uint8_t action_id, uint8_t input_id)
  424. {
  425. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  426. ble_qiot_log_e("invalid action id %d", action_id);
  427. return BLE_QIOT_DATA_TYPE_BUTT;
  428. }
  429. if (input_id >= sg_ble_event_array[action_id].array_size) {
  430. ble_qiot_log_e("invalid input id %d", input_id);
  431. return BLE_QIOT_DATA_TYPE_BUTT;
  432. }
  433. return sg_ble_action_array[action_id].input_type_array[input_id];
  434. }
  435. uint8_t ble_action_get_output_type_by_id(uint8_t action_id, uint8_t output_id)
  436. {
  437. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  438. ble_qiot_log_e("invalid action id %d", action_id);
  439. return BLE_QIOT_DATA_TYPE_BUTT;
  440. }
  441. if (output_id >= sg_ble_event_array[action_id].array_size) {
  442. ble_qiot_log_e("invalid output id %d", output_id);
  443. return BLE_QIOT_DATA_TYPE_BUTT;
  444. }
  445. return sg_ble_action_array[action_id].output_type_array[output_id];
  446. }
  447. int ble_action_get_input_id_size(uint8_t action_id)
  448. {
  449. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  450. ble_qiot_log_e("invalid action id %d", action_id);
  451. return -1;
  452. }
  453. return sg_ble_action_array[action_id].input_id_size;
  454. }
  455. int ble_action_get_output_id_size(uint8_t action_id)
  456. {
  457. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  458. ble_qiot_log_e("invalid action id %d", action_id);
  459. return -1;
  460. }
  461. return sg_ble_action_array[action_id].output_id_size;
  462. }
  463. int ble_action_user_handle_input_param(uint8_t action_id, e_ble_tlv *input_param_array, uint8_t input_array_size,
  464. uint8_t *output_id_array)
  465. {
  466. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  467. ble_qiot_log_e("invalid action id %d", action_id);
  468. return -1;
  469. }
  470. if (NULL != sg_ble_action_array[action_id].input_cb) {
  471. if (0 != sg_ble_action_array[action_id].input_cb(input_param_array, input_array_size, output_id_array)) {
  472. ble_qiot_log_e("input handle error");
  473. return -1;
  474. }
  475. }
  476. return 0;
  477. }
  478. int ble_action_user_handle_output_param(uint8_t action_id, uint8_t output_id, char *buf, uint16_t buf_len)
  479. {
  480. int ret_len = 0;
  481. if (action_id >= BLE_QIOT_ACTION_ID_BUTT) {
  482. ble_qiot_log_e("invalid action id %d", action_id);
  483. return -1;
  484. }
  485. if (NULL == sg_ble_action_array[action_id].output_cb) {
  486. ble_qiot_log_e("invalid callback, action id %d", action_id);
  487. return 0;
  488. }
  489. if (!ble_check_space_enough_by_type(sg_ble_action_array[action_id].output_type_array[output_id], buf_len)) {
  490. ble_qiot_log_e("not enough space get data, action id %d, output id %d", action_id, output_id);
  491. return -1;
  492. }
  493. ret_len = sg_ble_action_array[action_id].output_cb(output_id, buf, buf_len);
  494. if (ret_len < 0) {
  495. ble_qiot_log_e("get action data failed, action id %d, output id %d", action_id, output_id);
  496. return -1;
  497. } else {
  498. if (ble_check_ret_value_by_type(sg_ble_action_array[action_id].output_type_array[output_id], buf_len,
  499. ret_len)) {
  500. return ret_len;
  501. } else {
  502. ble_qiot_log_e("action data length invalid, action id %d, output id %d", action_id, output_id);
  503. return -1;
  504. }
  505. }
  506. }
  507. #ifdef __cplusplus
  508. }
  509. #endif