API
For Arduino developers
ESP8266.cpp
Go to the documentation of this file.
1 
21 #include "ESP8266.h"
22 
23 #define LOG_OUTPUT_DEBUG (1)
24 #define LOG_OUTPUT_DEBUG_PREFIX (1)
25 
26 #define logDebug(arg)\
27  do {\
28  if (LOG_OUTPUT_DEBUG)\
29  {\
30  if (LOG_OUTPUT_DEBUG_PREFIX)\
31  {\
32  Serial.print("[LOG Debug: ");\
33  Serial.print((const char*)__FILE__);\
34  Serial.print(",");\
35  Serial.print((unsigned int)__LINE__);\
36  Serial.print(",");\
37  Serial.print((const char*)__FUNCTION__);\
38  Serial.print("] ");\
39  }\
40  Serial.print(arg);\
41  }\
42  } while(0)
43 
44 #ifdef ESP8266_USE_SOFTWARE_SERIAL
45 ESP8266::ESP8266(SoftwareSerial &uart, uint32_t baud): m_puart(&uart)
46 {
47  m_puart->begin(baud);
48  rx_empty();
49 }
50 #else
51 ESP8266::ESP8266(HardwareSerial &uart, uint32_t baud): m_puart(&uart)
52 {
53  m_puart->begin(baud);
54  rx_empty();
55 }
56 #endif
57 
58 bool ESP8266::kick(void)
59 {
60  return eAT();
61 }
62 
63 bool ESP8266::restart(void)
64 {
65  unsigned long start;
66  if (eATRST()) {
67  delay(2000);
68  start = millis();
69  while (millis() - start < 3000) {
70  if (eAT()) {
71  delay(1500); /* Waiting for stable */
72  return true;
73  }
74  delay(100);
75  }
76  }
77  return false;
78 }
79 
80 String ESP8266::getVersion(void)
81 {
82  String version;
83  eATGMR(version);
84  return version;
85 }
86 
88 {
89  uint8_t mode;
90  if (!qATCWMODE(&mode)) {
91  return false;
92  }
93  if (mode == 1) {
94  return true;
95  } else {
96  if (sATCWMODE(1) && restart()) {
97  return true;
98  } else {
99  return false;
100  }
101  }
102 }
103 
105 {
106  uint8_t mode;
107  if (!qATCWMODE(&mode)) {
108  return false;
109  }
110  if (mode == 2) {
111  return true;
112  } else {
113  if (sATCWMODE(2) && restart()) {
114  return true;
115  } else {
116  return false;
117  }
118  }
119 }
120 
122 {
123  uint8_t mode;
124  if (!qATCWMODE(&mode)) {
125  return false;
126  }
127  if (mode == 3) {
128  return true;
129  } else {
130  if (sATCWMODE(3) && restart()) {
131  return true;
132  } else {
133  return false;
134  }
135  }
136 }
137 
138 String ESP8266::getAPList(void)
139 {
140  String list;
141  eATCWLAP(list);
142  return list;
143 }
144 
145 bool ESP8266::joinAP(String ssid, String pwd)
146 {
147  return sATCWJAP(ssid, pwd);
148 }
149 
151 {
152  return eATCWQAP();
153 }
154 
155 bool ESP8266::setSoftAPParam(String ssid, String pwd, uint8_t chl, uint8_t ecn)
156 {
157  return sATCWSAP(ssid, pwd, chl, ecn);
158 }
159 
161 {
162  String list;
163  eATCWLIF(list);
164  return list;
165 }
166 
168 {
169  String list;
170  eATCIPSTATUS(list);
171  return list;
172 }
173 
175 {
176  String list;
177  eATCIFSR(list);
178  return list;
179 }
180 
182 {
183  return sATCIPMUX(1);
184 }
185 
187 {
188  return sATCIPMUX(0);
189 }
190 
191 bool ESP8266::createTCP(String addr, uint32_t port)
192 {
193  return sATCIPSTARTSingle("TCP", addr, port);
194 }
195 
197 {
198  return eATCIPCLOSESingle();
199 }
200 
201 bool ESP8266::registerUDP(String addr, uint32_t port)
202 {
203  return sATCIPSTARTSingle("UDP", addr, port);
204 }
205 
207 {
208  return eATCIPCLOSESingle();
209 }
210 
211 bool ESP8266::createTCP(uint8_t mux_id, String addr, uint32_t port)
212 {
213  return sATCIPSTARTMultiple(mux_id, "TCP", addr, port);
214 }
215 
216 bool ESP8266::releaseTCP(uint8_t mux_id)
217 {
218  return sATCIPCLOSEMulitple(mux_id);
219 }
220 
221 bool ESP8266::registerUDP(uint8_t mux_id, String addr, uint32_t port)
222 {
223  return sATCIPSTARTMultiple(mux_id, "UDP", addr, port);
224 }
225 
226 bool ESP8266::unregisterUDP(uint8_t mux_id)
227 {
228  return sATCIPCLOSEMulitple(mux_id);
229 }
230 
231 bool ESP8266::setTCPServerTimeout(uint32_t timeout)
232 {
233  return sATCIPSTO(timeout);
234 }
235 
236 bool ESP8266::startTCPServer(uint32_t port)
237 {
238  if (sATCIPSERVER(1, port)) {
239  return true;
240  }
241  return false;
242 }
243 
245 {
246  sATCIPSERVER(0);
247  restart();
248  return false;
249 }
250 
251 bool ESP8266::startServer(uint32_t port)
252 {
253  return startTCPServer(port);
254 }
255 
257 {
258  return stopTCPServer();
259 }
260 
261 bool ESP8266::send(const uint8_t *buffer, uint32_t len)
262 {
263  return sATCIPSENDSingle(buffer, len);
264 }
265 
266 bool ESP8266::send(uint8_t mux_id, const uint8_t *buffer, uint32_t len)
267 {
268  return sATCIPSENDMultiple(mux_id, buffer, len);
269 }
270 
271 uint32_t ESP8266::recv(uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
272 {
273  return recvPkg(buffer, buffer_size, NULL, timeout, NULL);
274 }
275 
276 uint32_t ESP8266::recv(uint8_t mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
277 {
278  uint8_t id;
279  uint32_t ret;
280  ret = recvPkg(buffer, buffer_size, NULL, timeout, &id);
281  if (ret > 0 && id == mux_id) {
282  return ret;
283  }
284  return 0;
285 }
286 
287 uint32_t ESP8266::recv(uint8_t *coming_mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
288 {
289  return recvPkg(buffer, buffer_size, NULL, timeout, coming_mux_id);
290 }
291 
292 /*----------------------------------------------------------------------------*/
293 
294 uint32_t ESP8266::recvPkg(uint8_t *buffer, uint32_t buffer_size, uint32_t *data_len, uint32_t timeout, uint8_t *coming_mux_id)
295 {
296  String data;
297  char a;
298  int32_t index_PIPDcomma = -1;
299  int32_t index_colon = -1; /* : */
300  int32_t index_comma = -1; /* , */
301  int32_t len = -1;
302  int8_t id = -1;
303  bool has_data = false;
304  //logDebug("start recv pkg");
305 
306  unsigned long start = millis();
307  while (millis() - start < timeout) {
308  while(m_puart->available() > 0) {
309  a = m_puart->read();
310  data += a;
311  }
312 
313  index_PIPDcomma = data.indexOf("+IPD,");
314  if (index_PIPDcomma != -1) {
315  //logDebug("index_PIPDcomma found = %d", index_PIPDcomma);
316  index_colon = data.indexOf(':', index_PIPDcomma + 5);
317  if (index_colon != -1) {
318  //logDebug("data1 = %s\r\n", data.c_str());
319  //logDebug("index_colon found = %d", index_colon);
320 
321  index_comma = data.indexOf(',', index_PIPDcomma + 5);
322  //logDebug("index_comma found = %d", index_comma);
323 
324  if (index_comma != -1 && index_comma < index_colon) { /* +IPD,id,len:data */
325  //logDebug("id = %d", id);
326  id = data.substring(index_PIPDcomma + 5, index_comma).toInt();
327  //logDebug("id = %d", id);
328  if (id < 0 || id > 4) {
329  return 0;
330  }
331  //logDebug("len = %d", len);
332  len = data.substring(index_comma + 1, index_colon).toInt();
333  //logDebug("len = %d", len);
334  if (len <= 0) {
335  return 0;
336  }
337  //logDebug("has id");
338  } else { /* +IPD,len:data */
339  len = data.substring(index_PIPDcomma + 5, index_colon).toInt();
340  //logDebug("len = %d", len);
341  if (len <= 0) {
342  return 0;
343  }
344  //logDebug("no id");
345  }
346  has_data = true;
347  //logDebug("has_data true");
348  break;
349  }
350  }
351  }
352  //logDebug("has_data = %u\r\n", has_data);
353  //logDebug("data2 = %s\r\n", data.c_str());
354 
355  if (has_data) {
356  start = millis();
357  while (millis() - start < 3000) {
358  while(m_puart->available() > 0) {
359  a = m_puart->read();
360  data += a;
361  }
362  //logDebug("data3 = %s\r\n", data.c_str());
363  if (data.length() >= index_colon + 1 + len) {
364  if (data_len) {
365  *data_len = len;
366  }
367  if (index_comma != -1 && coming_mux_id) {
368  *coming_mux_id = id;
369  }
370  //logDebug("len = %d", len);
371  //logDebug("buffer_size = %d", buffer_size);
372  uint32_t ret = len > buffer_size ? buffer_size : len;
373 
374  memcpy(buffer,
375  data.substring(index_colon + 1, index_colon + 1 + len).c_str(),
376  ret);
377  //logDebug("ret = %u\r\n", ret);
378  return ret;
379  }
380  }
381  }
382  //logDebug("end recv pkg");
383  return 0;
384 }
385 
386 void ESP8266::rx_empty(void)
387 {
388  while(m_puart->available() > 0) {
389  m_puart->read();
390  }
391 }
392 
393 String ESP8266::recvString(String target, uint32_t timeout)
394 {
395  String data;
396  char a;
397  unsigned long start = millis();
398  while (millis() - start < timeout) {
399  while(m_puart->available() > 0) {
400  a = m_puart->read();
401  if(a == '\0') continue;
402  data += a;
403  }
404  if (data.indexOf(target) != -1) {
405  break;
406  }
407  }
408  return data;
409 }
410 
411 String ESP8266::recvString(String target1, String target2, uint32_t timeout)
412 {
413  String data;
414  char a;
415  unsigned long start = millis();
416  while (millis() - start < timeout) {
417  while(m_puart->available() > 0) {
418  a = m_puart->read();
419  if(a == '\0') continue;
420  data += a;
421  }
422  if (data.indexOf(target1) != -1) {
423  break;
424  } else if (data.indexOf(target2) != -1) {
425  break;
426  }
427  }
428  return data;
429 }
430 
431 String ESP8266::recvString(String target1, String target2, String target3, uint32_t timeout)
432 {
433  String data;
434  char a;
435  unsigned long start = millis();
436  while (millis() - start < timeout) {
437  while(m_puart->available() > 0) {
438  a = m_puart->read();
439  if(a == '\0') continue;
440  data += a;
441  }
442  if (data.indexOf(target1) != -1) {
443  break;
444  } else if (data.indexOf(target2) != -1) {
445  break;
446  } else if (data.indexOf(target3) != -1) {
447  break;
448  }
449  }
450  return data;
451 }
452 
453 bool ESP8266::recvFind(String target, uint32_t timeout)
454 {
455  String data_tmp;
456  data_tmp = recvString(target, timeout);
457  if (data_tmp.indexOf(target) != -1) {
458  return true;
459  }
460  return false;
461 }
462 
463 bool ESP8266::recvFindAndFilter(String target, String begin, String end, String &data, uint32_t timeout)
464 {
465  String data_tmp;
466  data_tmp = recvString(target, timeout);
467  if (data_tmp.indexOf(target) != -1) {
468  int32_t index1 = data_tmp.indexOf(begin);
469  int32_t index2 = data_tmp.indexOf(end);
470  if (index1 != -1 && index2 != -1) {
471  index1 += begin.length();
472  data = data_tmp.substring(index1, index2);
473  return true;
474  }
475  }
476  data = "";
477  return false;
478 }
479 
480 bool ESP8266::eAT(void)
481 {
482  rx_empty();
483  m_puart->println("AT");
484  return recvFind("OK");
485 }
486 
487 bool ESP8266::eATRST(void)
488 {
489  rx_empty();
490  m_puart->println("AT+RST");
491  return recvFind("OK");
492 }
493 
494 bool ESP8266::eATGMR(String &version)
495 {
496  rx_empty();
497  m_puart->println("AT+GMR");
498  return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", version);
499 }
500 
501 bool ESP8266::qATCWMODE(uint8_t *mode)
502 {
503  String str_mode;
504  bool ret;
505  if (!mode) {
506  return false;
507  }
508  rx_empty();
509  m_puart->println("AT+CWMODE?");
510  ret = recvFindAndFilter("OK", "+CWMODE:", "\r\n\r\nOK", str_mode);
511  if (ret) {
512  *mode = (uint8_t)str_mode.toInt();
513  return true;
514  } else {
515  return false;
516  }
517 }
518 
519 bool ESP8266::sATCWMODE(uint8_t mode)
520 {
521  String data;
522  rx_empty();
523  m_puart->print("AT+CWMODE=");
524  m_puart->println(mode);
525 
526  data = recvString("OK", "no change");
527  if (data.indexOf("OK") != -1 || data.indexOf("no change") != -1) {
528  return true;
529  }
530  return false;
531 }
532 
533 bool ESP8266::sATCWJAP(String ssid, String pwd)
534 {
535  String data;
536  rx_empty();
537  m_puart->print("AT+CWJAP=\"");
538  m_puart->print(ssid);
539  m_puart->print("\",\"");
540  m_puart->print(pwd);
541  m_puart->println("\"");
542 
543  data = recvString("OK", "FAIL", 10000);
544  if (data.indexOf("OK") != -1) {
545  return true;
546  }
547  return false;
548 }
549 
550 bool ESP8266::eATCWLAP(String &list)
551 {
552  String data;
553  rx_empty();
554  m_puart->println("AT+CWLAP");
555  return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list, 10000);
556 }
557 
558 bool ESP8266::eATCWQAP(void)
559 {
560  String data;
561  rx_empty();
562  m_puart->println("AT+CWQAP");
563  return recvFind("OK");
564 }
565 
566 bool ESP8266::sATCWSAP(String ssid, String pwd, uint8_t chl, uint8_t ecn)
567 {
568  String data;
569  rx_empty();
570  m_puart->print("AT+CWSAP=\"");
571  m_puart->print(ssid);
572  m_puart->print("\",\"");
573  m_puart->print(pwd);
574  m_puart->print("\",");
575  m_puart->print(chl);
576  m_puart->print(",");
577  m_puart->println(ecn);
578 
579  data = recvString("OK", "ERROR", 5000);
580  if (data.indexOf("OK") != -1) {
581  return true;
582  }
583  return false;
584 }
585 
586 bool ESP8266::eATCWLIF(String &list)
587 {
588  String data;
589  rx_empty();
590  m_puart->println("AT+CWLIF");
591  return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
592 }
593 bool ESP8266::eATCIPSTATUS(String &list)
594 {
595  String data;
596  delay(100);
597  rx_empty();
598  m_puart->println("AT+CIPSTATUS");
599  return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
600 }
601 bool ESP8266::sATCIPSTARTSingle(String type, String addr, uint32_t port)
602 {
603  String data;
604  rx_empty();
605  m_puart->print("AT+CIPSTART=\"");
606  m_puart->print(type);
607  m_puart->print("\",\"");
608  m_puart->print(addr);
609  m_puart->print("\",");
610  m_puart->println(port);
611 
612  data = recvString("OK", "ERROR", "ALREADY CONNECT", 10000);
613  if (data.indexOf("OK") != -1 || data.indexOf("ALREADY CONNECT") != -1) {
614  return true;
615  }
616  return false;
617 }
618 bool ESP8266::sATCIPSTARTMultiple(uint8_t mux_id, String type, String addr, uint32_t port)
619 {
620  String data;
621  rx_empty();
622  m_puart->print("AT+CIPSTART=");
623  m_puart->print(mux_id);
624  m_puart->print(",\"");
625  m_puart->print(type);
626  m_puart->print("\",\"");
627  m_puart->print(addr);
628  m_puart->print("\",");
629  m_puart->println(port);
630 
631  data = recvString("OK", "ERROR", "ALREADY CONNECT", 10000);
632  if (data.indexOf("OK") != -1 || data.indexOf("ALREADY CONNECT") != -1) {
633  return true;
634  }
635  return false;
636 }
637 bool ESP8266::sATCIPSENDSingle(const uint8_t *buffer, uint32_t len)
638 {
639  rx_empty();
640  m_puart->print("AT+CIPSEND=");
641  m_puart->println(len);
642  if (recvFind(">", 5000)) {
643  rx_empty();
644  for (uint32_t i = 0; i < len; i++) {
645  m_puart->write(buffer[i]);
646  }
647  return recvFind("SEND OK", 10000);
648  }
649  return false;
650 }
651 bool ESP8266::sATCIPSENDMultiple(uint8_t mux_id, const uint8_t *buffer, uint32_t len)
652 {
653  rx_empty();
654  m_puart->print("AT+CIPSEND=");
655  m_puart->print(mux_id);
656  m_puart->print(",");
657  m_puart->println(len);
658  if (recvFind(">", 5000)) {
659  rx_empty();
660  for (uint32_t i = 0; i < len; i++) {
661  m_puart->write(buffer[i]);
662  }
663  return recvFind("SEND OK", 10000);
664  }
665  return false;
666 }
667 bool ESP8266::sATCIPCLOSEMulitple(uint8_t mux_id)
668 {
669  String data;
670  rx_empty();
671  m_puart->print("AT+CIPCLOSE=");
672  m_puart->println(mux_id);
673 
674  data = recvString("OK", "link is not", 5000);
675  if (data.indexOf("OK") != -1 || data.indexOf("link is not") != -1) {
676  return true;
677  }
678  return false;
679 }
680 bool ESP8266::eATCIPCLOSESingle(void)
681 {
682  rx_empty();
683  m_puart->println("AT+CIPCLOSE");
684  return recvFind("OK", 5000);
685 }
686 bool ESP8266::eATCIFSR(String &list)
687 {
688  rx_empty();
689  m_puart->println("AT+CIFSR");
690  return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
691 }
692 bool ESP8266::sATCIPMUX(uint8_t mode)
693 {
694  String data;
695  rx_empty();
696  m_puart->print("AT+CIPMUX=");
697  m_puart->println(mode);
698 
699  data = recvString("OK", "Link is builded");
700  if (data.indexOf("OK") != -1) {
701  return true;
702  }
703  return false;
704 }
705 bool ESP8266::sATCIPSERVER(uint8_t mode, uint32_t port)
706 {
707  String data;
708  if (mode) {
709  rx_empty();
710  m_puart->print("AT+CIPSERVER=1,");
711  m_puart->println(port);
712 
713  data = recvString("OK", "no change");
714  if (data.indexOf("OK") != -1 || data.indexOf("no change") != -1) {
715  return true;
716  }
717  return false;
718  } else {
719  rx_empty();
720  m_puart->println("AT+CIPSERVER=0");
721  return recvFind("\r\r\n");
722  }
723 }
724 bool ESP8266::sATCIPSTO(uint32_t timeout)
725 {
726  rx_empty();
727  m_puart->print("AT+CIPSTO=");
728  m_puart->println(timeout);
729  return recvFind("OK");
730 }
731 
bool send(const uint8_t *buffer, uint32_t len)
Send data based on TCP or UDP builded already in single mode.
Definition: ESP8266.cpp:261
String getVersion(void)
Get the version of AT Command Set.
Definition: ESP8266.cpp:80
bool releaseTCP(void)
Release TCP connection in single mode.
Definition: ESP8266.cpp:196
uint32_t recv(uint8_t *buffer, uint32_t buffer_size, uint32_t timeout=1000)
Receive data from TCP or UDP builded already in single mode.
Definition: ESP8266.cpp:271
bool enableMUX(void)
Enable IP MUX(multiple connection mode).
Definition: ESP8266.cpp:181
String getLocalIP(void)
Get the IP address of ESP8266.
Definition: ESP8266.cpp:174
bool setOprToSoftAP(void)
Set operation mode to softap.
Definition: ESP8266.cpp:104
The definition of class ESP8266.
bool setOprToStationSoftAP(void)
Set operation mode to station + softap.
Definition: ESP8266.cpp:121
bool createTCP(String addr, uint32_t port)
Create TCP connection in single mode.
Definition: ESP8266.cpp:191
bool unregisterUDP(void)
Unregister UDP port number in single mode.
Definition: ESP8266.cpp:206
bool startServer(uint32_t port=333)
Start Server(Only in multiple mode).
Definition: ESP8266.cpp:251
bool stopTCPServer(void)
Stop TCP Server(Only in multiple mode).
Definition: ESP8266.cpp:244
bool stopServer(void)
Stop Server(Only in multiple mode).
Definition: ESP8266.cpp:256
bool disableMUX(void)
Disable IP MUX(single connection mode).
Definition: ESP8266.cpp:186
bool restart(void)
Restart ESP8266 by "AT+RST".
Definition: ESP8266.cpp:63
bool kick(void)
Verify ESP8266 whether live or not.
Definition: ESP8266.cpp:58
bool joinAP(String ssid, String pwd)
Join in AP.
Definition: ESP8266.cpp:145
bool registerUDP(String addr, uint32_t port)
Register UDP port number in single mode.
Definition: ESP8266.cpp:201
bool leaveAP(void)
Leave AP joined before.
Definition: ESP8266.cpp:150
bool setTCPServerTimeout(uint32_t timeout=180)
Set the timeout of TCP Server.
Definition: ESP8266.cpp:231
bool startTCPServer(uint32_t port=333)
Start TCP Server(Only in multiple mode).
Definition: ESP8266.cpp:236
bool setSoftAPParam(String ssid, String pwd, uint8_t chl=7, uint8_t ecn=4)
Set SoftAP parameters.
Definition: ESP8266.cpp:155
bool setOprToStation(void)
Set operation mode to staion.
Definition: ESP8266.cpp:87
String getAPList(void)
Search available AP list and return it.
Definition: ESP8266.cpp:138
String getIPStatus(void)
Get the current status of connection(UDP and TCP).
Definition: ESP8266.cpp:167
String getJoinedDeviceIP(void)
Get the IP list of devices connected to SoftAP.
Definition: ESP8266.cpp:160