at_socket_esp8266.c 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. /*
  2. * File : at_socket_esp8266.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-20 chenyong first version
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <rtthread.h>
  27. #include <sys/socket.h>
  28. #include <at.h>
  29. #include <at_socket.h>
  30. #if !defined(RT_USING_NETDEV)
  31. #error "This RT-Thread version is older, please check and updata laster RT-Thread!"
  32. #else
  33. #include <arpa/inet.h>
  34. #include <netdev.h>
  35. #endif /* RT_USING_NETDEV */
  36. #if !defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10200
  37. #error "This AT Client version is older, please check and update latest AT Client!"
  38. #endif
  39. #define LOG_TAG "at.esp8266"
  40. #include <at_log.h>
  41. #ifdef AT_DEVICE_ESP8266
  42. #define ESP8266_MODULE_SEND_MAX_SIZE 2048
  43. #define ESP8266_WAIT_CONNECT_TIME 5000
  44. #define ESP8266_THREAD_STACK_SIZE 1024
  45. #define ESP8266_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX/2)
  46. /* set real event by current socket and current state */
  47. #define SET_EVENT(socket, event) (((socket + 1) << 16) | (event))
  48. /* AT socket event type */
  49. #define ESP8266_EVENT_CONN_OK (1L << 0)
  50. #define ESP8266_EVENT_SEND_OK (1L << 1)
  51. #define ESP8266_EVENT_RECV_OK (1L << 2)
  52. #define ESP8266_EVNET_CLOSE_OK (1L << 3)
  53. #define ESP8266_EVENT_CONN_FAIL (1L << 4)
  54. #define ESP8266_EVENT_SEND_FAIL (1L << 5)
  55. #define ESP8266_NETDEV_NAME "esp8266"
  56. static int cur_socket;
  57. static int cur_send_bfsz;
  58. static struct rt_delayed_work esp8266_net_work;
  59. static rt_event_t at_socket_event;
  60. static rt_mutex_t at_event_lock;
  61. static at_evt_cb_t at_evt_cb_set[] = {
  62. [AT_SOCKET_EVT_RECV] = NULL,
  63. [AT_SOCKET_EVT_CLOSED] = NULL,
  64. };
  65. static int at_socket_event_send(uint32_t event)
  66. {
  67. return (int) rt_event_send(at_socket_event, event);
  68. }
  69. static int at_socket_event_recv(uint32_t event, uint32_t timeout, rt_uint8_t option)
  70. {
  71. int result = 0;
  72. rt_uint32_t recved;
  73. result = rt_event_recv(at_socket_event, event, option | RT_EVENT_FLAG_CLEAR, timeout, &recved);
  74. if (result != RT_EOK)
  75. {
  76. return -RT_ETIMEOUT;
  77. }
  78. return recved;
  79. }
  80. /**
  81. * close socket by AT commands.
  82. *
  83. * @param current socket
  84. *
  85. * @return 0: close socket success
  86. * -1: send AT commands error
  87. * -2: wait socket event timeout
  88. * -5: no memory
  89. */
  90. static int esp8266_socket_close(int socket)
  91. {
  92. at_response_t resp = RT_NULL;
  93. int result = RT_EOK;
  94. resp = at_create_resp(64, 0, rt_tick_from_millisecond(5000));
  95. if (!resp)
  96. {
  97. LOG_E("No memory for response structure!");
  98. return -RT_ENOMEM;
  99. }
  100. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  101. if (at_exec_cmd(resp, "AT+CIPCLOSE=%d", socket) < 0)
  102. {
  103. result = -RT_ERROR;
  104. goto __exit;
  105. }
  106. __exit:
  107. rt_mutex_release(at_event_lock);
  108. if (resp)
  109. {
  110. at_delete_resp(resp);
  111. }
  112. return result;
  113. }
  114. /**
  115. * create TCP/UDP client or server connect by AT commands.
  116. *
  117. * @param socket current socket
  118. * @param ip server or client IP address
  119. * @param port server or client port
  120. * @param type connect socket type(tcp, udp)
  121. * @param is_client connection is client
  122. *
  123. * @return 0: connect success
  124. * -1: connect failed, send commands error or type error
  125. * -2: wait socket event timeout
  126. * -5: no memory
  127. */
  128. static int esp8266_socket_connect(int socket, char *ip, int32_t port, enum at_socket_type type, rt_bool_t is_client)
  129. {
  130. at_response_t resp = RT_NULL;
  131. int result = RT_EOK;
  132. rt_bool_t retryed = RT_FALSE;
  133. RT_ASSERT(ip);
  134. RT_ASSERT(port >= 0);
  135. resp = at_create_resp(128, 0, rt_tick_from_millisecond(5000));
  136. if (!resp)
  137. {
  138. LOG_E("No memory for response structure!");
  139. return -RT_ENOMEM;
  140. }
  141. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  142. __retry:
  143. if (is_client)
  144. {
  145. switch (type)
  146. {
  147. case AT_SOCKET_TCP:
  148. /* send AT commands to connect TCP server */
  149. if (at_exec_cmd(resp, "AT+CIPSTART=%d,\"TCP\",\"%s\",%d,60", socket, ip, port) < 0)
  150. {
  151. result = -RT_ERROR;
  152. }
  153. break;
  154. case AT_SOCKET_UDP:
  155. if (at_exec_cmd(resp, "AT+CIPSTART=%d,\"UDP\",\"%s\",%d", socket, ip, port) < 0)
  156. {
  157. result = -RT_ERROR;
  158. }
  159. break;
  160. default:
  161. LOG_E("Not supported connect type : %d.", type);
  162. result = -RT_ERROR;
  163. goto __exit;
  164. }
  165. }
  166. if (result != RT_EOK && !retryed)
  167. {
  168. LOG_D("socket (%d) connect failed, maybe the socket was not be closed at the last time and now will retry.", socket);
  169. if (esp8266_socket_close(socket) < 0)
  170. {
  171. goto __exit;
  172. }
  173. retryed = RT_TRUE;
  174. result = RT_EOK;
  175. goto __retry;
  176. }
  177. __exit:
  178. rt_mutex_release(at_event_lock);
  179. if (resp)
  180. {
  181. at_delete_resp(resp);
  182. }
  183. return result;
  184. }
  185. /**
  186. * send data to server or client by AT commands.
  187. *
  188. * @param socket current socket
  189. * @param buff send buffer
  190. * @param bfsz send buffer size
  191. * @param type connect socket type(tcp, udp)
  192. *
  193. * @return >=0: the size of send success
  194. * -1: send AT commands error or send data error
  195. * -2: waited socket event timeout
  196. * -5: no memory
  197. */
  198. static int esp8266_socket_send(int socket, const char *buff, size_t bfsz, enum at_socket_type type)
  199. {
  200. int result = RT_EOK;
  201. int event_result = 0;
  202. at_response_t resp = RT_NULL;
  203. size_t cur_pkt_size = 0, sent_size = 0;
  204. RT_ASSERT(buff);
  205. RT_ASSERT(bfsz > 0);
  206. resp = at_create_resp(128, 2, rt_tick_from_millisecond(5000));
  207. if (!resp)
  208. {
  209. LOG_E("No memory for response structure!");
  210. return -RT_ENOMEM;
  211. }
  212. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  213. /* set current socket for send URC event */
  214. cur_socket = socket;
  215. /* set AT client end sign to deal with '>' sign.*/
  216. at_set_end_sign('>');
  217. while (sent_size < bfsz)
  218. {
  219. if (bfsz - sent_size < ESP8266_MODULE_SEND_MAX_SIZE)
  220. {
  221. cur_pkt_size = bfsz - sent_size;
  222. }
  223. else
  224. {
  225. cur_pkt_size = ESP8266_MODULE_SEND_MAX_SIZE;
  226. }
  227. /* send the "AT+CIPSEND" commands to AT server than receive the '>' response on the first line. */
  228. if (at_exec_cmd(resp, "AT+CIPSEND=%d,%d", socket, cur_pkt_size) < 0)
  229. {
  230. result = -RT_ERROR;
  231. goto __exit;
  232. }
  233. /* send the real data to server or client */
  234. result = (int) at_client_send(buff + sent_size, cur_pkt_size);
  235. if (result == 0)
  236. {
  237. result = -RT_ERROR;
  238. goto __exit;
  239. }
  240. /* waiting result event from AT URC */
  241. if (at_socket_event_recv(SET_EVENT(socket, 0), rt_tick_from_millisecond(5 * 1000), RT_EVENT_FLAG_OR) < 0)
  242. {
  243. LOG_E("socket (%d) send failed, wait connect result timeout.", socket);
  244. result = -RT_ETIMEOUT;
  245. goto __exit;
  246. }
  247. /* waiting OK or failed result */
  248. if ((event_result = at_socket_event_recv(ESP8266_EVENT_SEND_OK | ESP8266_EVENT_SEND_FAIL, rt_tick_from_millisecond(5 * 1000),
  249. RT_EVENT_FLAG_OR)) < 0)
  250. {
  251. LOG_E("socket (%d) send failed, wait connect OK|FAIL timeout.", socket);
  252. result = -RT_ETIMEOUT;
  253. goto __exit;
  254. }
  255. /* check result */
  256. if (event_result & ESP8266_EVENT_SEND_FAIL)
  257. {
  258. LOG_E("socket (%d) send failed, return failed.", socket);
  259. result = -RT_ERROR;
  260. goto __exit;
  261. }
  262. if (type == AT_SOCKET_TCP)
  263. {
  264. cur_pkt_size = cur_send_bfsz;
  265. }
  266. sent_size += cur_pkt_size;
  267. }
  268. __exit:
  269. /* reset the end sign for data */
  270. at_set_end_sign(0);
  271. rt_mutex_release(at_event_lock);
  272. if (resp)
  273. {
  274. at_delete_resp(resp);
  275. }
  276. return result;
  277. }
  278. /**
  279. * domain resolve by AT commands.
  280. *
  281. * @param name domain name
  282. * @param ip parsed IP address, it's length must be 16
  283. *
  284. * @return 0: domain resolve success
  285. * -2: wait socket event timeout
  286. * -5: no memory
  287. */
  288. static int esp8266_domain_resolve(const char *name, char ip[16])
  289. {
  290. #define RESOLVE_RETRY 5
  291. int i, result = RT_EOK;
  292. char recv_ip[16] = { 0 };
  293. at_response_t resp = RT_NULL;
  294. RT_ASSERT(name);
  295. RT_ASSERT(ip);
  296. resp = at_create_resp(128, 0, rt_tick_from_millisecond(20000));
  297. if (!resp)
  298. {
  299. LOG_E("No memory for response structure!");
  300. return -RT_ENOMEM;
  301. }
  302. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  303. for (i = 0; i < RESOLVE_RETRY; i++)
  304. {
  305. if (at_exec_cmd(resp, "AT+CIPDOMAIN=\"%s\"", name) < 0)
  306. {
  307. result = -RT_ERROR;
  308. goto __exit;
  309. }
  310. /* parse the third line of response data, get the IP address */
  311. if (at_resp_parse_line_args_by_kw(resp, "+CIPDOMAIN:", "+CIPDOMAIN:%s", recv_ip) < 0)
  312. {
  313. rt_thread_delay(rt_tick_from_millisecond(100));
  314. /* resolve failed, maybe receive an URC CRLF */
  315. continue;
  316. }
  317. if (strlen(recv_ip) < 8)
  318. {
  319. rt_thread_delay(rt_tick_from_millisecond(100));
  320. /* resolve failed, maybe receive an URC CRLF */
  321. continue;
  322. }
  323. else
  324. {
  325. strncpy(ip, recv_ip, 15);
  326. ip[15] = '\0';
  327. break;
  328. }
  329. }
  330. __exit:
  331. rt_mutex_release(at_event_lock);
  332. if (resp)
  333. {
  334. at_delete_resp(resp);
  335. }
  336. return result;
  337. }
  338. /**
  339. * set AT socket event notice callback
  340. *
  341. * @param event notice event
  342. * @param cb notice callback
  343. */
  344. static void esp8266_socket_set_event_cb(at_socket_evt_t event, at_evt_cb_t cb)
  345. {
  346. if (event < sizeof(at_evt_cb_set) / sizeof(at_evt_cb_set[1]))
  347. {
  348. at_evt_cb_set[event] = cb;
  349. }
  350. }
  351. static void urc_send_func(const char *data, rt_size_t size)
  352. {
  353. RT_ASSERT(data && size);
  354. if (strstr(data, "SEND OK"))
  355. {
  356. at_socket_event_send(SET_EVENT(cur_socket, ESP8266_EVENT_SEND_OK));
  357. }
  358. else if (strstr(data, "SEND FAIL"))
  359. {
  360. at_socket_event_send(SET_EVENT(cur_socket, ESP8266_EVENT_SEND_FAIL));
  361. }
  362. }
  363. static void urc_send_bfsz_func(const char *data, rt_size_t size)
  364. {
  365. int send_bfsz = 0;
  366. RT_ASSERT(data && size);
  367. sscanf(data, "Recv %d bytes", &send_bfsz);
  368. cur_send_bfsz = send_bfsz;
  369. }
  370. static void urc_close_func(const char *data, rt_size_t size)
  371. {
  372. int socket = 0;
  373. RT_ASSERT(data && size);
  374. sscanf(data, "%d,CLOSED", &socket);
  375. /* notice the socket is disconnect by remote */
  376. if (at_evt_cb_set[AT_SOCKET_EVT_CLOSED])
  377. {
  378. at_evt_cb_set[AT_SOCKET_EVT_CLOSED](socket, AT_SOCKET_EVT_CLOSED, RT_NULL, 0);
  379. }
  380. }
  381. static void urc_recv_func(const char *data, rt_size_t size)
  382. {
  383. int socket = 0;
  384. rt_size_t bfsz = 0, temp_size = 0;
  385. rt_int32_t timeout;
  386. char *recv_buf = RT_NULL, temp[8];
  387. RT_ASSERT(data && size);
  388. /* get the current socket and receive buffer size by receive data */
  389. sscanf(data, "+IPD,%d,%d:", &socket, (int *) &bfsz);
  390. /* get receive timeout by receive buffer length */
  391. timeout = bfsz;
  392. if (socket < 0 || bfsz == 0)
  393. return;
  394. recv_buf = rt_calloc(1, bfsz);
  395. if (!recv_buf)
  396. {
  397. LOG_E("no memory for URC receive buffer (%d)!", bfsz);
  398. /* read and clean the coming data */
  399. while (temp_size < bfsz)
  400. {
  401. if (bfsz - temp_size > sizeof(temp))
  402. {
  403. at_client_recv(temp, sizeof(temp), timeout);
  404. }
  405. else
  406. {
  407. at_client_recv(temp, bfsz - temp_size, timeout);
  408. }
  409. temp_size += sizeof(temp);
  410. }
  411. return;
  412. }
  413. /* sync receive data */
  414. if (at_client_recv(recv_buf, bfsz, timeout) != bfsz)
  415. {
  416. LOG_E("receive size(%d) data failed!", bfsz);
  417. rt_free(recv_buf);
  418. return;
  419. }
  420. /* notice the receive buffer and buffer size */
  421. if (at_evt_cb_set[AT_SOCKET_EVT_RECV])
  422. {
  423. at_evt_cb_set[AT_SOCKET_EVT_RECV](socket, AT_SOCKET_EVT_RECV, recv_buf, bfsz);
  424. }
  425. }
  426. static void urc_busy_p_func(const char *data, rt_size_t size)
  427. {
  428. RT_ASSERT(data && size);
  429. LOG_D("system is processing a commands and it cannot respond to the current commands.");
  430. }
  431. static void urc_busy_s_func(const char *data, rt_size_t size)
  432. {
  433. RT_ASSERT(data && size);
  434. LOG_D("system is sending data and it cannot respond to the current commands.");
  435. }
  436. static void urc_func(const char *data, rt_size_t size)
  437. {
  438. RT_ASSERT(data && size);
  439. if (strstr(data, "WIFI CONNECTED"))
  440. {
  441. netdev_low_level_set_link_status(netdev_get_by_name(ESP8266_NETDEV_NAME), RT_TRUE);
  442. rt_work_submit(&(esp8266_net_work.work), RT_TICK_PER_SECOND);
  443. LOG_I("ESP8266 WIFI is connected.");
  444. }
  445. else if (strstr(data, "WIFI DISCONNECT"))
  446. {
  447. netdev_low_level_set_link_status(netdev_get_by_name(ESP8266_NETDEV_NAME), RT_FALSE);
  448. LOG_I("ESP8266 WIFI is disconnect.");
  449. }
  450. }
  451. static struct at_urc urc_table[] = {
  452. {"SEND OK", "\r\n", urc_send_func},
  453. {"SEND FAIL", "\r\n", urc_send_func},
  454. {"Recv", "bytes\r\n", urc_send_bfsz_func},
  455. {"", ",CLOSED\r\n", urc_close_func},
  456. {"+IPD", ":", urc_recv_func},
  457. {"busy p", "\r\n", urc_busy_p_func},
  458. {"busy s", "\r\n", urc_busy_s_func},
  459. {"WIFI CONNECTED", "\r\n", urc_func},
  460. {"WIFI DISCONNECT", "\r\n", urc_func},
  461. };
  462. #define AT_SEND_CMD(resp, cmd) \
  463. do \
  464. { \
  465. if (at_exec_cmd(at_resp_set_info(resp, 256, 0, rt_tick_from_millisecond(5000)), cmd) < 0) \
  466. { \
  467. LOG_E("RT AT send commands(%s) error!", cmd); \
  468. result = -RT_ERROR; \
  469. goto __exit; \
  470. } \
  471. } while(0); \
  472. static void exp8266_get_netdev_info(struct rt_work *work, void *work_data)
  473. {
  474. #define AT_ADDR_LEN 32
  475. at_response_t resp = RT_NULL;
  476. char ip[AT_ADDR_LEN], mac[AT_ADDR_LEN];
  477. char gateway[AT_ADDR_LEN], netmask[AT_ADDR_LEN];
  478. char dns_server1[AT_ADDR_LEN] = {0}, dns_server2[AT_ADDR_LEN] = {0};
  479. const char *resp_expr = "%*[^\"]\"%[^\"]\"";
  480. const char *resp_dns = "+CIPDNS_CUR:%s";
  481. ip_addr_t sal_ip_addr;
  482. rt_uint32_t mac_addr[6] = {0};
  483. rt_uint32_t num = 0;
  484. rt_uint8_t dhcp_stat = 0;
  485. struct netdev *netdev = RT_NULL;
  486. netdev = (struct netdev *)work_data;
  487. rt_memset(ip, 0x00, sizeof(ip));
  488. rt_memset(mac, 0x00, sizeof(mac));
  489. rt_memset(gateway, 0x00, sizeof(gateway));
  490. rt_memset(netmask, 0x00, sizeof(netmask));
  491. resp = at_create_resp(512, 0, rt_tick_from_millisecond(300));
  492. if (!resp)
  493. {
  494. LOG_E("No memory for response structure!");
  495. return;
  496. }
  497. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  498. /* send mac addr query commond "AT+CIFSR" and wait response */
  499. if (at_exec_cmd(resp, "AT+CIFSR") < 0)
  500. {
  501. LOG_E("AT send \"AT+CIFSR\" commands error!");
  502. goto __exit;
  503. }
  504. if (at_resp_parse_line_args(resp, 2, resp_expr, mac) <= 0)
  505. {
  506. LOG_E("Parse error, current line buff : %s", at_resp_get_line(resp, 2));
  507. goto __exit;
  508. }
  509. /* send addr info query commond "AT+CIPSTA?" and wait response */
  510. if (at_exec_cmd(resp, "AT+CIPSTA?") < 0)
  511. {
  512. LOG_E("AT send \"AT+CIPSTA?\" commands error!");
  513. goto __exit;
  514. }
  515. if (at_resp_parse_line_args(resp, 1, resp_expr, ip) <= 0 ||
  516. at_resp_parse_line_args(resp, 2, resp_expr, gateway) <= 0 ||
  517. at_resp_parse_line_args(resp, 3, resp_expr, netmask) <= 0)
  518. {
  519. LOG_E("Prase \"AT+CIPSTA?\" commands resposne data error!");
  520. goto __exit;
  521. }
  522. /* set netdev info */
  523. inet_aton(ip, &sal_ip_addr);
  524. netdev_low_level_set_ipaddr(netdev, &sal_ip_addr);
  525. inet_aton(gateway, &sal_ip_addr);
  526. netdev_low_level_set_gw(netdev, &sal_ip_addr);
  527. inet_aton(netmask, &sal_ip_addr);
  528. netdev_low_level_set_netmask(netdev, &sal_ip_addr);
  529. sscanf(mac, "%x:%x:%x:%x:%x:%x", &mac_addr[0], &mac_addr[1], &mac_addr[2], &mac_addr[3], &mac_addr[4], &mac_addr[5]);
  530. for (num = 0; num < netdev->hwaddr_len; num++)
  531. {
  532. netdev->hwaddr[num] = mac_addr[num];
  533. }
  534. /* send dns server query commond "AT+CIPDNS_CUR?" and wait response */
  535. if (at_exec_cmd(resp, "AT+CIPDNS_CUR?") < 0)
  536. {
  537. LOG_W("Get dns server failed! Please check and update your firmware to support the \"AT+CIPDNS_CUR?\" command.");
  538. goto __exit;
  539. }
  540. if (at_resp_parse_line_args(resp, 1, resp_dns, dns_server1) <= 0 &&
  541. at_resp_parse_line_args(resp, 2, resp_dns, dns_server2) <= 0)
  542. {
  543. LOG_E("Prase \"AT+CIPDNS_CUR?\" commands resposne data error!");
  544. goto __exit;
  545. }
  546. if (strlen(dns_server1) > 0)
  547. {
  548. inet_aton(dns_server1, &sal_ip_addr);
  549. netdev_low_level_set_dns_server(netdev, 0, &sal_ip_addr);
  550. }
  551. if (strlen(dns_server2) > 0)
  552. {
  553. inet_aton(dns_server2, &sal_ip_addr);
  554. netdev_low_level_set_dns_server(netdev, 1, &sal_ip_addr);
  555. }
  556. /* send DHCP query commond " AT+CWDHCP_CUR?" and wait response */
  557. if (at_exec_cmd(resp, "AT+CWDHCP_CUR?") < 0)
  558. {
  559. LOG_E("AT send \"AT+CWDHCP_CUR?\" commands error!");
  560. goto __exit;
  561. }
  562. /* parse response data, get the DHCP status */
  563. if (at_resp_parse_line_args_by_kw(resp, "+CWDHCP_CUR:", "+CWDHCP_CUR:%d", &dhcp_stat) < 0)
  564. {
  565. LOG_E("get DHCP status failed!");
  566. goto __exit;
  567. }
  568. /* Bit0 - SoftAP DHCP status, Bit1 - Station DHCP status */
  569. if (dhcp_stat & 0x02)
  570. {
  571. netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
  572. }
  573. else
  574. {
  575. netdev_low_level_set_dhcp_status(netdev, RT_FALSE);
  576. }
  577. __exit:
  578. rt_mutex_release(at_event_lock);
  579. if (resp)
  580. {
  581. at_delete_resp(resp);
  582. }
  583. }
  584. static void esp8266_init_thread_entry(void *parameter)
  585. {
  586. at_response_t resp = RT_NULL;
  587. rt_err_t result = RT_EOK;
  588. rt_size_t i;
  589. resp = at_create_resp(128, 0, rt_tick_from_millisecond(5000));
  590. if (!resp)
  591. {
  592. LOG_E("No memory for response structure!");
  593. result = -RT_ENOMEM;
  594. goto __exit;
  595. }
  596. rt_thread_delay(rt_tick_from_millisecond(5000));
  597. /* reset module */
  598. AT_SEND_CMD(resp, "AT+RST");
  599. /* reset waiting delay */
  600. rt_thread_delay(rt_tick_from_millisecond(1000));
  601. /* disable echo */
  602. AT_SEND_CMD(resp, "ATE0");
  603. /* set current mode to Wi-Fi station */
  604. AT_SEND_CMD(resp, "AT+CWMODE=1");
  605. /* get module version */
  606. AT_SEND_CMD(resp, "AT+GMR");
  607. /* show module version */
  608. for (i = 0; i < resp->line_counts - 1; i++)
  609. {
  610. LOG_D("%s", at_resp_get_line(resp, i + 1));
  611. }
  612. /* connect to WiFi AP */
  613. if (at_exec_cmd(at_resp_set_info(resp, 128, 0, 20 * RT_TICK_PER_SECOND), "AT+CWJAP=\"%s\",\"%s\"",
  614. AT_DEVICE_WIFI_SSID, AT_DEVICE_WIFI_PASSWORD) != RT_EOK)
  615. {
  616. LOG_E("AT network initialize failed, check ssid(%s) and password(%s).", AT_DEVICE_WIFI_SSID, AT_DEVICE_WIFI_PASSWORD);
  617. result = -RT_ERROR;
  618. goto __exit;
  619. }
  620. AT_SEND_CMD(resp, "AT+CIPMUX=1");
  621. __exit:
  622. if (resp)
  623. {
  624. at_delete_resp(resp);
  625. }
  626. if (!result)
  627. {
  628. netdev_low_level_set_status(netdev_get_by_name(ESP8266_NETDEV_NAME), RT_TRUE);
  629. LOG_I("AT network initialize success!");
  630. }
  631. else
  632. {
  633. netdev_low_level_set_status(netdev_get_by_name(ESP8266_NETDEV_NAME), RT_FALSE);
  634. LOG_E("AT network initialize failed (%d)!", result);
  635. }
  636. }
  637. int esp8266_net_init(void)
  638. {
  639. #ifdef PKG_AT_INIT_BY_THREAD
  640. rt_thread_t tid;
  641. tid = rt_thread_create("esp8266_net_init", esp8266_init_thread_entry, RT_NULL, ESP8266_THREAD_STACK_SIZE, ESP8266_THREAD_PRIORITY, 20);
  642. if (tid)
  643. {
  644. rt_thread_startup(tid);
  645. }
  646. else
  647. {
  648. LOG_E("Create AT initialization thread fail!");
  649. }
  650. #else
  651. esp8266_init_thread_entry(RT_NULL);
  652. #endif
  653. return RT_EOK;
  654. }
  655. #ifdef FINSH_USING_MSH
  656. #include <finsh.h>
  657. MSH_CMD_EXPORT_ALIAS(esp8266_net_init, at_net_init, initialize AT network);
  658. #endif
  659. static const struct at_device_ops esp8266_socket_ops =
  660. {
  661. esp8266_socket_connect,
  662. esp8266_socket_close,
  663. esp8266_socket_send,
  664. esp8266_domain_resolve,
  665. esp8266_socket_set_event_cb,
  666. };
  667. static int esp8266_netdev_set_up(struct netdev *netdev)
  668. {
  669. netdev_low_level_set_status(netdev, RT_TRUE);
  670. LOG_D("esp8266 network interface set up status.");
  671. return RT_EOK;
  672. }
  673. static int esp8266_netdev_set_down(struct netdev *netdev)
  674. {
  675. netdev_low_level_set_status(netdev, RT_FALSE);
  676. LOG_D("esp8266 network interface set down status.");
  677. return RT_EOK;
  678. }
  679. static int esp8266_netdev_set_addr_info(struct netdev *netdev, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw)
  680. {
  681. #define RESP_SIZE 128
  682. #define IPV4_ADDR_STRLEN_MAX 16
  683. at_response_t resp = RT_NULL;
  684. int result = RT_EOK;
  685. char esp8266_ip_addr[IPV4_ADDR_STRLEN_MAX] = {0};
  686. char esp8266_gw_addr[IPV4_ADDR_STRLEN_MAX] = {0};
  687. char esp8266_netmask_addr[IPV4_ADDR_STRLEN_MAX] = {0};
  688. RT_ASSERT(netdev);
  689. RT_ASSERT(ip_addr || netmask || gw);
  690. resp = at_create_resp(RESP_SIZE, 0, rt_tick_from_millisecond(300));
  691. if (!resp)
  692. {
  693. LOG_E("No memory for response structure!");
  694. result = -RT_ENOMEM;
  695. goto __exit;
  696. }
  697. /* Convert numeric IP address into decimal dotted ASCII representation. */
  698. if (ip_addr)
  699. rt_memcpy(esp8266_ip_addr, inet_ntoa(*ip_addr), IPV4_ADDR_STRLEN_MAX);
  700. else
  701. rt_memcpy(esp8266_ip_addr, inet_ntoa(netdev->ip_addr), IPV4_ADDR_STRLEN_MAX);
  702. if (gw)
  703. rt_memcpy(esp8266_gw_addr, inet_ntoa(*gw), IPV4_ADDR_STRLEN_MAX);
  704. else
  705. rt_memcpy(esp8266_gw_addr, inet_ntoa(netdev->gw), IPV4_ADDR_STRLEN_MAX);
  706. if (netmask)
  707. rt_memcpy(esp8266_netmask_addr, inet_ntoa(*netmask), IPV4_ADDR_STRLEN_MAX);
  708. else
  709. rt_memcpy(esp8266_netmask_addr, inet_ntoa(netdev->netmask), IPV4_ADDR_STRLEN_MAX);
  710. /* send addr info set commond "AT+CIPSTA_CUR=<ip>[,<gateway>,<netmask>]" and wait response */
  711. if (at_exec_cmd(resp, "AT+CIPSTA_CUR=\"%s\",\"%s\",\"%s\"", esp8266_ip_addr, esp8266_gw_addr, esp8266_netmask_addr) < 0)
  712. {
  713. LOG_D("esp8266 set addr info failed.");
  714. result = -RT_ERROR;
  715. }
  716. else
  717. {
  718. /* Update netdev information */
  719. if (ip_addr)
  720. netdev_low_level_set_ipaddr(netdev, ip_addr);
  721. if (gw)
  722. netdev_low_level_set_gw(netdev, gw);
  723. if (netmask)
  724. netdev_low_level_set_netmask(netdev, netmask);
  725. LOG_D("esp8266 set addr info successfully.");
  726. }
  727. __exit:
  728. if (resp)
  729. {
  730. at_delete_resp(resp);
  731. }
  732. return result;
  733. }
  734. static int esp8266_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
  735. {
  736. #define RESP_SIZE 128
  737. at_response_t resp = RT_NULL;
  738. int result = RT_EOK;
  739. RT_ASSERT(netdev);
  740. RT_ASSERT(dns_server);
  741. resp = at_create_resp(RESP_SIZE, 0, rt_tick_from_millisecond(300));
  742. if (!resp)
  743. {
  744. LOG_E("No memory for response structure!");
  745. return -RT_ENOMEM;
  746. }
  747. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  748. /* send dns server set commond "AT+CIPDNS_CUR=<enable>[,<DNS server0>,<DNS server1>]" and wait response */
  749. if (at_exec_cmd(resp, "AT+CIPDNS_CUR=1,\"%s\"", inet_ntoa(*dns_server)) < 0)
  750. {
  751. LOG_E("set dns server(%s) failed", inet_ntoa(*dns_server));
  752. result = -RT_ERROR;
  753. }
  754. else
  755. {
  756. netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
  757. LOG_D("esp8266 set dns server successfully.");
  758. }
  759. if (resp)
  760. {
  761. at_delete_resp(resp);
  762. }
  763. rt_mutex_release(at_event_lock);
  764. return result;
  765. }
  766. static int esp8266_netdev_set_dhcp(struct netdev *netdev, rt_bool_t is_enabled)
  767. {
  768. #define ESP8266_STATION 1
  769. #define RESP_SIZE 128
  770. at_response_t resp = RT_NULL;
  771. int result = RT_EOK;
  772. RT_ASSERT(netdev);
  773. resp = at_create_resp(RESP_SIZE, 0, rt_tick_from_millisecond(300));
  774. if (!resp)
  775. {
  776. LOG_E("No memory for response structure!");
  777. return -RT_ENOMEM;
  778. }
  779. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  780. /* send dhcp set commond "AT+CWDHCP_CUR=<mode>,<en>" and wait response */
  781. if (at_exec_cmd(resp, "AT+CWDHCP_CUR=%d,%d", ESP8266_STATION, is_enabled) < 0)
  782. {
  783. LOG_E("set dhcp status(%d) failed", is_enabled);
  784. result = -RT_ERROR;
  785. goto __exit;
  786. }
  787. else
  788. {
  789. netdev_low_level_set_dhcp_status(netdev, is_enabled);
  790. LOG_D("esp8266 set dhcp successfully.");
  791. }
  792. __exit:
  793. if (resp)
  794. {
  795. at_delete_resp(resp);
  796. }
  797. rt_mutex_release(at_event_lock);
  798. return result;
  799. }
  800. static int esp8266_netdev_ping(struct netdev *netdev, const char *host, size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp)
  801. {
  802. #define ESP8266_PING_IP_SIZE 16
  803. at_response_t resp = RT_NULL;
  804. rt_err_t result = RT_EOK;
  805. int req_time;
  806. char ip_addr[ESP8266_PING_IP_SIZE] = {0};
  807. RT_ASSERT(netdev);
  808. RT_ASSERT(host);
  809. RT_ASSERT(ping_resp);
  810. resp = at_create_resp(64, 0, timeout);
  811. if (!resp)
  812. {
  813. LOG_E("No memory for response structure!");
  814. return -RT_ENOMEM;
  815. }
  816. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  817. /* send domain commond "AT+CIPDOMAIN=<domain name>" and wait response */
  818. if (at_exec_cmd(resp, "AT+CIPDOMAIN=\"%s\"", host) < 0)
  819. {
  820. LOG_D("ping: send commond AT+CIPDOMAIN=<domain name> failed");
  821. result = -RT_ERROR;
  822. goto __exit;
  823. }
  824. /* parse the third line of response data, get the IP address */
  825. if (at_resp_parse_line_args_by_kw(resp, "+CIPDOMAIN:", "+CIPDOMAIN:%s", ip_addr) < 0)
  826. {
  827. LOG_E("ping: get the IP address failed");
  828. result = -RT_ERROR;
  829. goto __exit;
  830. }
  831. /* send ping commond "AT+PING=<IP>" and wait response */
  832. if (at_exec_cmd(resp, "AT+PING=\"%s\"", host) < 0)
  833. {
  834. LOG_D("ping: unknown remote server host");
  835. result = -RT_ERROR;
  836. goto __exit;
  837. }
  838. if (at_resp_parse_line_args_by_kw(resp, "+", "+%d", &req_time) < 0)
  839. {
  840. result = -RT_ERROR;
  841. goto __exit;
  842. }
  843. if (req_time)
  844. {
  845. inet_aton(ip_addr, &(ping_resp->ip_addr));
  846. ping_resp->data_len = data_len;
  847. ping_resp->ttl = 0;
  848. ping_resp->ticks = req_time;
  849. }
  850. __exit:
  851. if (resp)
  852. {
  853. at_delete_resp(resp);
  854. }
  855. rt_mutex_release(at_event_lock);
  856. return result;
  857. }
  858. void esp8266_netdev_netstat(struct netdev *netdev)
  859. {
  860. #define ESP8266_NETSTAT_RESP_SIZE 320
  861. #define ESP8266_NETSTAT_TYPE_SIZE 4
  862. #define ESP8266_NETSTAT_IPADDR_SIZE 17
  863. #define ESP8266_NETSTAT_EXPRESSION "+CIPSTATUS:%*d,\"%[^\"]\",\"%[^\"]\",%d,%d,%*d"
  864. at_response_t resp = RT_NULL;
  865. int remote_port, local_port, i;
  866. char *type = RT_NULL;
  867. char *ipaddr = RT_NULL;
  868. type = rt_calloc(1, ESP8266_NETSTAT_TYPE_SIZE);
  869. ipaddr = rt_calloc(1, ESP8266_NETSTAT_IPADDR_SIZE);
  870. if ((type && ipaddr) == RT_NULL)
  871. {
  872. LOG_E("No memory for response structure!");
  873. goto __exit;
  874. }
  875. resp = at_create_resp(ESP8266_NETSTAT_RESP_SIZE, 0, rt_tick_from_millisecond(5000));
  876. if (!resp)
  877. {
  878. LOG_E("No memory for response structure!");
  879. goto __exit;
  880. }
  881. rt_mutex_take(at_event_lock, RT_WAITING_FOREVER);
  882. /* send network connection information commond "AT+CIPSTATUS" and wait response */
  883. if (at_exec_cmd(resp, "AT+CIPSTATUS") < 0)
  884. {
  885. LOG_E("netstat: send commond AT+CIPSTATUS failed");
  886. goto __exit;
  887. }
  888. for (i = 1; i <= resp->line_counts; i++)
  889. {
  890. if (strstr(at_resp_get_line(resp, i), "+CIPSTATUS"))
  891. {
  892. /* parse the third line of response data, get the network connection information */
  893. if (at_resp_parse_line_args(resp, i, ESP8266_NETSTAT_EXPRESSION, type, ipaddr, &remote_port, &local_port) < 0)
  894. goto __exit;
  895. else
  896. {
  897. LOG_RAW("%s: %s:%d ==> %s:%d\n", type, inet_ntoa(netdev->ip_addr), local_port, ipaddr, remote_port);
  898. }
  899. }
  900. }
  901. __exit:
  902. if (resp)
  903. {
  904. at_delete_resp(resp);
  905. }
  906. if (type)
  907. {
  908. rt_free(type);
  909. }
  910. if (ipaddr)
  911. {
  912. rt_free(ipaddr);
  913. }
  914. rt_mutex_release(at_event_lock);
  915. }
  916. const struct netdev_ops esp8266_netdev_ops =
  917. {
  918. esp8266_netdev_set_up,
  919. esp8266_netdev_set_down,
  920. esp8266_netdev_set_addr_info,
  921. esp8266_netdev_set_dns_server,
  922. esp8266_netdev_set_dhcp,
  923. esp8266_netdev_ping,
  924. esp8266_netdev_netstat,
  925. };
  926. static struct netdev *esp8266_netdev_add(const char *netdev_name)
  927. {
  928. #define ETHERNET_MTU 1500
  929. #define HWADDR_LEN 6
  930. struct netdev *netdev = RT_NULL;
  931. RT_ASSERT(netdev_name);
  932. netdev = (struct netdev *) rt_calloc(1, sizeof(struct netdev));
  933. if (netdev == RT_NULL)
  934. {
  935. return RT_NULL;
  936. }
  937. netdev->mtu = ETHERNET_MTU;
  938. netdev->ops = &esp8266_netdev_ops;
  939. netdev->hwaddr_len = HWADDR_LEN;
  940. #ifdef SAL_USING_AT
  941. extern int sal_at_netdev_set_pf_info(struct netdev *netdev);
  942. /* set the network interface socket/netdb operations */
  943. sal_at_netdev_set_pf_info(netdev);
  944. #endif
  945. netdev_register(netdev, netdev_name, RT_NULL);
  946. return netdev;
  947. }
  948. static int at_socket_device_init(void)
  949. {
  950. /* create current AT socket event */
  951. at_socket_event = rt_event_create("at_se", RT_IPC_FLAG_FIFO);
  952. if (at_socket_event == RT_NULL)
  953. {
  954. LOG_E("RT AT client port initialize failed! at_sock_event create failed!");
  955. return -RT_ENOMEM;
  956. }
  957. /* create current AT socket event lock */
  958. at_event_lock = rt_mutex_create("at_se", RT_IPC_FLAG_FIFO);
  959. if (at_event_lock == RT_NULL)
  960. {
  961. LOG_E("RT AT client port initialize failed! at_sock_lock create failed!");
  962. rt_event_delete(at_socket_event);
  963. return -RT_ENOMEM;
  964. }
  965. /* initialize AT client */
  966. at_client_init(AT_DEVICE_NAME, AT_DEVICE_RECV_BUFF_LEN);
  967. /* register URC data execution function */
  968. at_set_urc_table(urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  969. /* Add esp8266 to the netdev list */
  970. esp8266_netdev_add(ESP8266_NETDEV_NAME);
  971. /* initialize esp8266 net workqueue */
  972. rt_delayed_work_init(&esp8266_net_work, exp8266_get_netdev_info, (void *)netdev_get_by_name(ESP8266_NETDEV_NAME));
  973. /* initialize esp8266 network */
  974. esp8266_net_init();
  975. /* set esp8266 AT Socket options */
  976. at_socket_device_register(&esp8266_socket_ops);
  977. return RT_EOK;
  978. }
  979. INIT_APP_EXPORT(at_socket_device_init);
  980. #endif /* AT_DEVICE_ESP8266 */