Provide an easy-to-use way to manipulate ESP8266.

Dependencies:   ArduinoAPI

Dependents:   WeeESP8266_TCPClientMultiple WeeESP8266_TCPClientSingle WeeESP8266_TCPServer WeeESP8266_UDPClientMultiple ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ESP8266.cpp Source File

ESP8266.cpp

Go to the documentation of this file.
00001 /**
00002  * @file ESP8266.cpp
00003  * @brief The implementation of class ESP8266. 
00004  * @author Wu Pengfei<pengfei.wu@itead.cc> 
00005  * @date 2015.02
00006  * 
00007  * @par Copyright:
00008  * Copyright (c) 2015 ITEAD Intelligent Systems Co., Ltd. \n\n
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU General Public License as
00011  * published by the Free Software Foundation; either version 2 of
00012  * the License, or (at your option) any later version. \n\n
00013  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00016  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00018  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00019  * THE SOFTWARE.
00020  */
00021 #include "ESP8266.h"
00022 #include "log.h"
00023 
00024 ESP8266::ESP8266(ArduinoSerial &uart): m_puart(&uart)
00025 {
00026     m_puart->begin(9600);
00027     m_puart->flush();
00028 }
00029 
00030 
00031 bool ESP8266::kick(void)
00032 {
00033     return eAT();
00034 }
00035 
00036 bool ESP8266::restart(void)
00037 {
00038     unsigned long start;
00039     if (eATRST()) {
00040         delay(2000);
00041         start = millis();
00042         while (millis() - start < 3000) {
00043             if (eAT()) {
00044                 delay(1500); /* Waiting for stable */
00045                 return true;
00046             }
00047             delay(100);
00048         }
00049     }
00050     return false;
00051 }
00052 
00053 String ESP8266::getVersion(void)
00054 {
00055     String version;
00056     eATGMR(version);
00057     return version;
00058 }
00059 
00060 bool ESP8266::setOprToStation(void)
00061 {
00062     uint8_t mode;
00063     if (!qATCWMODE(&mode)) {
00064         return false;
00065     }
00066     if (mode == 1) {
00067         return true;
00068     } else {
00069         if (sATCWMODE(1) && restart()) {
00070             return true;
00071         } else {
00072             return false;
00073         }
00074     }
00075 }
00076 
00077 bool ESP8266::setOprToSoftAP(void)
00078 {
00079     uint8_t mode;
00080     if (!qATCWMODE(&mode)) {
00081         return false;
00082     }
00083     if (mode == 2) {
00084         return true;
00085     } else {
00086         if (sATCWMODE(2) && restart()) {
00087             return true;
00088         } else {
00089             return false;
00090         }
00091     }
00092 }
00093 
00094 bool ESP8266::setOprToStationSoftAP(void)
00095 {
00096     uint8_t mode;
00097     if (!qATCWMODE(&mode)) {
00098         return false;
00099     }
00100     if (mode == 3) {
00101         return true;
00102     } else {
00103         if (sATCWMODE(3) && restart()) {
00104             return true;
00105         } else {
00106             return false;
00107         }
00108     }
00109 }
00110 
00111 String ESP8266::getAPList(void)
00112 {
00113     String list;
00114     eATCWLAP(list);
00115     return list;
00116 }
00117 
00118 bool ESP8266::joinAP(String ssid, String pwd)
00119 {
00120     return sATCWJAP(ssid, pwd);
00121 }
00122 
00123 bool ESP8266::leaveAP(void)
00124 {
00125     return eATCWQAP();
00126 }
00127 
00128 bool ESP8266::setSoftAPParam(String ssid, String pwd, uint8_t chl, uint8_t ecn)
00129 {
00130     return sATCWSAP(ssid, pwd, chl, ecn);
00131 }
00132 
00133 String ESP8266::getJoinedDeviceIP(void)
00134 {
00135     String list;
00136     eATCWLIF(list);
00137     return list;
00138 }
00139 
00140 String ESP8266::getIPStatus(void)
00141 {
00142     String list;
00143     eATCIPSTATUS(list);
00144     return list;
00145 }
00146 
00147 String ESP8266::getLocalIP(void)
00148 {
00149     String list;
00150     eATCIFSR(list);
00151     return list;
00152 }
00153 
00154 bool ESP8266::enableMUX(void)
00155 {
00156     return sATCIPMUX(1);
00157 }
00158 
00159 bool ESP8266::disableMUX(void)
00160 {
00161     return sATCIPMUX(0);
00162 }
00163 
00164 bool ESP8266::createTCP(String addr, uint32_t port)
00165 {
00166     return sATCIPSTARTSingle("TCP", addr, port);
00167 }
00168 
00169 bool ESP8266::releaseTCP(void)
00170 {
00171     return eATCIPCLOSESingle();
00172 }
00173 
00174 bool ESP8266::registerUDP(String addr, uint32_t port)
00175 {
00176     return sATCIPSTARTSingle("UDP", addr, port);
00177 }
00178 
00179 bool ESP8266::unregisterUDP(void)
00180 {
00181     return eATCIPCLOSESingle();
00182 }
00183 
00184 bool ESP8266::createTCP(uint8_t mux_id, String addr, uint32_t port)
00185 {
00186     return sATCIPSTARTMultiple(mux_id, "TCP", addr, port);
00187 }
00188 
00189 bool ESP8266::releaseTCP(uint8_t mux_id)
00190 {
00191     return sATCIPCLOSEMulitple(mux_id);
00192 }
00193 
00194 bool ESP8266::registerUDP(uint8_t mux_id, String addr, uint32_t port)
00195 {
00196     return sATCIPSTARTMultiple(mux_id, "UDP", addr, port);
00197 }
00198 
00199 bool ESP8266::unregisterUDP(uint8_t mux_id)
00200 {
00201     return sATCIPCLOSEMulitple(mux_id);
00202 }
00203 
00204 bool ESP8266::setTCPServerTimeout(uint32_t timeout)
00205 {
00206     return sATCIPSTO(timeout);
00207 }
00208 
00209 bool ESP8266::startTCPServer(uint32_t port)
00210 {
00211     if (sATCIPSERVER(1, port)) {
00212         return true;
00213     }
00214     return false;
00215 }
00216 
00217 bool ESP8266::stopTCPServer(void)
00218 {
00219     sATCIPSERVER(0);
00220     restart();
00221     return false;
00222 }
00223 
00224 bool ESP8266::send(const uint8_t *buffer, uint32_t len)
00225 {
00226     return sATCIPSENDSingle(buffer, len);
00227 }
00228 
00229 bool ESP8266::send(uint8_t mux_id, const uint8_t *buffer, uint32_t len)
00230 {
00231     return sATCIPSENDMultiple(mux_id, buffer, len);
00232 }
00233 
00234 uint32_t ESP8266::recv(uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
00235 {
00236     return recvPkg(buffer, buffer_size, NULL, timeout, NULL);
00237 }
00238 
00239 uint32_t ESP8266::recv(uint8_t mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
00240 {
00241     uint8_t id;
00242     uint32_t ret;
00243     ret = recvPkg(buffer, buffer_size, NULL, timeout, &id);
00244     if (ret > 0 && id == mux_id) {
00245         return ret;
00246     }
00247     return 0;
00248 }
00249 
00250 uint32_t ESP8266::recv(uint8_t *coming_mux_id, uint8_t *buffer, uint32_t buffer_size, uint32_t timeout)
00251 {
00252     return recvPkg(buffer, buffer_size, NULL, timeout, coming_mux_id);
00253 }
00254 
00255 /*----------------------------------------------------------------------------*/
00256 
00257 uint32_t ESP8266::recvPkg(uint8_t *buffer, uint32_t buffer_size, uint32_t *data_len, uint32_t timeout, uint8_t *coming_mux_id)
00258 {
00259     String data;
00260     char a;
00261     int32_t index_PIPDcomma = -1;
00262     int32_t index_colon = -1; /* : */
00263     int32_t index_comma = -1; /* , */
00264     int32_t len = -1;
00265     int8_t id = -1;
00266     bool has_data = false;
00267     logDebug("start recv pkg");
00268     
00269     unsigned long start = millis();
00270     while (millis() - start < timeout) {
00271         while(m_puart->available() > 0) {
00272             a = m_puart->readChr();
00273             data += a;
00274         }
00275         
00276         index_PIPDcomma = data.indexOf("+IPD,");
00277         if (index_PIPDcomma != -1) {
00278             logDebug("index_PIPDcomma found = %d", index_PIPDcomma);
00279             index_colon = data.indexOf(':', index_PIPDcomma + 5);
00280             if (index_colon != -1) {
00281                 logDebug("data1 = %s\r\n", data.c_str());
00282                 logDebug("index_colon found = %d", index_colon);
00283                 
00284                 index_comma = data.indexOf(',', index_PIPDcomma + 5);
00285                 logDebug("index_comma found = %d", index_comma);
00286                 
00287                 if (index_comma != -1 && index_comma < index_colon) { /* +IPD,id,len:data */
00288                     logDebug("id = %d", id);
00289                     id = data.substring(index_PIPDcomma + 5, index_comma).toInt();
00290                     logDebug("id = %d", id);
00291                     if (id < 0 || id > 4) {
00292                         return 0;
00293                     }
00294                     logDebug("len = %d", len);
00295                     len = data.substring(index_comma + 1, index_colon).toInt();
00296                     logDebug("len = %d", len);
00297                     if (len <= 0) {
00298                         return 0;
00299                     }
00300                     logDebug("has id");
00301                 } else { /* +IPD,len:data */
00302                     len = data.substring(index_PIPDcomma + 5, index_colon).toInt();
00303                     logDebug("len = %d", len);
00304                     if (len <= 0) {
00305                         return 0;
00306                     }
00307                     logDebug("no id");
00308                 }
00309                 has_data = true;
00310                 logDebug("has_data true");
00311                 break;
00312             }
00313         }
00314     }
00315     //logDebug("has_data = %u\r\n", has_data);
00316     //logDebug("data2 = %s\r\n", data.c_str());
00317     
00318     if (has_data) {
00319         start = millis();
00320         while (millis() - start < 3000) {
00321             while(m_puart->available() > 0) {
00322                 a = m_puart->readChr();
00323                 data += a;
00324             }
00325             //logDebug("data3 = %s\r\n", data.c_str());
00326             if (data.length() >= index_colon + 1 + len) {
00327                 if (data_len) {
00328                     *data_len = len;    
00329                 }
00330                 if (index_comma != -1 && coming_mux_id) {
00331                     *coming_mux_id = id;
00332                 }
00333                 //logDebug("len = %d", len);
00334                 //logDebug("buffer_size = %d", buffer_size);
00335                 uint32_t ret = len > buffer_size ? buffer_size : len;
00336                 
00337                 memcpy(buffer, 
00338                     data.substring(index_colon + 1, index_colon + 1 + len).c_str(), 
00339                     ret);
00340                 logDebug("ret = %u\r\n", ret);
00341                 return ret;
00342             }
00343         }
00344     }
00345     logDebug("end recv pkg");
00346     return 0;
00347 }
00348 
00349 String ESP8266::recvString(String target, uint32_t timeout)
00350 {
00351     String data;
00352     char a;
00353     unsigned long start = millis();
00354     while (millis() - start < timeout) {
00355         while(m_puart->available() > 0) {
00356             a = m_puart->readChr();
00357             data += a;
00358         }
00359         if (data.indexOf(target) != -1) {
00360             break;
00361         }   
00362     }
00363     return data;
00364 }
00365 
00366 String ESP8266::recvString(String target1, String target2, uint32_t timeout)
00367 {
00368     String data;
00369     char a;
00370     unsigned long start = millis();
00371     while (millis() - start < timeout) {
00372         while(m_puart->available() > 0) {
00373             a = m_puart->readChr();
00374             data += a;
00375         }
00376         if (data.indexOf(target1) != -1) {
00377             break;
00378         } else if (data.indexOf(target2) != -1) {
00379             break;
00380         }
00381     }
00382     return data;
00383 }
00384 
00385 String ESP8266::recvString(String target1, String target2, String target3, uint32_t timeout)
00386 {
00387     String data;
00388     char a;
00389     unsigned long start = millis();
00390     while (millis() - start < timeout) {
00391         while(m_puart->available() > 0) {
00392             a = m_puart->readChr();
00393             data += a;
00394         }
00395         if (data.indexOf(target1) != -1) {
00396             break;
00397         } else if (data.indexOf(target2) != -1) {
00398             break;
00399         } else if (data.indexOf(target3) != -1) {
00400             break;
00401         }
00402     }
00403     return data;
00404 }
00405 
00406 bool ESP8266::recvFind(String target, uint32_t timeout)
00407 {
00408     String data_tmp;
00409     data_tmp = recvString(target, timeout);
00410     if (data_tmp.indexOf(target) != -1) {
00411         return true;
00412     }
00413     return false;
00414 }
00415 
00416 bool ESP8266::recvFindAndFilter(String target, String begin, String end, String &data, uint32_t timeout)
00417 {
00418     String data_tmp;
00419     data_tmp = recvString(target, timeout);
00420     if (data_tmp.indexOf(target) != -1) {
00421         int32_t index1 = data_tmp.indexOf(begin);
00422         int32_t index2 = data_tmp.indexOf(end);
00423         if (index1 != -1 && index2 != -1) {
00424             index1 += begin.length();
00425             data = data_tmp.substring(index1, index2);
00426             return true;
00427         }
00428     }
00429     data = "";
00430     return false;
00431 }
00432 
00433 bool ESP8266::eAT(void)
00434 {
00435     m_puart->flush();
00436     m_puart->println("AT");
00437     return recvFind("OK");
00438 }
00439 
00440 bool ESP8266::eATRST(void) 
00441 {
00442     m_puart->flush();
00443     m_puart->println("AT+RST");
00444     return recvFind("OK");
00445 }
00446 
00447 bool ESP8266::eATGMR(String &version)
00448 {
00449     m_puart->flush();
00450     m_puart->println("AT+GMR");
00451     return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", version); 
00452 }
00453 
00454 bool ESP8266::qATCWMODE(uint8_t *mode) 
00455 {
00456     String str_mode;
00457     bool ret;
00458     if (!mode) {
00459         return false;
00460     }
00461     m_puart->flush();
00462     m_puart->println("AT+CWMODE?");
00463     ret = recvFindAndFilter("OK", "+CWMODE:", "\r\n\r\nOK", str_mode); 
00464     if (ret) {
00465         *mode = (uint8_t)str_mode.toInt();
00466         return true;
00467     } else {
00468         return false;
00469     }
00470 }
00471 
00472 bool ESP8266::sATCWMODE(uint8_t mode)
00473 {
00474     String data;
00475     m_puart->flush();
00476     m_puart->print("AT+CWMODE=");
00477     m_puart->println(mode);
00478     
00479     data = recvString("OK", "no change");
00480     if (data.indexOf("OK") != -1 || data.indexOf("no change") != -1) {
00481         return true;
00482     }
00483     return false;
00484 }
00485 
00486 bool ESP8266::sATCWJAP(String ssid, String pwd)
00487 {
00488     String data;
00489     m_puart->flush();
00490     m_puart->print("AT+CWJAP=\"");
00491     m_puart->print(ssid);
00492     m_puart->print("\",\"");
00493     m_puart->print(pwd);
00494     m_puart->println("\"");
00495     
00496     data = recvString("OK", "FAIL", 10000);
00497     if (data.indexOf("OK") != -1) {
00498         return true;
00499     }
00500     return false;
00501 }
00502 
00503 bool ESP8266::eATCWLAP(String &list)
00504 {
00505     String data;
00506     m_puart->flush();
00507     m_puart->println("AT+CWLAP");
00508     return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list, 10000);
00509 }
00510 
00511 bool ESP8266::eATCWQAP(void)
00512 {
00513     String data;
00514     m_puart->flush();
00515     m_puart->println("AT+CWQAP");
00516     return recvFind("OK");
00517 }
00518 
00519 bool ESP8266::sATCWSAP(String ssid, String pwd, uint8_t chl, uint8_t ecn)
00520 {
00521     String data;
00522     m_puart->flush();
00523     m_puart->print("AT+CWSAP=\"");
00524     m_puart->print(ssid);
00525     m_puart->print("\",\"");
00526     m_puart->print(pwd);
00527     m_puart->print("\",");
00528     m_puart->print(chl);
00529     m_puart->print(",");
00530     m_puart->println(ecn);
00531     
00532     data = recvString("OK", "ERROR", 5000);
00533     if (data.indexOf("OK") != -1) {
00534         return true;
00535     }
00536     return false;
00537 }
00538 
00539 bool ESP8266::eATCWLIF(String &list)
00540 {
00541     String data;
00542     m_puart->flush();
00543     m_puart->println("AT+CWLIF");
00544     return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
00545 }
00546 bool ESP8266::eATCIPSTATUS(String &list)
00547 {
00548     String data;
00549     delay(100);
00550     m_puart->flush();
00551     m_puart->println("AT+CIPSTATUS");
00552     return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
00553 }
00554 bool ESP8266::sATCIPSTARTSingle(String type, String addr, uint32_t port)
00555 {
00556     String data;
00557     m_puart->flush();
00558     m_puart->print("AT+CIPSTART=\"");
00559     m_puart->print(type);
00560     m_puart->print("\",\"");
00561     m_puart->print(addr);
00562     m_puart->print("\",");
00563     m_puart->println(port);
00564     
00565     data = recvString("OK", "ERROR", "ALREADY CONNECT", 10000);
00566     if (data.indexOf("OK") != -1 || data.indexOf("ALREADY CONNECT") != -1) {
00567         return true;
00568     }
00569     return false;
00570 }
00571 bool ESP8266::sATCIPSTARTMultiple(uint8_t mux_id, String type, String addr, uint32_t port)
00572 {
00573     String data;
00574     m_puart->flush();
00575     m_puart->print("AT+CIPSTART=");
00576     m_puart->print(mux_id);
00577     m_puart->print(",\"");
00578     m_puart->print(type);
00579     m_puart->print("\",\"");
00580     m_puart->print(addr);
00581     m_puart->print("\",");
00582     m_puart->println(port);
00583     
00584     data = recvString("OK", "ERROR", "ALREADY CONNECT", 10000);
00585     if (data.indexOf("OK") != -1 || data.indexOf("ALREADY CONNECT") != -1) {
00586         return true;
00587     }
00588     return false;
00589 }
00590 bool ESP8266::sATCIPSENDSingle(const uint8_t *buffer, uint32_t len)
00591 {
00592     m_puart->flush();
00593     m_puart->print("AT+CIPSEND=");
00594     m_puart->println(len);
00595     if (recvFind(">", 5000)) {
00596         m_puart->flush();
00597         for (uint32_t i = 0; i < len; i++) {
00598             m_puart->write(buffer[i]);
00599         }
00600         return recvFind("SEND OK", 10000);
00601     }
00602     return false;
00603 }
00604 bool ESP8266::sATCIPSENDMultiple(uint8_t mux_id, const uint8_t *buffer, uint32_t len)
00605 {
00606     m_puart->flush();
00607     m_puart->print("AT+CIPSEND=");
00608     m_puart->print(mux_id);
00609     m_puart->print(",");
00610     m_puart->println(len);
00611     if (recvFind(">", 5000)) {
00612         m_puart->flush();
00613         for (uint32_t i = 0; i < len; i++) {
00614             m_puart->write(buffer[i]);
00615         }
00616         return recvFind("SEND OK", 10000);
00617     }
00618     return false;
00619 }
00620 bool ESP8266::sATCIPCLOSEMulitple(uint8_t mux_id)
00621 {
00622     String data;
00623     m_puart->flush();
00624     m_puart->print("AT+CIPCLOSE=");
00625     m_puart->println(mux_id);
00626     
00627     data = recvString("OK", "Link is not", 5000);
00628     if (data.indexOf("OK") != -1 || data.indexOf("Link is not") != -1) {
00629         return true;
00630     }
00631     return false;
00632 }
00633 bool ESP8266::eATCIPCLOSESingle(void)
00634 {
00635     m_puart->flush();
00636     m_puart->println("AT+CIPCLOSE");
00637     return recvFind("OK", 5000);
00638 }
00639 bool ESP8266::eATCIFSR(String &list)
00640 {
00641     m_puart->flush();
00642     m_puart->println("AT+CIFSR");
00643     return recvFindAndFilter("OK", "\r\r\n", "\r\n\r\nOK", list);
00644 }
00645 bool ESP8266::sATCIPMUX(uint8_t mode)
00646 {
00647     String data;
00648     m_puart->flush();
00649     m_puart->print("AT+CIPMUX=");
00650     m_puart->println(mode);
00651     
00652     data = recvString("OK", "Link is builded");
00653     if (data.indexOf("OK") != -1) {
00654         return true;
00655     }
00656     return false;
00657 }
00658 bool ESP8266::sATCIPSERVER(uint8_t mode, uint32_t port)
00659 {
00660     String data;
00661     if (mode) {
00662         m_puart->flush();
00663         m_puart->print("AT+CIPSERVER=1,");
00664         m_puart->println(port);
00665         
00666         data = recvString("OK", "no change");
00667         if (data.indexOf("OK") != -1 || data.indexOf("no change") != -1) {
00668             return true;
00669         }
00670         return false;
00671     } else {
00672         m_puart->flush();
00673         m_puart->println("AT+CIPSERVER=0");
00674         return recvFind("\r\r\n");
00675     }
00676 }
00677 bool ESP8266::sATCIPSTO(uint32_t timeout)
00678 {
00679     m_puart->flush();
00680     m_puart->print("AT+CIPSTO=");
00681     m_puart->println(timeout);
00682     return recvFind("OK");
00683 }