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.
Dependencies: BufferedSerial
Dependents: esp8266_nodeMCU1 esp8266_2_thingspeak1 Solarator_0-0-2 IoTBurglar_and_Fire_AlarmSystem ... more
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 #define INFO(x, ...) printf("[ESP8266 : INFO]"x" \t[%s,%d]\r\n", ##__VA_ARGS__,__FILE__,__LINE__); 00031 #ifndef ESP8266_ECHO 00032 #define ESP8266_ECHO 1 00033 #endif 00034 #else 00035 #define DBG(x, ...) 00036 #define WARN(x, ...) 00037 #define ERR(x, ...) 00038 #define INFO(x, ...) 00039 #endif 00040 00041 00042 ESP8266 *ESP8266::_inst; 00043 00044 ESP8266::ESP8266(PinName tx, PinName rx, PinName reset, int baud, int timeout) : 00045 _serial(tx, rx), _reset_pin(reset) { 00046 INFO("Initializing ESP8266 object"); 00047 00048 _baud = baud; 00049 _timeout = timeout; 00050 00051 _serial.baud(_baud); 00052 00053 _inst = this; 00054 } 00055 00056 bool ESP8266::reset() { 00057 _reset_pin = 0; 00058 wait_us(20); 00059 _reset_pin = 1; 00060 00061 // Send reboot command in case reset is not connected 00062 return command("\x03\r\n" "node.restart()") && execute(); 00063 } 00064 00065 bool ESP8266::init() { 00066 // Reset device to clear state 00067 return reset(); 00068 } 00069 00070 bool ESP8266::connect(const char *ssid, const char *phrase) { 00071 // Configure as station with passed ssid and passphrase 00072 if (!(command("wifi.setmode(wifi.STATION);") && 00073 command("wifi.sta.config('") && 00074 command(ssid) && 00075 command("','") && 00076 command(phrase) && 00077 command("')") && 00078 execute())) 00079 return false; 00080 00081 // Wait for an IP address 00082 // TODO WISHLIST make this a seperate check so it can run asynch? 00083 Timer timer; 00084 timer.start(); 00085 00086 while (true) { 00087 int ip_len = 15; 00088 00089 if (!(command("ip=wifi.sta.getip();") && 00090 command("print(ip)") && 00091 execute(_ip, &ip_len))) 00092 return false; 00093 00094 _ip[ip_len] = 0; 00095 00096 if (strcmp(_ip, "nil") != 0) 00097 return true; 00098 00099 if (timer.read_ms() > _timeout) 00100 return false; 00101 } 00102 } 00103 00104 bool ESP8266::disconnect() { 00105 int ip_len = 15; 00106 00107 if (!(command("wifi.sta.disconnect();") && 00108 command("ip=wifi.sta.getip();") && 00109 command("print(ip)") && 00110 execute(_ip, &ip_len))) 00111 return false; 00112 00113 _ip[ip_len] = 0; 00114 00115 return (strcmp(_ip, "nil") == 0); 00116 } 00117 00118 bool ESP8266::is_connected() { 00119 return (strcmp(_ip, "nil") != 0); 00120 } 00121 00122 bool ESP8266::open(bool type, char* ip, int port, int id) { 00123 // Create the actual connection 00124 if (!(command("c=net.createConnection(") && 00125 command(type ? "net.TCP" : "net.UDP") && 00126 command(")") && 00127 execute())) 00128 return false; 00129 00130 // Setup handlers for connecting and disconnecting 00131 if (!(command("cc=nil;") && 00132 command("c:on('connection',function() cc=true end);") && 00133 command("c:on('disconnection',function() cc=false end)") && 00134 execute())) 00135 return false; 00136 00137 // Setup functions for sending and recieving characters on the esp side 00138 if (!(command("cm='';") && 00139 command("function cs(n) c:send(n) end;") && 00140 command("function ca() print(#cm) end;") && 00141 command("function cr(n) " 00142 "d=cm:sub(1,n):gsub('.', function(s) " 00143 "return s.format('\\\\%03d', s:byte(1)) " 00144 "end);" 00145 "cm=cm:sub(n+1,-1);" 00146 "print(d) " 00147 "end;") && 00148 command("c:on('receive',function(c,n) cm=cm..n end)") && 00149 execute())) 00150 return false; 00151 00152 // Convert port to a string 00153 char port_buf[16]; 00154 sprintf(port_buf, "%d", port); 00155 00156 // Connect to the ip address 00157 if (!(command("c:connect(") && 00158 command(port_buf) && 00159 command(",'") && 00160 command(ip) && 00161 command("')") && 00162 execute())) 00163 return false; 00164 00165 // Wait for it to connect 00166 // TODO WISHLIST make this a seperate check so it can run asynch? 00167 Timer timer; 00168 timer.start(); 00169 00170 while (true) { 00171 char con_buf[5]; 00172 int con_len = 5; 00173 00174 if (!(command("print(cc)") && execute(con_buf, &con_len))) 00175 return false; 00176 00177 if (memcmp(con_buf, "true", con_len) == 0) 00178 return true; 00179 else if (memcmp(con_buf, "false", con_len) == 0) 00180 return false; 00181 00182 if (timer.read_ms() > _timeout) 00183 return false; 00184 } 00185 } 00186 00187 bool ESP8266::close() { 00188 return command("c:close();" "c=nil") && execute(); 00189 } 00190 00191 bool ESP8266::send(const char *buffer, int len) { 00192 for (int line = 0; line < len; line += ESP_MAX_LINE) { 00193 if (!command("cs('")) 00194 return false; 00195 00196 for (int i = 0; i < ESP_MAX_LINE && line+i < len; i++) { 00197 int a = buffer[line+i] / 100; 00198 int b = (buffer[line+i] - a*100) / 10; 00199 int c = (buffer[line+i] - a*100 - b*10); 00200 00201 if (serialputc('\\') < 0 || 00202 serialputc(a + '0') < 0 || 00203 serialputc(b + '0') < 0 || 00204 serialputc(c + '0') < 0) 00205 return false; 00206 } 00207 00208 if (!(command("')") && execute())) 00209 return false; 00210 } 00211 00212 return true; 00213 } 00214 00215 bool ESP8266::recv(char *buffer, int *len) { 00216 char len_buf[16]; 00217 sprintf(len_buf, "%d", *len); 00218 00219 if (!(command("cr(") && 00220 command(len_buf) && 00221 command(")"))) 00222 return false; 00223 00224 if (!(command("\r\n") && discardEcho())) 00225 return false; 00226 00227 // Read in response 00228 for (int i = 0; i < *len; i++) { 00229 int e = serialgetc(); 00230 00231 if (e == '\r') { 00232 *len = i; 00233 break; 00234 } else if (e != '\\') { 00235 return false; 00236 } 00237 00238 int a = serialgetc(); 00239 int b = serialgetc(); 00240 int c = serialgetc(); 00241 00242 if (a < 0 || b < 0 || c < 0) 00243 return false; 00244 00245 buffer[i] = (a-'0')*100 + (b-'0')*10 + (c-'0'); 00246 } 00247 00248 // Flush to next prompt 00249 return flush(); 00250 } 00251 00252 int ESP8266::putc(char c) { 00253 char buffer[1] = { c }; 00254 00255 return send(buffer, 1) ? 0 : -1; 00256 } 00257 00258 int ESP8266::getc() { 00259 char buffer[1]; 00260 00261 while (true) { 00262 int len = 1; 00263 00264 if (!recv(buffer, &len)) 00265 return -1; 00266 00267 if (len > 0) 00268 break; 00269 } 00270 00271 return buffer[0]; 00272 } 00273 00274 int ESP8266::writeable() { 00275 // Always succeeds since message can be temporarily stored on the esp 00276 return 1; 00277 } 00278 00279 int ESP8266::readable() { 00280 char count_buf[16]; 00281 int count_len = 15; 00282 00283 if (!(command("ca()") && execute(count_buf, &count_len))) 00284 return false; 00285 00286 count_buf[count_len] = 0; 00287 return atoi(count_buf); 00288 } 00289 00290 const char *ESP8266::getIPAddress() { 00291 if (strcmp(_ip, "nil") != 0) 00292 return _ip; 00293 else 00294 return 0; 00295 } 00296 00297 bool ESP8266::getHostByName(const char *host, char *ip) { 00298 if (!(command("dh='") && 00299 command(host) && 00300 command("';") && 00301 command("dn=nil;") && 00302 command("if dh:match('%d+.%d+.%d+.%d+') then ") && 00303 command("dn=dh ") && 00304 command("else ") && 00305 command("dc=net.createConnection(net.TCP);") && 00306 command("dc:dns(dh,function(dc,ip) dn=ip end);") && 00307 command("dc=nil ") && 00308 command("end") && 00309 execute())) 00310 return false; 00311 00312 // Wait for a response 00313 Timer timer; 00314 timer.start(); 00315 00316 while (true) { 00317 int ip_len = 15; 00318 00319 if (!(command("print(dn)") && execute(ip, &ip_len))) 00320 return false; 00321 00322 ip[ip_len] = 0; 00323 00324 if (strcmp(ip, "nil") != 0) 00325 return true; 00326 00327 if (timer.read_ms() > _timeout) 00328 return false; 00329 } 00330 } 00331 00332 int ESP8266::serialgetc() { 00333 Timer timer; 00334 timer.start(); 00335 00336 while (true) { 00337 if (_serial.readable()) { 00338 char c = _serial.getc(); 00339 #ifdef ESP8266_ECHO 00340 printf("%c", c); 00341 #endif 00342 return c; 00343 } 00344 00345 if (timer.read_ms() > _timeout) 00346 return -1; 00347 } 00348 } 00349 00350 int ESP8266::serialputc(char c) { 00351 Timer timer; 00352 timer.start(); 00353 00354 while (true) { 00355 if (_serial.writeable()) 00356 return _serial.putc(c); 00357 00358 if (timer.read_ms() > _timeout) 00359 return -1; 00360 } 00361 } 00362 00363 bool ESP8266::discardEcho() { 00364 while (true) { 00365 int c = serialgetc(); 00366 00367 if (c < 0) 00368 return false; 00369 else if (c == '\n') 00370 return true; 00371 } 00372 } 00373 00374 bool ESP8266::flush() { 00375 while (true) { 00376 int c = serialgetc(); 00377 00378 if (c < 0) 00379 return false; 00380 else if (c == '>') 00381 return true; 00382 } 00383 } 00384 00385 bool ESP8266::command(const char *cmd) { 00386 DBG("command sent:\t %s", cmd); 00387 00388 for (int i = 0; cmd[i]; i++) { 00389 if (serialputc(cmd[i]) < 0) 00390 return false; 00391 } 00392 00393 return true; 00394 } 00395 00396 bool ESP8266::execute(char *resp_buf, int *resp_len) { 00397 // Finish command with a newline 00398 if (!(command("\r\n") && discardEcho())) 00399 return false; 00400 00401 // Read in response if any 00402 if (resp_buf && resp_len) { 00403 int i; 00404 00405 for (i = 0; i < *resp_len; i++) { 00406 int c = serialgetc(); 00407 00408 if (c < 0) 00409 return false; 00410 00411 if (c == '\r') { 00412 *resp_len = i; 00413 break; 00414 } 00415 00416 resp_buf[i] = c; 00417 } 00418 00419 DBG("command response:\t %.*s", *resp_len, resp_buf); 00420 } 00421 00422 return flush(); 00423 }
Generated on Tue Jul 12 2022 18:54:25 by
1.7.2

Adafruit Huzzah