Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of ESP8266Interface by
ESP8266.cpp
00001 /* Copyright (C) 2012 mbed.org, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 #include "mbed.h" 00020 #include "ESP8266.h" 00021 #include "Endpoint.h" 00022 #include <string> 00023 #include <algorithm> 00024 00025 //Debug is disabled by default 00026 #if 0 00027 #define DBG(x, ...) printf("[ESP8266 : DBG]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00028 #define WARN(x, ...) printf("[ESP8266 : WARN]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00029 #define ERR(x, ...) printf("[ESP8266 : ERR]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00030 #else 00031 #define DBG(x, ...) //wait_us(10); 00032 #define WARN(x, ...) //wait_us(10); 00033 #define ERR(x, ...) 00034 #endif 00035 00036 #if 0 00037 #define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00038 #else 00039 #define INFO(x, ...) 00040 #endif 00041 00042 #define ESP_MAX_TRY_JOIN 3 00043 #define ESP_MAXID 4 // the largest possible ID Value (max num of sockets possible) 00044 00045 ESP8266 * ESP8266::inst; 00046 char* ip = NULL; 00047 00048 ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, const char *ssid, const char *phrase, uint32_t baud) : 00049 wifi(tx, rx), reset_pin(reset), buf_ESP8266(ESP_MBUFFE_MAX) 00050 { 00051 INFO("Initializing ESP8266 object"); 00052 memset(&state, 0, sizeof(state)); 00053 00054 00055 strcpy(this->ssid, ssid); 00056 strcpy(this->phrase, phrase); 00057 inst = this; 00058 attach_rx(false); 00059 00060 wifi.baud(baud); // initial baud rate of the ESP8266 00061 00062 state.associated = false; 00063 state.cmdMode = false; 00064 } 00065 00066 bool ESP8266::join() 00067 { 00068 sendCommand( "AT+CWMODE=1", "change", NULL, 1000); 00069 string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\""; 00070 if( sendCommand( cmd.c_str(), "OK", NULL, 10000) ) { 00071 // successfully joined the network 00072 state.associated = true; 00073 INFO("ssid: %s, phrase: %s", this->ssid, this->phrase); 00074 00075 return true; 00076 } 00077 return false; 00078 } 00079 00080 bool ESP8266::connect() 00081 { 00082 sendCommand("AT+CWDHCP=1,1","OK",NULL,1000); // DHCP Enabled in Station Mode 00083 return ESP8266::join(); 00084 } 00085 00086 bool ESP8266::is_connected() 00087 { 00088 return true; 00089 } 00090 00091 bool ESP8266::start(bool type,char* ip, int port, int id) 00092 { 00093 // Error Check 00094 if(id > ESP_MAXID) { 00095 ERR("startUDPMulti: max id is: %d, id given is %d",ESP_MAXID,id); 00096 return false; 00097 } 00098 // Single Connection Mode 00099 if(id < 0) { 00100 DBG("Start Single Connection Mode"); 00101 char portstr[5]; 00102 char idstr[2]; 00103 bool check [3] = {0}; 00104 sprintf(idstr,"%d",id); 00105 sprintf(portstr, "%d", port); 00106 switch(type) { 00107 case ESP_UDP_TYPE : //UDP 00108 check[0] = sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00109 break; 00110 case ESP_TCP_TYPE : //TCP 00111 check[0] = sendCommand(( "AT+CIPSTART=\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00112 break; 00113 default: 00114 ERR("Default hit for starting connection, this shouldnt be possible!!"); 00115 break; 00116 } 00117 check[1] = sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode 00118 check[2] = sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode 00119 // check that all commands were sucessful 00120 if(check[0] and check[1] and check[2]) { 00121 state.cmdMode = false; 00122 return true; 00123 } else { 00124 ERR("startUDPTransparent Failed for ip:%s, port:%d",ip,port); 00125 return false; 00126 } 00127 } 00128 // Multi Connection Mode 00129 else { 00130 //TODO: impliment Multi Connection Mode 00131 ERR("Not currently Supported!"); 00132 return false; 00133 00134 // DBG("Start Multi Connection Mode"); 00135 // char portstr[5]; 00136 // char idstr[2]; 00137 // bool check [3] = {0}; 00138 // sprintf(idstr,"%d",id); 00139 // sprintf(portstr, "%d", port); 00140 // switch(type) { 00141 // case ESP_UDP_TYPE : //UDP 00142 // check[0] = sendCommand(( "AT+CIPSTART=" + (string) idstr + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00143 // break; 00144 // case ESP_TCP_TYPE : //TCP 00145 // check[0] = sendCommand(( "AT+CIPSTART=" + (string) idstr + ",\"TCP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000); 00146 // break; 00147 // default: 00148 // ERR("Default hit for starting connection, this shouldnt be possible!!"); 00149 // break; 00150 // } 00151 } 00152 } 00153 00154 bool ESP8266::startUDP(char* ip, int port, int id, int length) 00155 { 00156 char portstr[5]; 00157 char idstr[1]; 00158 char lenstr[2]; 00159 00160 sprintf(portstr, "%d", port); 00161 sprintf(idstr, "%d", id); 00162 sprintf(lenstr, "%d", length); 00163 00164 sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00165 sendCommand(( "AT+CIPSTART=" + string(idstr) + ",\"UDP\",\"" + (string) ip + "\"," + (string) portstr + ",1112,0").c_str(), "OK", NULL, 10000); 00166 sendCommand(("AT+CIPSEND=" + (string)idstr + "," + (string)lenstr).c_str(), ">", NULL, 1000);// go into transparent mode 00167 DBG("Data Mode\r\n"); 00168 state.cmdMode = false; 00169 00170 return true; 00171 } 00172 00173 bool ESP8266::startTCPServer(int port) 00174 { 00175 bool command_results[3]; 00176 command_results[0]=sendCommand("AT+CWMODE=3", "OK", NULL, 1000); 00177 command_results[1]=sendCommand("AT+CIPMUX=1", "OK", NULL, 1000); 00178 if(port == 333){ 00179 command_results[2]=sendCommand("AT+CIPSERVER=1", "OK", NULL, 1000); 00180 } 00181 else{ 00182 char portstr[5]; 00183 sprintf(portstr, "%d", port); 00184 command_results[2]=sendCommand(("AT+CIPSERVER=1," + (string)portstr).c_str(), "OK", NULL, 1000); 00185 } 00186 //sendCommand("AT+CIFSR", "OK", NULL, 1000); 00187 DBG("Data Mode\r\n"); 00188 state.cmdMode = false; 00189 if (command_results[0] and command_results[1] and command_results[2]){ 00190 return true; 00191 } 00192 else{ 00193 return false; 00194 } 00195 } 00196 00197 bool ESP8266::close() 00198 { 00199 wait(0.1f); 00200 send("+++",3); 00201 wait(1.0f); 00202 state.cmdMode = true; 00203 sendCommand("AT+CIPCLOSE","OK", NULL, 10000); 00204 return true; 00205 } 00206 00207 bool ESP8266::disconnect() 00208 { 00209 // if already disconnected, return 00210 if (!state.associated) 00211 return true; 00212 // send command to quit AP 00213 sendCommand("AT+CWQAP", "OK", NULL, 10000); 00214 state.associated = false; 00215 return true; 00216 } 00217 00218 /* 00219 Assuming Returned data looks like this: 00220 +CIFSR:STAIP,"192.168.11.2" 00221 +CIFSR:STAMAC,"18:fe:34:9f:3a:f5" 00222 grabbing IP from first set of quotation marks 00223 */ 00224 extern RawSerial pc; 00225 char* ESP8266::getIPAddress() 00226 { 00227 char result[30] = {0}; 00228 int check = 0; 00229 check = sendCommand("AT+CIFSR", NULL, result, 1000); 00230 //pc.printf("\r\nReceivedInfo for IP Command is: %s\r\n",result); 00231 ip = ipString; 00232 if(check) { 00233 // Success 00234 string resultString(result); 00235 uint8_t pos1 = 0, pos2 = 0; 00236 //uint8_t pos3 = 0, pos4 = 0; 00237 pos1 = resultString.find("+CIFSR:STAIP"); 00238 pos1 = resultString.find('"',pos1); 00239 pos2 = resultString.find('"',pos1+1); 00240 //pos3 = resultString.find('"',pos2+1); //would find mac address 00241 //pos4 = resultString.find('"',pos3+1); 00242 // sekim XXXXX 00243 /* 00244 if ( pos2<=pos1 ) 00245 { 00246 pc.printf("\r\n IP String Error : (%d) (%d, %d) \r\n", strlen(result), pos1, pos2); 00247 return NULL; 00248 } 00249 */ 00250 strncpy(ipString,resultString.substr(pos1,pos2).c_str(),sizeof(ipString)); 00251 ipString[pos2 - pos1 +1] = 0; // null terminate string correctly. 00252 INFO("IP: %s",ipString); 00253 ip = ipString; 00254 00255 } else { 00256 // Failure 00257 ERR("getIPAddress() failed"); 00258 ip = NULL; 00259 } 00260 return ip; 00261 } 00262 00263 bool ESP8266::gethostbyname(const char * host, char * ip) 00264 { 00265 string h = host; 00266 int nb_digits = 0; 00267 00268 // no dns needed 00269 int pos = h.find("."); 00270 if (pos != string::npos) { 00271 string sub = h.substr(0, h.find(".")); 00272 nb_digits = atoi(sub.c_str()); 00273 } 00274 //printf("substrL %s\r\n", sub.c_str()); 00275 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) { 00276 strcpy(ip, host); 00277 return true; 00278 } else { 00279 // dns needed, not currently available 00280 ERR("gethostbyname(): DNS Not currently available, only use IP Addresses!"); 00281 return false; 00282 } 00283 } 00284 00285 void ESP8266::reset() 00286 { 00287 reset_pin = 0; 00288 wait_us(20); 00289 reset_pin = 1; 00290 wait(1); 00291 //reset_pin = !reset_pin 00292 //send("+++",3); 00293 //wait(1); 00294 state.cmdMode = true; 00295 sendCommand("AT", "OK", NULL, 1000); 00296 sendCommand("AT+RST", "ready", NULL, 10000); 00297 state.associated = false; 00298 00299 } 00300 00301 bool ESP8266::reboot() 00302 { 00303 reset(); 00304 return true; 00305 } 00306 00307 // sekim XXXX 00308 extern CircBuffer<char> buffer_ESP8266_recv; 00309 00310 void ESP8266::handler_rx(void) 00311 { 00312 //read characters 00313 char c; 00314 while (wifi.readable()) { 00315 c=wifi.getc(); 00316 buf_ESP8266.queue(c); 00317 //if (state.cmdMode) pc.printf("%c",c); //debug echo, needs fast serial console to prevent UART overruns 00318 00319 // sekim XXXX 00320 buffer_ESP8266_recv.queue(c); 00321 } 00322 } 00323 00324 void ESP8266::attach_rx(bool callback) 00325 { 00326 if (!callback) { 00327 wifi.attach(NULL); 00328 } 00329 else { 00330 wifi.attach(this, &ESP8266::handler_rx); 00331 } 00332 } 00333 00334 int ESP8266::readable() 00335 { 00336 return buf_ESP8266.available(); 00337 } 00338 00339 int ESP8266::writeable() 00340 { 00341 return wifi.writeable(); 00342 } 00343 00344 char ESP8266::getc() 00345 { 00346 char c=0; 00347 while (!buf_ESP8266.available()); 00348 buf_ESP8266.dequeue(&c); 00349 return c; 00350 } 00351 00352 int ESP8266::putc(char c) 00353 { 00354 while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first 00355 return wifi.putc(c); 00356 } 00357 00358 void ESP8266::flush() 00359 { 00360 buf_ESP8266.flush(); 00361 } 00362 00363 int ESP8266::send(const char * buf, int len) 00364 { 00365 //TODO: need to add handler for data > 2048B, this is the max packet size of the ESP8266. 00366 if(len >= 2048){ 00367 WARN("send buffer >= 2048B, need to chunk this up to be less."); 00368 } 00369 const char* bufptr=buf; 00370 for(int i=0; i<len; i++) { 00371 //pc.printf("%c", *bufptr); 00372 putc((int)*bufptr++); 00373 00374 } 00375 return len; 00376 } 00377 00378 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout) 00379 { 00380 char read; 00381 size_t found = string::npos; 00382 string checking = ""; 00383 Timer tmr; 00384 int result = 0; 00385 00386 DBG("sendCmd:\t %s",cmd); 00387 00388 attach_rx(true); 00389 00390 //We flush the buffer 00391 while (readable()) 00392 getc(); 00393 00394 if (!ACK || !strcmp(ACK, "NO")) { 00395 for (int i = 0; i < strlen(cmd); i++) { 00396 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00397 wait(0.005f); // prevents stuck recieve ready (?) need to let echoed character get read first 00398 } 00399 putc(13); //CR 00400 wait(0.005f); // wait for echo 00401 putc(10); //LF 00402 00403 } else { 00404 //We flush the buffer 00405 while (readable()) 00406 getc(); 00407 00408 tmr.start(); 00409 for (int i = 0; i < strlen(cmd); i++) { 00410 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result; 00411 wait(.005); // wait for echo 00412 } 00413 putc(13); //CR 00414 wait(0.005f); // wait for echo 00415 putc(10); //LF 00416 00417 while (1) { 00418 if (tmr.read_ms() > timeout) { 00419 //We flush the buffer 00420 while (readable()) 00421 getc(); 00422 00423 DBG("check:\t %s", checking.c_str()); 00424 00425 attach_rx(true); 00426 return -1; 00427 } else if (readable()) { 00428 read = getc(); 00429 //printf("%c",read); //debug echo 00430 if ( read != '\r' && read != '\n') { 00431 checking += read; 00432 found = checking.find(ACK); 00433 if (found != string::npos) { 00434 wait(0.01f); 00435 00436 //We flush the buffer 00437 while (readable()) 00438 read = getc(); 00439 //printf("%c",read); //debug echo 00440 break; 00441 } 00442 } 00443 } 00444 } 00445 DBG("check: %s", checking.c_str()); 00446 00447 attach_rx(true); 00448 return result; 00449 } 00450 00451 //the user wants the result from the command (ACK == NULL, res != NULL) 00452 if (res != NULL) { 00453 int i = 0; 00454 Timer timeout; 00455 timeout.start(); 00456 tmr.reset(); 00457 while (1) { 00458 if (timeout.read() > 2) { 00459 if (i == 0) { 00460 res = NULL; 00461 break; 00462 } 00463 res[i] = '\0'; 00464 DBG("user str 1: %s", res); 00465 00466 break; 00467 } else { 00468 if (tmr.read_ms() > 300) { 00469 res[i] = '\0'; 00470 DBG("user str: %s", res); 00471 00472 break; 00473 } 00474 if (readable()) { 00475 tmr.start(); 00476 read = getc(); 00477 00478 // we drop \r and \n 00479 if ( read != '\r' && read != '\n') { 00480 res[i++] = read; 00481 } 00482 } 00483 } 00484 } 00485 DBG("user str: %s", res); 00486 } 00487 00488 //We flush the buffer 00489 while (readable()) 00490 getc(); 00491 00492 attach_rx(true); 00493 DBG("result: %d", result) 00494 return result; 00495 } 00496
Generated on Sat Jul 23 2022 10:47:34 by
1.7.2
