for testing wifi
Fork of ESP8266Interface by
Embed:
(wiki syntax)
Show/hide line numbers
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