at_socket_sim800c.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /*
  2. * File : at_socket_sim800c.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2018-06-12 malongwei first version
  23. * 2019-05-13 chenyong multi AT socket client support
  24. */
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <at_device_sim800c.h>
  28. #define LOG_TAG "at.skt.sim800"
  29. #include <at_log.h>
  30. #if defined(AT_DEVICE_USING_SIM800C) && defined(AT_USING_SOCKET)
  31. #define SIM800C_MODULE_SEND_MAX_SIZE 1000
  32. /* set real event by current socket and current state */
  33. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  34. /* AT socket event type */
  35. #define SIM800C_EVENT_CONN_OK (1L << 0)
  36. #define SIM800C_EVENT_SEND_OK (1L << 1)
  37. #define SIM800C_EVENT_RECV_OK (1L << 2)
  38. #define SIM800C_EVNET_CLOSE_OK (1L << 3)
  39. #define SIM800C_EVENT_CONN_FAIL (1L << 4)
  40. #define SIM800C_EVENT_SEND_FAIL (1L << 5)
  41. static at_evt_cb_t at_evt_cb_set[] = {
  42. [AT_SOCKET_EVT_RECV] = NULL,
  43. [AT_SOCKET_EVT_CLOSED] = NULL,
  44. };
  45. static int sim800c_socket_event_send(struct at_device *device, uint32_t event)
  46. {
  47. return (int) rt_event_send(device->socket_event, event);
  48. }
  49. static int sim800c_socket_event_recv(struct at_device *device, uint32_t event, uint32_t timeout, rt_uint8_t option)
  50. {
  51. int result = RT_EOK;
  52. rt_uint32_t recved;
  53. result = rt_event_recv(device->socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  54. if (result != RT_EOK)
  55. {
  56. return -RT_ETIMEOUT;
  57. }
  58. return recved;
  59. }
  60. /**
  61. * close socket by AT commands.
  62. *
  63. * @param current socket
  64. *
  65. * @return 0: close socket success
  66. * -1: send AT commands error
  67. * -2: wait socket event timeout
  68. * -5: no memory
  69. */
  70. static int sim800c_socket_close(struct at_socket *socket)
  71. {
  72. uint32_t event = 0;
  73. int result = RT_EOK;
  74. int device_socket = (int) socket->user_data;
  75. struct at_device *device = (struct at_device *) socket->device;
  76. /* clear socket close event */
  77. event = SET_EVENT(device_socket, SIM800C_EVNET_CLOSE_OK);
  78. sim800c_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  79. if (at_obj_exec_cmd(device->client, NULL, "AT+CIPCLOSE=%d", device_socket) < 0)
  80. {
  81. result = -RT_ERROR;
  82. goto __exit;
  83. }
  84. if (sim800c_socket_event_recv(device, event, rt_tick_from_millisecond(300*3), RT_EVENT_FLAG_AND) < 0)
  85. {
  86. LOG_E("%s device socket(%d) wait close OK timeout.", device->name, device_socket);
  87. result = -RT_ETIMEOUT;
  88. goto __exit;
  89. }
  90. __exit:
  91. return result;
  92. }
  93. /**
  94. * create TCP/UDP client or server connect by AT commands.
  95. *
  96. * @param socket current socket
  97. * @param ip server or client IP address
  98. * @param port server or client port
  99. * @param type connect socket type(tcp, udp)
  100. * @param is_client connection is client
  101. *
  102. * @return 0: connect success
  103. * -1: connect failed, send commands error or type error
  104. * -2: wait socket event timeout
  105. * -5: no memory
  106. */
  107. static int sim800c_socket_connect(struct at_socket *socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  108. {
  109. uint32_t event = 0;
  110. rt_bool_t retryed = RT_FALSE;
  111. at_response_t resp = RT_NULL;
  112. int result = RT_EOK, event_result = 0;
  113. int device_socket = (int) socket->user_data;
  114. struct at_device *device = (struct at_device *) socket->device;
  115. RT_ASSERT(ip);
  116. RT_ASSERT(port >= 0);
  117. resp = at_create_resp(128, 0, 5 * RT_TICK_PER_SECOND);
  118. if (resp == RT_NULL)
  119. {
  120. LOG_E("no memory for resp create.");
  121. return -RT_ENOMEM;
  122. }
  123. __retry:
  124. /* clear socket connect event */
  125. event = SET_EVENT(device_socket, SIM800C_EVENT_CONN_OK | SIM800C_EVENT_CONN_FAIL);
  126. sim800c_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  127. if (is_client)
  128. {
  129. switch (type)
  130. {
  131. case AT_SOCKET_TCP:
  132. /* send AT commands(eg: AT+QIOPEN=0,"TCP","x.x.x.x", 1234) to connect TCP server */
  133. if (at_obj_exec_cmd(device->client, RT_NULL,
  134. "AT+CIPSTART=%d,\"TCP\",\"%s\",%d", device_socket, ip, port) < 0)
  135. {
  136. result = -RT_ERROR;
  137. goto __exit;
  138. }
  139. break;
  140. case AT_SOCKET_UDP:
  141. if (at_obj_exec_cmd(device->client, RT_NULL,
  142. "AT+CIPSTART=%d,\"UDP\",\"%s\",%d", device_socket, ip, port) < 0)
  143. {
  144. result = -RT_ERROR;
  145. goto __exit;
  146. }
  147. break;
  148. default:
  149. LOG_E("%s device not supported connect type : %d.", device->name, type);
  150. result = -RT_ERROR;
  151. goto __exit;
  152. }
  153. }
  154. /* waiting result event from AT URC, the device default connection timeout is 75 seconds, but it set to 10 seconds is convenient to use */
  155. if (sim800c_socket_event_recv(device, SET_EVENT(device_socket, 0), 10 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  156. {
  157. LOG_E("%s device socket(%d) wait connect result timeout.", device->name, device_socket);
  158. result = -RT_ETIMEOUT;
  159. goto __exit;
  160. }
  161. /* waiting OK or failed result */
  162. event_result = sim800c_socket_event_recv(device,
  163. SIM800C_EVENT_CONN_OK | SIM800C_EVENT_CONN_FAIL, 1 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  164. if (event_result < 0)
  165. {
  166. LOG_E("%s device socket(%d) wait connect OK|FAIL timeout.", device->name, device_socket);
  167. result = -RT_ETIMEOUT;
  168. goto __exit;
  169. }
  170. /* check result */
  171. if (event_result & SIM800C_EVENT_CONN_FAIL)
  172. {
  173. if (retryed == RT_FALSE)
  174. {
  175. LOG_D("%s device socket(%d) connect failed, the socket was not be closedand now will connect retry.",
  176. device->name, device_socket);
  177. if (sim800c_socket_close(socket) < 0)
  178. {
  179. result = -RT_ERROR;
  180. goto __exit;
  181. }
  182. retryed = RT_TRUE;
  183. goto __retry;
  184. }
  185. LOG_E("%s device socket(%d) connect failed.", device->name, device_socket);
  186. result = -RT_ERROR;
  187. goto __exit;
  188. }
  189. __exit:
  190. if (resp)
  191. {
  192. at_delete_resp(resp);
  193. }
  194. return result;
  195. }
  196. /**
  197. * send data to server or client by AT commands.
  198. *
  199. * @param socket current socket
  200. * @param buff send buffer
  201. * @param bfsz send buffer size
  202. * @param type connect socket type(tcp, udp)
  203. *
  204. * @return >=0: the size of send success
  205. * -1: send AT commands error or send data error
  206. * -2: waited socket event timeout
  207. * -5: no memory
  208. */
  209. static int sim800c_socket_send(struct at_socket *socket, const char *buff, size_t bfsz, enum at_socket_type type)
  210. {
  211. uint32_t event = 0;
  212. int result = RT_EOK, event_result = 0;
  213. size_t cur_pkt_size = 0, sent_size = 0;
  214. at_response_t resp = RT_NULL;
  215. int device_socket = (int) socket->user_data;
  216. struct at_device *device = (struct at_device *) socket->device;
  217. rt_mutex_t lock = device->client->lock;
  218. RT_ASSERT(buff);
  219. resp = at_create_resp(128, 2, 5 * RT_TICK_PER_SECOND);
  220. if (resp == RT_NULL)
  221. {
  222. LOG_E("no memory for resp create.");
  223. return -RT_ENOMEM;
  224. }
  225. rt_mutex_take(lock, RT_WAITING_FOREVER);
  226. /* clear socket connect event */
  227. event = SET_EVENT(device_socket, SIM800C_EVENT_SEND_OK | SIM800C_EVENT_SEND_FAIL);
  228. sim800c_socket_event_recv(device, event, 0, RT_EVENT_FLAG_OR);
  229. /* set AT client end sign to deal with '>' sign.*/
  230. at_obj_set_end_sign(device->client, '>');
  231. while (sent_size < bfsz)
  232. {
  233. if (bfsz - sent_size < SIM800C_MODULE_SEND_MAX_SIZE)
  234. {
  235. cur_pkt_size = bfsz - sent_size;
  236. }
  237. else
  238. {
  239. cur_pkt_size = SIM800C_MODULE_SEND_MAX_SIZE;
  240. }
  241. /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
  242. if (at_obj_exec_cmd(device->client, resp, "AT+CIPSEND=%d,%d", device_socket, cur_pkt_size) < 0)
  243. {
  244. result = -RT_ERROR;
  245. goto __exit;
  246. }
  247. /* send the real data to server or client */
  248. result = (int) at_client_obj_send(device->client, buff + sent_size, cur_pkt_size);
  249. if (result == 0)
  250. {
  251. result = -RT_ERROR;
  252. goto __exit;
  253. }
  254. /* waiting result event from AT URC */
  255. if (sim800c_socket_event_recv(device, SET_EVENT(device_socket, 0), 15 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR) < 0)
  256. {
  257. LOG_E("%s device socket(%d) wait send result timeout.", device->name, device_socket);
  258. result = -RT_ETIMEOUT;
  259. goto __exit;
  260. }
  261. /* waiting OK or failed result */
  262. event_result = sim800c_socket_event_recv(device,
  263. SIM800C_EVENT_SEND_OK | SIM800C_EVENT_SEND_FAIL, 5 * RT_TICK_PER_SECOND, RT_EVENT_FLAG_OR);
  264. if (event_result < 0)
  265. {
  266. LOG_E("%s device socket(%d) wait send connect OK|FAIL timeout.", device->name, device_socket);
  267. result = -RT_ETIMEOUT;
  268. goto __exit;
  269. }
  270. /* check result */
  271. if (event_result & SIM800C_EVENT_SEND_FAIL)
  272. {
  273. LOG_E("%s device socket(%d) send failed.", device->name, device_socket);
  274. result = -RT_ERROR;
  275. goto __exit;
  276. }
  277. sent_size += cur_pkt_size;
  278. }
  279. __exit:
  280. /* reset the end sign for data conflict */
  281. at_obj_set_end_sign(device->client, 0);
  282. rt_mutex_release(lock);
  283. if (resp)
  284. {
  285. at_delete_resp(resp);
  286. }
  287. return result > 0 ? sent_size : result;
  288. }
  289. /**
  290. * domain resolve by AT commands.
  291. *
  292. * @param name domain name
  293. * @param ip parsed IP address, it's length must be 16
  294. *
  295. * @return 0: domain resolve success
  296. * -1: send AT commands error or response error
  297. * -2: wait socket event timeout
  298. * -5: no memory
  299. */
  300. static int sim800c_domain_resolve(const char *name, char ip[16])
  301. {
  302. #define RESOLVE_RETRY 5
  303. int i, result = RT_EOK;
  304. char recv_ip[16] = { 0 };
  305. at_response_t resp = RT_NULL;
  306. struct at_device *device = RT_NULL;
  307. RT_ASSERT(name);
  308. RT_ASSERT(ip);
  309. device = at_device_get_first_initialized();
  310. if (device == RT_NULL)
  311. {
  312. LOG_E("get first init device failed.");
  313. return -RT_ERROR;
  314. }
  315. /* The maximum response time is 14 seconds, affected by network status */
  316. resp = at_create_resp(128, 4, 14 * RT_TICK_PER_SECOND);
  317. if (resp == RT_NULL)
  318. {
  319. LOG_E("no memory for resp create.");
  320. return -RT_ENOMEM;
  321. }
  322. for (i = 0; i < RESOLVE_RETRY; i++)
  323. {
  324. int err_code = 0;
  325. if (at_obj_exec_cmd(device->client, resp, "AT+CDNSGIP=\"%s\"", name) < 0)
  326. {
  327. result = -RT_ERROR;
  328. goto __exit;
  329. }
  330. /* domain name prase error options */
  331. if (at_resp_parse_line_args_by_kw(resp, "+CDNSGIP: 0", "+CDNSGIP: 0,%d", &err_code) > 0)
  332. {
  333. /* 3 - network error, 8 - dns common error */
  334. if (err_code == 3 || err_code == 8)
  335. {
  336. result = -RT_ERROR;
  337. goto __exit;
  338. }
  339. }
  340. /* parse the third line of response data, get the IP address */
  341. if (at_resp_parse_line_args_by_kw(resp, "+CDNSGIP:", "%*[^,],%*[^,],\"%[^\"]", recv_ip) < 0)
  342. {
  343. rt_thread_mdelay(100);
  344. /* resolve failed, maybe receive an URC CRLF */
  345. continue;
  346. }
  347. if (rt_strlen(recv_ip) < 8)
  348. {
  349. rt_thread_mdelay(100);
  350. /* resolve failed, maybe receive an URC CRLF */
  351. continue;
  352. }
  353. else
  354. {
  355. rt_thread_mdelay(10);
  356. rt_strncpy(ip, recv_ip, 15);
  357. ip[15] = '\0';
  358. break;
  359. }
  360. }
  361. __exit:
  362. if (resp)
  363. {
  364. at_delete_resp(resp);
  365. }
  366. return result;
  367. }
  368. /**
  369. * set AT socket event notice callback
  370. *
  371. * @param event notice event
  372. * @param cb notice callback
  373. */
  374. static void sim800c_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  375. {
  376. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  377. {
  378. at_evt_cb_set[event] = cb;
  379. }
  380. }
  381. static void urc_connect_func(struct at_client *client, const char *data, rt_size_t size)
  382. {
  383. int device_socket = 0;
  384. struct at_device *device = RT_NULL;
  385. char *client_name = client->device->parent.name;
  386. RT_ASSERT(data && size);
  387. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  388. if (device == RT_NULL)
  389. {
  390. LOG_E("get device(%s) failed.", client_name);
  391. return;
  392. }
  393. /* get the current socket by receive data */
  394. sscanf(data, "%d,%*s", &device_socket);
  395. if (strstr(data, "CONNECT OK"))
  396. {
  397. sim800c_socket_event_send(device, SET_EVENT(device_socket, SIM800C_EVENT_CONN_OK));
  398. }
  399. else if (strstr(data, "CONNECT FAIL"))
  400. {
  401. sim800c_socket_event_send(device, SET_EVENT(device_socket, SIM800C_EVENT_CONN_FAIL));
  402. }
  403. }
  404. static void urc_send_func(struct at_client *client, const char *data, rt_size_t size)
  405. {
  406. int device_socket = 0;
  407. struct at_device *device = RT_NULL;
  408. char *client_name = client->device->parent.name;
  409. RT_ASSERT(data && size);
  410. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  411. if (device == RT_NULL)
  412. {
  413. LOG_E("get device(%s) failed.", client_name);
  414. return;
  415. }
  416. /* get the current socket by receive data */
  417. sscanf(data, "%d,%*s", &device_socket);
  418. if (rt_strstr(data, "SEND OK"))
  419. {
  420. sim800c_socket_event_send(device, SET_EVENT(device_socket, SIM800C_EVENT_SEND_OK));
  421. }
  422. else if (rt_strstr(data, "SEND FAIL"))
  423. {
  424. sim800c_socket_event_send(device, SET_EVENT(device_socket, SIM800C_EVENT_SEND_FAIL));
  425. }
  426. }
  427. static void urc_close_func(struct at_client *client, const char *data, rt_size_t size)
  428. {
  429. int device_socket = 0;
  430. struct at_device *device = RT_NULL;
  431. char *client_name = client->device->parent.name;
  432. RT_ASSERT(data && size);
  433. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  434. if (device == RT_NULL)
  435. {
  436. LOG_E("get device(%s) failed.", client_name);
  437. return;
  438. }
  439. /* get the current socket by receive data */
  440. sscanf(data, "%d,%*s", &device_socket);
  441. if (rt_strstr(data, "CLOSE OK"))
  442. {
  443. sim800c_socket_event_send(device, SET_EVENT(device_socket, SIM800C_EVNET_CLOSE_OK));
  444. }
  445. else if (rt_strstr(data, "CLOSED"))
  446. {
  447. struct at_socket *socket = RT_NULL;
  448. /* get AT socket object by device socket descriptor */
  449. socket = &(device->sockets[device_socket]);
  450. /* notice the socket is disconnect by remote */
  451. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  452. {
  453. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0);
  454. }
  455. }
  456. }
  457. static void urc_recv_func(struct at_client *client, const char *data, rt_size_t size)
  458. {
  459. int device_socket = 0;
  460. rt_int32_t timeout;
  461. rt_size_t bfsz = 0, temp_size = 0;
  462. char *recv_buf = RT_NULL, temp[8] = {0};
  463. struct at_socket *socket = RT_NULL;
  464. struct at_device *device = RT_NULL;
  465. char *client_name = client->device->parent.name;
  466. RT_ASSERT(data && size);
  467. /* get the current socket and receive buffer size by receive data */
  468. sscanf(data, "+RECEIVE,%d,%d:", &device_socket, (int *) &bfsz);
  469. /* set receive timeout by receive buffer length, not less than 10 ms */
  470. timeout = bfsz > 10 ? bfsz : 10;
  471. if (device_socket < 0 || bfsz == 0)
  472. {
  473. return;
  474. }
  475. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_CLIENT, client_name);
  476. if (device == RT_NULL)
  477. {
  478. LOG_E("get device(%s) failed.", client_name);
  479. return;
  480. }
  481. recv_buf = (char *) rt_calloc(1, bfsz);
  482. if (recv_buf == RT_NULL)
  483. {
  484. LOG_E("no memory for receive buffer(%d).", bfsz);
  485. /* read and clean the coming data */
  486. while (temp_size < bfsz)
  487. {
  488. if (bfsz - temp_size > sizeof(temp))
  489. {
  490. at_client_obj_recv(client, temp, sizeof(temp), timeout);
  491. }
  492. else
  493. {
  494. at_client_obj_recv(client, temp, bfsz - temp_size, timeout);
  495. }
  496. temp_size += sizeof(temp);
  497. }
  498. return;
  499. }
  500. /* sync receive data */
  501. if (at_client_obj_recv(client, recv_buf, bfsz, timeout) != bfsz)
  502. {
  503. LOG_E("%s device receive size(%d) data failed.", device->name, bfsz);
  504. rt_free(recv_buf);
  505. return;
  506. }
  507. /* get AT socket object by device socket descriptor */
  508. socket = &(device->sockets[device_socket]);
  509. /* notice the receive buffer and buffer size */
  510. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  511. {
  512. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  513. }
  514. }
  515. /* sim800c device URC table for the socket data */
  516. static const struct at_urc urc_table[] =
  517. {
  518. {"", ", CONNECT OK\r\n", urc_connect_func},
  519. {"", ", CONNECT FAIL\r\n", urc_connect_func},
  520. {"", ", SEND OK\r\n", urc_send_func},
  521. {"", ", SEND FAIL\r\n", urc_send_func},
  522. {"", ", CLOSE OK\r\n", urc_close_func},
  523. {"", ", CLOSED\r\n", urc_close_func},
  524. {"+RECEIVE,", "\r\n", urc_recv_func},
  525. };
  526. static const struct at_socket_ops sim800c_socket_ops =
  527. {
  528. sim800c_socket_connect,
  529. sim800c_socket_close,
  530. sim800c_socket_send,
  531. sim800c_domain_resolve,
  532. sim800c_socket_set_event_cb,
  533. #if defined(AT_SW_VERSION_NUM) && AT_SW_VERSION_NUM > 0x10300
  534. RT_NULL,
  535. #endif
  536. };
  537. int sim800c_socket_init(struct at_device *device)
  538. {
  539. RT_ASSERT(device);
  540. /* register URC data execution function */
  541. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  542. return RT_EOK;
  543. }
  544. int sim800c_socket_class_register(struct at_device_class *class)
  545. {
  546. RT_ASSERT(class);
  547. class->socket_num = AT_DEVICE_SIM800C_SOCKETS_NUM;
  548. class->socket_ops = &sim800c_socket_ops;
  549. return RT_EOK;
  550. }
  551. #endif /* AT_DEVICE_USING_SIM800C && AT_USING_SOCKET */