at_socket_sim800c.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  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. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <rtthread.h>
  27. #include <rtdevice.h>
  28. #include <sys/socket.h>
  29. #include <at.h>
  30. #include <at_socket.h>
  31. #if !defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10200
  32. #error "This AT Client version is older, please check and update latest AT Client!"
  33. #endif
  34. #define LOG_TAG "at.sim800c"
  35. #include <at_log.h>
  36. #ifdef AT_DEVICE_SIM800C
  37. #define SIM800C_MODULE_SEND_MAX_SIZE 1000
  38. #define SIM800C_WAIT_CONNECT_TIME 5000
  39. #define SIM800C_THREAD_STACK_SIZE 1024
  40. #define SIM800C_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX/2)
  41. /* set real event by current socket and current state */
  42. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  43. /* AT socket event type */
  44. #define SIM800C_EVENT_CONN_OK (1L << 0)
  45. #define SIM800C_EVENT_SEND_OK (1L << 1)
  46. #define SIM800C_EVENT_RECV_OK (1L << 2)
  47. #define SIM800C_EVNET_CLOSE_OK (1L << 3)
  48. #define SIM800C_EVENT_CONN_FAIL (1L << 4)
  49. #define SIM800C_EVENT_SEND_FAIL (1L << 5)
  50. /* AT+CSTT command default*/
  51. char *CSTT_CHINA_MOBILE = "AT+CSTT=\"CMNET\"";
  52. char *CSTT_CHINA_UNICOM = "AT+CSTT=\"UNINET\"";
  53. char *CSTT_CHINA_TELECOM = "AT+CSTT=\"CTNET\"";
  54. static int cur_socket;
  55. static rt_event_t at_socket_event;
  56. static rt_mutex_t at_event_lock;
  57. static at_evt_cb_t at_evt_cb_set[] = {
  58. [AT_SOCKET_EVT_RECV] = NULL,
  59. [AT_SOCKET_EVT_CLOSED] = NULL,
  60. };
  61. static int at_socket_event_send(uint32_t event)
  62. {
  63. return (int) rt_event_send(at_socket_event, event);
  64. }
  65. static int at_socket_event_recv(uint32_t event, uint32_t timeout, rt_uint8_t option)
  66. {
  67. int result = 0;
  68. rt_uint32_t recved;
  69. result = rt_event_recv(at_socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  70. if (result != RT_EOK)
  71. {
  72. return -RT_ETIMEOUT;
  73. }
  74. return recved;
  75. }
  76. /**
  77. * close socket by AT commands.
  78. *
  79. * @param current socket
  80. *
  81. * @return 0: close socket success
  82. * -1: send AT commands error
  83. * -2: wait socket event timeout
  84. * -5: no memory
  85. */
  86. static int sim800c_socket_close(int socket)
  87. {
  88. int result = 0;
  89. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  90. cur_socket = socket;
  91. if (at_exec_cmd(RT_NULL, "AT+CIPCLOSE=%d", socket) < 0)
  92. {
  93. result = -RT_ERROR;
  94. goto __exit;
  95. }
  96. if (at_socket_event_recv(SET_EVENT(socket, SIM800C_EVNET_CLOSE_OK), rt_tick_from_millisecond(300*3), RT_EVENT_FLAG_AND) < 0)
  97. {
  98. LOG_E("socket (%d) close failed, wait close OK timeout.", socket);
  99. result = -RT_ETIMEOUT;
  100. goto __exit;
  101. }
  102. __exit:
  103. rt_mutex_release(at_event_lock);
  104. return result;
  105. }
  106. /**
  107. * create TCP/UDP client or server connect by AT commands.
  108. *
  109. * @param socket current socket
  110. * @param ip server or client IP address
  111. * @param port server or client port
  112. * @param type connect socket type(tcp, udp)
  113. * @param is_client connection is client
  114. *
  115. * @return 0: connect success
  116. * -1: connect failed, send commands error or type error
  117. * -2: wait socket event timeout
  118. * -5: no memory
  119. */
  120. static int sim800c_socket_connect(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  121. {
  122. int result = 0, event_result = 0;
  123. rt_bool_t retryed = RT_FALSE;
  124. RT_ASSERT(ip);
  125. RT_ASSERT(port >= 0);
  126. /* lock AT socket connect */
  127. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  128. __retry:
  129. if (is_client)
  130. {
  131. switch (type)
  132. {
  133. case AT_SOCKET_TCP:
  134. /* send AT commands(eg: AT+QIOPEN=0,"TCP","x.x.x.x", 1234) to connect TCP server */
  135. if (at_exec_cmd(RT_NULL, "AT+CIPSTART=%d,\"TCP\",\"%s\",%d", socket, ip, port) < 0)
  136. {
  137. result = -RT_ERROR;
  138. goto __exit;
  139. }
  140. break;
  141. case AT_SOCKET_UDP:
  142. if (at_exec_cmd(RT_NULL, "AT+CIPSTART=%d,\"UDP\",\"%s\",%d", socket, ip, port) < 0)
  143. {
  144. result = -RT_ERROR;
  145. goto __exit;
  146. }
  147. break;
  148. default:
  149. LOG_E("Not supported connect type : %d.", type);
  150. result = -RT_ERROR;
  151. goto __exit;
  152. break;
  153. }
  154. }
  155. /* waiting result event from AT URC, the device default connection timeout is 75 seconds, but it set to 10 seconds is convenient to use.*/
  156. if (at_socket_event_recv(SET_EVENT(socket, 0), rt_tick_from_millisecond(10 * 1000), RT_EVENT_FLAG_OR) < 0)
  157. {
  158. LOG_E("socket (%d) connect failed, wait connect result timeout.", socket);
  159. result = -RT_ETIMEOUT;
  160. goto __exit;
  161. }
  162. /* waiting OK or failed result */
  163. if ((event_result = at_socket_event_recv(SIM800C_EVENT_CONN_OK | SIM800C_EVENT_CONN_FAIL, rt_tick_from_millisecond(1 * 1000),
  164. RT_EVENT_FLAG_OR)) < 0)
  165. {
  166. LOG_E("socket (%d) connect failed, wait connect OK|FAIL timeout.", socket);
  167. result = -RT_ETIMEOUT;
  168. goto __exit;
  169. }
  170. /* check result */
  171. if (event_result & SIM800C_EVENT_CONN_FAIL)
  172. {
  173. if (!retryed)
  174. {
  175. LOG_E("socket (%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", socket);
  176. if (sim800c_socket_close(socket) < 0)
  177. {
  178. goto __exit;
  179. }
  180. retryed = RT_TRUE;
  181. goto __retry;
  182. }
  183. LOG_E("socket (%d) connect failed, failed to establish a connection.", socket);
  184. result = -RT_ERROR;
  185. goto __exit;
  186. }
  187. __exit:
  188. /* unlock AT socket connect */
  189. rt_mutex_release(at_event_lock);
  190. return result;
  191. }
  192. /**
  193. * send data to server or client by AT commands.
  194. *
  195. * @param socket current socket
  196. * @param buff send buffer
  197. * @param bfsz send buffer size
  198. * @param type connect socket type(tcp, udp)
  199. *
  200. * @return >=0: the size of send success
  201. * -1: send AT commands error or send data error
  202. * -2: waited socket event timeout
  203. * -5: no memory
  204. */
  205. static int sim800c_socket_send(int socket, const char *buff, size_t bfsz, enum at_socket_type type)
  206. {
  207. int result = 0, event_result = 0;
  208. at_response_t resp = RT_NULL;
  209. size_t cur_pkt_size = 0, sent_size = 0;
  210. RT_ASSERT(buff);
  211. resp = at_create_resp(128, 2, rt_tick_from_millisecond(5000));
  212. if (!resp)
  213. {
  214. LOG_E("No memory for response structure!");
  215. return -RT_ENOMEM;
  216. }
  217. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  218. /* set current socket for send URC event */
  219. cur_socket = socket;
  220. /* set AT client end sign to deal with '>' sign.*/
  221. at_set_end_sign('>');
  222. while (sent_size < bfsz)
  223. {
  224. if (bfsz - sent_size < SIM800C_MODULE_SEND_MAX_SIZE)
  225. {
  226. cur_pkt_size = bfsz - sent_size;
  227. }
  228. else
  229. {
  230. cur_pkt_size = SIM800C_MODULE_SEND_MAX_SIZE;
  231. }
  232. /* send the "AT+QISEND" commands to AT server than receive the '>' response on the first line. */
  233. if (at_exec_cmd(resp, "AT+CIPSEND=%d,%d", socket, cur_pkt_size) < 0)
  234. {
  235. result = -RT_ERROR;
  236. goto __exit;
  237. }
  238. /* send the real data to server or client */
  239. result = (int) at_client_send(buff + sent_size, cur_pkt_size);
  240. if (result == 0)
  241. {
  242. result = -RT_ERROR;
  243. goto __exit;
  244. }
  245. /* waiting result event from AT URC */
  246. if (at_socket_event_recv(SET_EVENT(socket, 0), rt_tick_from_millisecond(5 * 1000), RT_EVENT_FLAG_OR) < 0)
  247. {
  248. LOG_E("socket (%d) send failed, wait connect result timeout.", socket);
  249. result = -RT_ETIMEOUT;
  250. goto __exit;
  251. }
  252. /* waiting OK or failed result */
  253. if ((event_result = at_socket_event_recv(SIM800C_EVENT_SEND_OK | SIM800C_EVENT_SEND_FAIL, rt_tick_from_millisecond(5 * 1000),
  254. RT_EVENT_FLAG_OR)) < 0)
  255. {
  256. LOG_E("socket (%d) send failed, wait connect OK|FAIL timeout.", socket);
  257. result = -RT_ETIMEOUT;
  258. goto __exit;
  259. }
  260. /* check result */
  261. if (event_result & SIM800C_EVENT_SEND_FAIL)
  262. {
  263. LOG_E("socket (%d) send failed, return failed.", socket);
  264. result = -RT_ERROR;
  265. goto __exit;
  266. }
  267. if (type == AT_SOCKET_TCP)
  268. {
  269. //cur_pkt_size = cur_send_bfsz;
  270. }
  271. sent_size += cur_pkt_size;
  272. }
  273. __exit:
  274. /* reset the end sign for data conflict */
  275. at_set_end_sign(0);
  276. rt_mutex_release(at_event_lock);
  277. if (resp)
  278. {
  279. at_delete_resp(resp);
  280. }
  281. return result;
  282. }
  283. /**
  284. * domain resolve by AT commands.
  285. *
  286. * @param name domain name
  287. * @param ip parsed IP address, it's length must be 16
  288. *
  289. * @return 0: domain resolve success
  290. * -1: send AT commands error or response error
  291. * -2: wait socket event timeout
  292. * -5: no memory
  293. */
  294. static int sim800c_domain_resolve(const char *name, char ip[16])
  295. {
  296. #define RESOLVE_RETRY 5
  297. int i, result = RT_EOK;
  298. char recv_ip[16] = { 0 };
  299. at_response_t resp = RT_NULL;
  300. RT_ASSERT(name);
  301. RT_ASSERT(ip);
  302. /* The maximum response time is 14 seconds, affected by network status */
  303. resp = at_create_resp(128, 4, rt_tick_from_millisecond(14 * 1000));
  304. if (!resp)
  305. {
  306. LOG_E("No memory for response structure!");
  307. return -RT_ENOMEM;
  308. }
  309. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  310. for(i = 0; i < RESOLVE_RETRY; i++)
  311. {
  312. if (at_exec_cmd(resp, "AT+CDNSGIP=\"%s\"", name) < 0)
  313. {
  314. result = -RT_ERROR;
  315. goto __exit;
  316. }
  317. /* parse the third line of response data, get the IP address */
  318. if(at_resp_parse_line_args_by_kw(resp, "+CDNSGIP:", "%*[^,],%*[^,],\"%[^\"]", recv_ip) < 0)
  319. {
  320. rt_thread_delay(rt_tick_from_millisecond(100));
  321. /* resolve failed, maybe receive an URC CRLF */
  322. continue;
  323. }
  324. if (strlen(recv_ip) < 8)
  325. {
  326. rt_thread_delay(rt_tick_from_millisecond(100));
  327. /* resolve failed, maybe receive an URC CRLF */
  328. continue;
  329. }
  330. else
  331. {
  332. strncpy(ip, recv_ip, 15);
  333. ip[15] = '\0';
  334. //LOG_I("DNS IP:%s",ip);
  335. break;
  336. }
  337. }
  338. __exit:
  339. rt_mutex_release(at_event_lock);
  340. if (resp)
  341. {
  342. at_delete_resp(resp);
  343. }
  344. return result;
  345. }
  346. /**
  347. * set AT socket event notice callback
  348. *
  349. * @param event notice event
  350. * @param cb notice callback
  351. */
  352. static void sim800c_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  353. {
  354. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  355. {
  356. at_evt_cb_set[event] = cb;
  357. }
  358. }
  359. static void urc_connect_func(const char *data, rt_size_t size)
  360. {
  361. int socket = 0;
  362. RT_ASSERT(data && size);
  363. sscanf(data, "%d,%*", &socket);
  364. if (strstr(data, "CONNECT OK"))
  365. {
  366. at_socket_event_send(SET_EVENT(socket, SIM800C_EVENT_CONN_OK));
  367. }
  368. else if (strstr(data, "CONNECT FAIL"))
  369. {
  370. at_socket_event_send(SET_EVENT(socket, SIM800C_EVENT_CONN_FAIL));
  371. }
  372. }
  373. static void urc_send_func(const char *data, rt_size_t size)
  374. {
  375. RT_ASSERT(data && size);
  376. if (strstr(data, "SEND OK"))
  377. {
  378. at_socket_event_send(SET_EVENT(cur_socket, SIM800C_EVENT_SEND_OK));
  379. }
  380. else if (strstr(data, "SEND FAIL"))
  381. {
  382. at_socket_event_send(SET_EVENT(cur_socket, SIM800C_EVENT_SEND_FAIL));
  383. }
  384. }
  385. static void urc_close_func(const char *data, rt_size_t size)
  386. {
  387. int socket = 0;
  388. RT_ASSERT(data && size);
  389. if (strstr(data, "CLOSE OK"))
  390. {
  391. at_socket_event_send(SET_EVENT(cur_socket, SIM800C_EVNET_CLOSE_OK));
  392. }
  393. else if (strstr(data, "CLOSED"))
  394. {
  395. sscanf(data, "%d, CLOSED", &socket);
  396. /* notice the socket is disconnect by remote */
  397. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  398. {
  399. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, NULL, 0);
  400. }
  401. }
  402. }
  403. static void urc_recv_func(const char *data, rt_size_t size)
  404. {
  405. int socket = 0;
  406. rt_size_t bfsz = 0, temp_size = 0;
  407. rt_int32_t timeout;
  408. char *recv_buf = RT_NULL, temp[8];
  409. RT_ASSERT(data && size);
  410. /* get the current socket and receive buffer size by receive data */
  411. sscanf(data, "+RECEIVE,%d,%d:", &socket, (int *) &bfsz);
  412. /* get receive timeout by receive buffer length */
  413. timeout = bfsz;
  414. if (socket < 0 || bfsz == 0)
  415. return;
  416. recv_buf = rt_calloc(1, bfsz);
  417. if (!recv_buf)
  418. {
  419. LOG_E("no memory for URC receive buffer (%d)!", bfsz);
  420. /* read and clean the coming data */
  421. while (temp_size < bfsz)
  422. {
  423. if (bfsz - temp_size > sizeof(temp))
  424. {
  425. at_client_recv(temp, sizeof(temp), timeout);
  426. }
  427. else
  428. {
  429. at_client_recv(temp, bfsz - temp_size, timeout);
  430. }
  431. temp_size += sizeof(temp);
  432. }
  433. return;
  434. }
  435. /* sync receive data */
  436. if (at_client_recv(recv_buf, bfsz, timeout) != bfsz)
  437. {
  438. LOG_E("receive size(%d) data failed!", bfsz);
  439. rt_free(recv_buf);
  440. return;
  441. }
  442. /* notice the receive buffer and buffer size */
  443. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  444. {
  445. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  446. }
  447. }
  448. static void urc_func(const char *data, rt_size_t size)
  449. {
  450. RT_ASSERT(data);
  451. LOG_I("URC data : %.*s", size, data);
  452. }
  453. static const struct at_urc urc_table[] = {
  454. {"RDY", "\r\n", urc_func},
  455. {"", ", CONNECT OK\r\n", urc_connect_func},
  456. {"", ", CONNECT FAIL\r\n", urc_connect_func},
  457. {"", ", SEND OK\r\n", urc_send_func},
  458. {"", ", SEND FAIL\r\n", urc_send_func},
  459. {"", ", CLOSE OK\r\n", urc_close_func},
  460. {"", ", CLOSED\r\n", urc_close_func},
  461. {"+RECEIVE,", "\r\n", urc_recv_func},
  462. };
  463. #define AT_SEND_CMD(resp, resp_line, timeout, cmd) \
  464. do \
  465. { \
  466. if (at_exec_cmd(at_resp_set_info(resp, 128, resp_line, rt_tick_from_millisecond(timeout)), cmd) < 0) \
  467. { \
  468. result = -RT_ERROR; \
  469. goto __exit; \
  470. } \
  471. } while(0); \
  472. static void sim800c_power_on(void)
  473. {
  474. if (rt_pin_read(AT_DEVICE_STATUS_PIN) == PIN_HIGH)
  475. return;
  476. rt_pin_write(AT_DEVICE_POWER_PIN, PIN_HIGH);
  477. while (rt_pin_read(AT_DEVICE_STATUS_PIN) == PIN_LOW)
  478. {
  479. rt_thread_delay(rt_tick_from_millisecond(10));
  480. }
  481. rt_pin_write(AT_DEVICE_POWER_PIN, PIN_LOW);
  482. }
  483. static void sim800c_power_off(void)
  484. {
  485. if (rt_pin_read(AT_DEVICE_STATUS_PIN) == PIN_LOW)
  486. return;
  487. rt_pin_write(AT_DEVICE_POWER_PIN, PIN_HIGH);
  488. while (rt_pin_read(AT_DEVICE_STATUS_PIN) == PIN_HIGH)
  489. {
  490. rt_thread_delay(rt_tick_from_millisecond(10));
  491. }
  492. rt_pin_write(AT_DEVICE_POWER_PIN, PIN_LOW);
  493. }
  494. /* init for SIM800C */
  495. static void sim800c_init_thread_entry(void *parameter)
  496. {
  497. #define CPIN_RETRY 10
  498. #define CSQ_RETRY 10
  499. #define CREG_RETRY 10
  500. #define CGREG_RETRY 20
  501. at_response_t resp = RT_NULL;
  502. int i, qimux;
  503. char parsed_data[10];
  504. rt_err_t result = RT_EOK;
  505. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  506. while (1)
  507. {
  508. result = RT_EOK;
  509. rt_memset(parsed_data, 0, sizeof(parsed_data));
  510. rt_thread_delay(rt_tick_from_millisecond(500));
  511. sim800c_power_on();
  512. rt_thread_delay(rt_tick_from_millisecond(2000));
  513. resp = at_create_resp(128, 0, rt_tick_from_millisecond(300));
  514. if (!resp)
  515. {
  516. LOG_E("No memory for response structure!");
  517. result = -RT_ENOMEM;
  518. goto __exit;
  519. }
  520. LOG_D("Start initializing the SIM800C module");
  521. /* wait SIM800C startup finish */
  522. if (at_client_wait_connect(SIM800C_WAIT_CONNECT_TIME))
  523. {
  524. result = -RT_ETIMEOUT;
  525. goto __exit;
  526. }
  527. /* disable echo */
  528. AT_SEND_CMD(resp, 0, 300, "ATE0");
  529. /* get module version */
  530. AT_SEND_CMD(resp, 0, 300, "ATI");
  531. /* show module version */
  532. for (i = 0; i < (int)resp->line_counts - 1; i++)
  533. {
  534. LOG_D("%s", at_resp_get_line(resp, i + 1));
  535. }
  536. /* check SIM card */
  537. for (i = 0; i < CPIN_RETRY; i++)
  538. {
  539. at_exec_cmd(at_resp_set_info(resp, 128, 2, rt_tick_from_millisecond(5000)), "AT+CPIN?");
  540. if (at_resp_get_line_by_kw(resp, "READY"))
  541. {
  542. LOG_D("SIM card detection success");
  543. break;
  544. }
  545. rt_thread_delay(rt_tick_from_millisecond(1000));
  546. }
  547. if (i == CPIN_RETRY)
  548. {
  549. LOG_E("SIM card detection failed!");
  550. result = -RT_ERROR;
  551. goto __exit;
  552. }
  553. /* waiting for dirty data to be digested */
  554. rt_thread_delay(rt_tick_from_millisecond(10));
  555. /* check the GSM network is registered */
  556. for (i = 0; i < CREG_RETRY; i++)
  557. {
  558. AT_SEND_CMD(resp, 0, 300, "AT+CREG?");
  559. at_resp_parse_line_args_by_kw(resp, "+CREG:", "+CREG: %s", &parsed_data);
  560. if (!strncmp(parsed_data, "0,1", sizeof(parsed_data)) || !strncmp(parsed_data, "0,5", sizeof(parsed_data)))
  561. {
  562. LOG_D("GSM network is registered (%s)", parsed_data);
  563. break;
  564. }
  565. rt_thread_delay(rt_tick_from_millisecond(1000));
  566. }
  567. if (i == CREG_RETRY)
  568. {
  569. LOG_E("The GSM network is register failed (%s)", parsed_data);
  570. result = -RT_ERROR;
  571. goto __exit;
  572. }
  573. /* check the GPRS network is registered */
  574. for (i = 0; i < CGREG_RETRY; i++)
  575. {
  576. AT_SEND_CMD(resp, 0, 300, "AT+CGREG?");
  577. at_resp_parse_line_args_by_kw(resp, "+CGREG:", "+CGREG: %s", &parsed_data);
  578. if (!strncmp(parsed_data, "0,1", sizeof(parsed_data)) || !strncmp(parsed_data, "0,5", sizeof(parsed_data)))
  579. {
  580. LOG_D("GPRS network is registered (%s)", parsed_data);
  581. break;
  582. }
  583. rt_thread_delay(rt_tick_from_millisecond(1000));
  584. }
  585. if (i == CGREG_RETRY)
  586. {
  587. LOG_E("The GPRS network is register failed (%s)", parsed_data);
  588. result = -RT_ERROR;
  589. goto __exit;
  590. }
  591. /* check signal strength */
  592. for (i = 0; i < CSQ_RETRY; i++)
  593. {
  594. AT_SEND_CMD(resp, 0, 300, "AT+CSQ");
  595. at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ: %s", &parsed_data);
  596. if (strncmp(parsed_data, "99,99", sizeof(parsed_data)))
  597. {
  598. LOG_D("Signal strength: %s", parsed_data);
  599. break;
  600. }
  601. rt_thread_delay(rt_tick_from_millisecond(1000));
  602. }
  603. if (i == CSQ_RETRY)
  604. {
  605. LOG_E("Signal strength check failed (%s)", parsed_data);
  606. result = -RT_ERROR;
  607. goto __exit;
  608. }
  609. /* the device default response timeout is 40 seconds, but it set to 15 seconds is convenient to use. */
  610. AT_SEND_CMD(resp, 2, 20 * 1000, "AT+CIPSHUT");
  611. /* Set to multiple connections */
  612. AT_SEND_CMD(resp, 0, 300, "AT+CIPMUX?");
  613. at_resp_parse_line_args_by_kw(resp, "+CIPMUX:", "+CIPMUX: %d", &qimux);
  614. if (qimux == 0)
  615. {
  616. AT_SEND_CMD(resp, 0, 300, "AT+CIPMUX=1");
  617. }
  618. AT_SEND_CMD(resp, 0, 300, "AT+COPS?");
  619. at_resp_parse_line_args_by_kw(resp, "+COPS:", "+COPS: %*[^\"]\"%[^\"]", &parsed_data);
  620. if (strcmp(parsed_data, "CHINA MOBILE") == 0)
  621. {
  622. /* "CMCC" */
  623. LOG_I("%s", parsed_data);
  624. AT_SEND_CMD(resp, 0, 300, CSTT_CHINA_MOBILE);
  625. }
  626. else if (strcmp(parsed_data, "CHN-UNICOM") == 0)
  627. {
  628. /* "UNICOM" */
  629. LOG_I("%s", parsed_data);
  630. AT_SEND_CMD(resp, 0, 300, CSTT_CHINA_UNICOM);
  631. }
  632. else if (strcmp(parsed_data, "CHN-CT") == 0)
  633. {
  634. AT_SEND_CMD(resp, 0, 300, CSTT_CHINA_TELECOM);
  635. /* "CT" */
  636. LOG_I("%s", parsed_data);
  637. }
  638. /* the device default response timeout is 150 seconds, but it set to 20 seconds is convenient to use. */
  639. AT_SEND_CMD(resp, 0, 20 * 1000, "AT+CIICR");
  640. AT_SEND_CMD(resp, 2, 300, "AT+CIFSR");
  641. if(at_resp_get_line_by_kw(resp, "ERROR") != RT_NULL)
  642. {
  643. LOG_E("Get the local address failed");
  644. result = -RT_ERROR;
  645. goto __exit;
  646. }
  647. __exit:
  648. if (resp)
  649. {
  650. at_delete_resp(resp);
  651. }
  652. if (!result)
  653. {
  654. LOG_I("AT network initialize success!");
  655. rt_mutex_release(at_event_lock);
  656. break;
  657. }
  658. else
  659. {
  660. LOG_E("AT network initialize failed (%d)!", result);
  661. sim800c_power_off();
  662. }
  663. }
  664. }
  665. int sim800c_net_init(void)
  666. {
  667. #ifdef PKG_AT_INIT_BY_THREAD
  668. rt_thread_t tid;
  669. tid = rt_thread_create("sim800c_net_init", sim800c_init_thread_entry, RT_NULL, SIM800C_THREAD_STACK_SIZE, SIM800C_THREAD_PRIORITY, 20);
  670. if (tid)
  671. {
  672. rt_thread_startup(tid);
  673. }
  674. else
  675. {
  676. LOG_E("Create AT initialization thread fail!");
  677. }
  678. #else
  679. sim800c_init_thread_entry(RT_NULL);
  680. #endif
  681. return RT_EOK;
  682. }
  683. int sim800c_ping(int argc, char **argv)
  684. {
  685. LOG_E("This device does not support Ping!");
  686. return RT_EOK;
  687. }
  688. int sim800c_ifconfig(void)
  689. {
  690. at_response_t resp = RT_NULL;
  691. char resp_arg[AT_CMD_MAX_LEN] = { 0 };
  692. const char * resp_expr = "%s";
  693. rt_err_t result = RT_EOK;
  694. resp = at_create_resp(64, 2, rt_tick_from_millisecond(300));
  695. if (!resp)
  696. {
  697. rt_kprintf("No memory for response structure!\n");
  698. return -RT_ENOMEM;
  699. }
  700. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  701. if (at_exec_cmd(resp, "AT+CIFSR") < 0)
  702. {
  703. rt_kprintf("AT send ip commands error!\n");
  704. result = RT_ERROR;
  705. goto __exit;
  706. }
  707. if (at_resp_parse_line_args(resp, 2, resp_expr, resp_arg) == 1)
  708. {
  709. rt_kprintf("IP address : %s\n", resp_arg);
  710. }
  711. else
  712. {
  713. rt_kprintf("Parse error, current line buff : %s\n", at_resp_get_line(resp, 2));
  714. result = RT_ERROR;
  715. goto __exit;
  716. }
  717. __exit:
  718. rt_mutex_release(at_event_lock);
  719. if (resp)
  720. {
  721. at_delete_resp(resp);
  722. }
  723. return result;
  724. }
  725. #ifdef FINSH_USING_MSH
  726. #include <finsh.h>
  727. MSH_CMD_EXPORT_ALIAS(sim800c_net_init, at_net_init, initialize AT network);
  728. MSH_CMD_EXPORT_ALIAS(sim800c_ping, at_ping, AT ping network host);
  729. MSH_CMD_EXPORT_ALIAS(sim800c_ifconfig, at_ifconfig, list the information of network interfaces);
  730. #endif
  731. static const struct at_device_ops sim800c_socket_ops = {
  732. sim800c_socket_connect,
  733. sim800c_socket_close,
  734. sim800c_socket_send,
  735. sim800c_domain_resolve,
  736. sim800c_socket_set_event_cb,
  737. };
  738. static int at_socket_device_init(void)
  739. {
  740. /* create current AT socket event */
  741. at_socket_event = rt_event_create("at_se", RT_IPC_FLAG_FIFO);
  742. if (at_socket_event == RT_NULL)
  743. {
  744. LOG_E("AT client port initialize failed! at_sock_event create failed!");
  745. return -RT_ENOMEM;
  746. }
  747. /* create current AT socket event lock */
  748. at_event_lock = rt_mutex_create("at_se", RT_IPC_FLAG_FIFO);
  749. if (at_event_lock == RT_NULL)
  750. {
  751. LOG_E("AT client port initialize failed! at_sock_lock create failed!");
  752. rt_event_delete(at_socket_event);
  753. return -RT_ENOMEM;
  754. }
  755. /* initialize AT client */
  756. at_client_init(AT_DEVICE_NAME, AT_DEVICE_RECV_BUFF_LEN);
  757. /* register URC data execution function */
  758. at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  759. /* initialize sim800c network */
  760. rt_pin_mode(AT_DEVICE_POWER_PIN, PIN_MODE_OUTPUT);
  761. rt_pin_mode(AT_DEVICE_STATUS_PIN, PIN_MODE_INPUT);
  762. sim800c_net_init();
  763. /* set sim800c AT Socket options */
  764. at_socket_device_register(&sim800c_socket_ops);
  765. return RT_EOK;
  766. }
  767. INIT_APP_EXPORT(at_socket_device_init);
  768. #endif /* AT_DEVICE_SIM800C */