ESP8266 Socket Library. AT Thinker firmware.

Dependents:   ESP8266_MQTT_HelloWorld ESP8266_IFTTT_Test ECE_4180_Lab_4 websocketmbed ... more

Fork of ESP8266Interface by ESP8266

This repository has been superceded

This project has moved to https://developer.mbed.org/teams/ESP8266/code/esp8266-driver/

This library works with the AT Thinker firmware.

Note

This library is currently in Beta. It is not feature complete and has some bugs, proceed with caution! Fixes and patches are welcome and appreciated!

Currently the ESP8266Interface Library has the following Abilities:

Working

  • TCP Client
  • UDP Client
  • Transparent mode (single connection of 1 type at a time)
  • Station Mode (connects to AP)

To be implemented

  • TCP Server
  • UDP Server
  • Multi Connection Mode (able to have up to 5 sockets at a time)
  • AP Mode (Make ESP Chip act like access point)
  • DNS Support (currently websites must be looked up by IP)
  • Error Recovery

Nice but not necessary

  • colorized text for ESP AT Commands in Command line (easier to differentiate from other text)
Committer:
michaeljkoster
Date:
Mon Dec 01 09:28:02 2014 +0000
Revision:
20:d764237405c2
Parent:
19:fb8d5bff2076
Child:
22:c4360e61486a
cleanup

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 1:fb4494783863 1 /* Copyright (C) 2012 mbed.org, MIT License
samux 1:fb4494783863 2 *
samux 1:fb4494783863 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
samux 1:fb4494783863 4 * and associated documentation files (the "Software"), to deal in the Software without restriction,
samux 1:fb4494783863 5 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
samux 1:fb4494783863 6 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
samux 1:fb4494783863 7 * furnished to do so, subject to the following conditions:
samux 1:fb4494783863 8 *
samux 1:fb4494783863 9 * The above copyright notice and this permission notice shall be included in all copies or
samux 1:fb4494783863 10 * substantial portions of the Software.
samux 1:fb4494783863 11 *
samux 1:fb4494783863 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
samux 1:fb4494783863 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
samux 1:fb4494783863 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
samux 1:fb4494783863 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
samux 1:fb4494783863 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
samux 1:fb4494783863 17 */
samux 1:fb4494783863 18
samux 1:fb4494783863 19 #include "mbed.h"
michaeljkoster 13:41098c907200 20 #include "ESP8266.h"
michaeljkoster 16:3f0efaa57a12 21 #include "Endpoint.h"
samux 1:fb4494783863 22 #include <string>
samux 1:fb4494783863 23 #include <algorithm>
samux 1:fb4494783863 24
samux 1:fb4494783863 25 //Debug is disabled by default
screamer 10:131675c17372 26 #if (defined(DEBUG))
michaeljkoster 13:41098c907200 27 #define DBG(x, ...) std::printf("[ESP8266 : DBG]"x"\r\n", ##__VA_ARGS__);
michaeljkoster 13:41098c907200 28 #define WARN(x, ...) std::printf("[ESP8266 : WARN]"x"\r\n", ##__VA_ARGS__);
michaeljkoster 13:41098c907200 29 #define ERR(x, ...) std::printf("[ESP8266 : ERR]"x"\r\n", ##__VA_ARGS__);
samux 1:fb4494783863 30 #else
samux 1:fb4494783863 31 #define DBG(x, ...)
samux 1:fb4494783863 32 #define WARN(x, ...)
samux 1:fb4494783863 33 #define ERR(x, ...)
samux 1:fb4494783863 34 #endif
samux 1:fb4494783863 35
screamer 10:131675c17372 36 #if defined(DEBUG)
michaeljkoster 13:41098c907200 37 #define INFO(x, ...) printf("[ESP8266 : INFO]"x"\r\n", ##__VA_ARGS__);
samux 1:fb4494783863 38 #else
samux 1:fb4494783863 39 #define INFO(x, ...)
samux 1:fb4494783863 40 #endif
samux 1:fb4494783863 41
samux 1:fb4494783863 42 #define MAX_TRY_JOIN 3
samux 1:fb4494783863 43
michaeljkoster 12:c5f0eac67a8a 44 extern Serial pc;
michaeljkoster 12:c5f0eac67a8a 45
michaeljkoster 13:41098c907200 46 ESP8266 * ESP8266::inst;
samux 1:fb4494783863 47
michaeljkoster 13:41098c907200 48 ESP8266::ESP8266( PinName tx, PinName rx, PinName _reset, const char * ssid, const char * phrase ):
michaeljkoster 13:41098c907200 49 wifi(tx, rx), reset_pin(_reset), buf_ESP8266(256)
samux 1:fb4494783863 50 {
samux 1:fb4494783863 51 memset(&state, 0, sizeof(state));
samux 1:fb4494783863 52
samux 1:fb4494783863 53 // change all ' ' in '$' in the ssid and the passphrase
samux 1:fb4494783863 54 strcpy(this->ssid, ssid);
samux 1:fb4494783863 55 for (int i = 0; i < strlen(ssid); i++) {
samux 1:fb4494783863 56 if (this->ssid[i] == ' ')
samux 1:fb4494783863 57 this->ssid[i] = '$';
samux 1:fb4494783863 58 }
samux 1:fb4494783863 59 strcpy(this->phrase, phrase);
samux 1:fb4494783863 60 for (int i = 0; i < strlen(phrase); i++) {
samux 1:fb4494783863 61 if (this->phrase[i] == ' ')
samux 1:fb4494783863 62 this->phrase[i] = '$';
samux 1:fb4494783863 63 }
samux 1:fb4494783863 64
samux 1:fb4494783863 65 inst = this;
samux 1:fb4494783863 66 attach_rx(false);
michaeljkoster 16:3f0efaa57a12 67
michaeljkoster 16:3f0efaa57a12 68 wifi.baud(9600); // initial baud rate of the ESP8266
samux 1:fb4494783863 69 }
samux 1:fb4494783863 70
michaeljkoster 13:41098c907200 71 bool ESP8266::join()
samux 1:fb4494783863 72 {
michaeljkoster 16:3f0efaa57a12 73 string cmd="AT+CWJAP=\""+(string)this->ssid+"\",\""+(string)this->phrase+"\"";
michaeljkoster 16:3f0efaa57a12 74 if( sendCommand( cmd.c_str(), "OK", NULL, 10000) ){
michaeljkoster 16:3f0efaa57a12 75 // successfully joined the network
samux 1:fb4494783863 76 state.associated = true;
michaeljkoster 13:41098c907200 77 INFO("\r\nssid: %s\r\nphrase: %s\r\nsecurity: %s\r\n\r\n", this->ssid, this->phrase);
samux 1:fb4494783863 78 return true;
samux 1:fb4494783863 79 }
samux 1:fb4494783863 80 return false;
samux 1:fb4494783863 81 }
samux 1:fb4494783863 82
michaeljkoster 13:41098c907200 83 bool ESP8266::connect()
samux 1:fb4494783863 84 {
michaeljkoster 16:3f0efaa57a12 85 return true;
samux 1:fb4494783863 86 }
samux 1:fb4494783863 87
michaeljkoster 15:37a7a56a424f 88 bool ESP8266::is_connected()
michaeljkoster 15:37a7a56a424f 89 {
michaeljkoster 15:37a7a56a424f 90 return true;
michaeljkoster 15:37a7a56a424f 91 }
michaeljkoster 15:37a7a56a424f 92
michaeljkoster 16:3f0efaa57a12 93 bool ESP8266::startUDP(char* ip, int port){
michaeljkoster 17:d11fa4c3ac65 94 char portstr[5];
michaeljkoster 16:3f0efaa57a12 95 sprintf(portstr, "%d", port);
michaeljkoster 18:60422852e99c 96 sendCommand(( "AT+CIPSTART=\"UDP\",\"" + (string) ip + "\"," + (string) portstr ).c_str(), "OK", NULL, 10000);
michaeljkoster 16:3f0efaa57a12 97
michaeljkoster 17:d11fa4c3ac65 98 sendCommand("AT+CIPMODE=1", "OK", NULL, 1000);// go into transparent mode
michaeljkoster 17:d11fa4c3ac65 99 sendCommand("AT+CIPSEND", ">", NULL, 1000);// go into transparent mode
michaeljkoster 16:3f0efaa57a12 100
michaeljkoster 16:3f0efaa57a12 101 return true;
michaeljkoster 16:3f0efaa57a12 102 }
michaeljkoster 16:3f0efaa57a12 103
michaeljkoster 15:37a7a56a424f 104 bool ESP8266::close()
michaeljkoster 15:37a7a56a424f 105 {
michaeljkoster 17:d11fa4c3ac65 106 send("+++",3);
michaeljkoster 17:d11fa4c3ac65 107 wait(1);
michaeljkoster 16:3f0efaa57a12 108 sendCommand("AT+CIPCLOSE","OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 109 return true;
michaeljkoster 15:37a7a56a424f 110 }
michaeljkoster 15:37a7a56a424f 111
michaeljkoster 15:37a7a56a424f 112 bool ESP8266::disconnect()
michaeljkoster 15:37a7a56a424f 113 {
michaeljkoster 15:37a7a56a424f 114 // if already disconnected, return
michaeljkoster 15:37a7a56a424f 115 if (!state.associated)
michaeljkoster 15:37a7a56a424f 116 return true;
michaeljkoster 15:37a7a56a424f 117 // send command to quit AP
michaeljkoster 16:3f0efaa57a12 118 sendCommand("AT+CWQAP", "OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 119 state.associated = false;
michaeljkoster 15:37a7a56a424f 120 return true;
michaeljkoster 15:37a7a56a424f 121 }
michaeljkoster 15:37a7a56a424f 122
michaeljkoster 15:37a7a56a424f 123 char* ESP8266::getIPAddress()
michaeljkoster 15:37a7a56a424f 124 {
michaeljkoster 16:3f0efaa57a12 125 sendCommand("AT+CWLIF", "OK", NULL, 10000);
michaeljkoster 15:37a7a56a424f 126 return ipString;
michaeljkoster 15:37a7a56a424f 127 }
michaeljkoster 15:37a7a56a424f 128
michaeljkoster 13:41098c907200 129 bool ESP8266::gethostbyname(const char * host, char * ip)
samux 1:fb4494783863 130 {
samux 1:fb4494783863 131 string h = host;
samux 1:fb4494783863 132 int nb_digits = 0;
samux 1:fb4494783863 133
samux 1:fb4494783863 134 // no dns needed
samux 1:fb4494783863 135 int pos = h.find(".");
samux 1:fb4494783863 136 if (pos != string::npos) {
samux 1:fb4494783863 137 string sub = h.substr(0, h.find("."));
samux 1:fb4494783863 138 nb_digits = atoi(sub.c_str());
samux 1:fb4494783863 139 }
samux 1:fb4494783863 140 //printf("substrL %s\r\n", sub.c_str());
samux 1:fb4494783863 141 if (count(h.begin(), h.end(), '.') == 3 && nb_digits > 0) {
samux 1:fb4494783863 142 strcpy(ip, host);
michaeljkoster 13:41098c907200 143 return true;
samux 1:fb4494783863 144 }
samux 1:fb4494783863 145 else {
michaeljkoster 13:41098c907200 146 // dns needed, not currently available
michaeljkoster 13:41098c907200 147 return false;
michaeljkoster 13:41098c907200 148 }
michaeljkoster 13:41098c907200 149 }
samux 1:fb4494783863 150
michaeljkoster 13:41098c907200 151 void ESP8266::reset()
samux 1:fb4494783863 152 {
michaeljkoster 16:3f0efaa57a12 153 sendCommand("AT+RST", "ready", NULL, 10000);
michaeljkoster 16:3f0efaa57a12 154 /*
samux 1:fb4494783863 155 reset_pin = 0;
samux 1:fb4494783863 156 wait(0.2);
samux 1:fb4494783863 157 reset_pin = 1;
samux 1:fb4494783863 158 wait(0.2);
michaeljkoster 16:3f0efaa57a12 159 */
samux 1:fb4494783863 160 }
samux 1:fb4494783863 161
michaeljkoster 13:41098c907200 162 bool ESP8266::reboot()
samux 3:9aa05e19c62e 163 {
michaeljkoster 16:3f0efaa57a12 164 reset();
samux 3:9aa05e19c62e 165 return true;
samux 3:9aa05e19c62e 166 }
samux 3:9aa05e19c62e 167
michaeljkoster 15:37a7a56a424f 168 void ESP8266::handler_rx(void)
samux 1:fb4494783863 169 {
michaeljkoster 15:37a7a56a424f 170 //read characters
michaeljkoster 16:3f0efaa57a12 171 char c;
michaeljkoster 16:3f0efaa57a12 172 while (wifi.readable()){
michaeljkoster 16:3f0efaa57a12 173 c=wifi.getc();
michaeljkoster 16:3f0efaa57a12 174 buf_ESP8266.queue(c);
michaeljkoster 20:d764237405c2 175 pc.printf("%c",c); //debug echo
michaeljkoster 16:3f0efaa57a12 176 }
michaeljkoster 15:37a7a56a424f 177 }
michaeljkoster 15:37a7a56a424f 178
michaeljkoster 15:37a7a56a424f 179 void ESP8266::attach_rx(bool callback)
michaeljkoster 15:37a7a56a424f 180 {
michaeljkoster 15:37a7a56a424f 181 if (!callback)
michaeljkoster 15:37a7a56a424f 182 wifi.attach(NULL);
michaeljkoster 15:37a7a56a424f 183 else
michaeljkoster 15:37a7a56a424f 184 wifi.attach(this, &ESP8266::handler_rx);
samux 1:fb4494783863 185 }
samux 1:fb4494783863 186
michaeljkoster 13:41098c907200 187 int ESP8266::readable()
samux 1:fb4494783863 188 {
michaeljkoster 13:41098c907200 189 return buf_ESP8266.available();
samux 1:fb4494783863 190 }
samux 1:fb4494783863 191
michaeljkoster 13:41098c907200 192 int ESP8266::writeable()
samux 1:fb4494783863 193 {
samux 1:fb4494783863 194 return wifi.writeable();
samux 1:fb4494783863 195 }
samux 1:fb4494783863 196
michaeljkoster 13:41098c907200 197 char ESP8266::getc()
samux 1:fb4494783863 198 {
michaeljkoster 14:4d1128f72e00 199 char c=0;
michaeljkoster 13:41098c907200 200 while (!buf_ESP8266.available());
michaeljkoster 13:41098c907200 201 buf_ESP8266.dequeue(&c);
samux 1:fb4494783863 202 return c;
samux 1:fb4494783863 203 }
samux 1:fb4494783863 204
michaeljkoster 15:37a7a56a424f 205 int ESP8266::putc(char c)
samux 1:fb4494783863 206 {
michaeljkoster 20:d764237405c2 207 while (!wifi.writeable() || wifi.readable()); //wait for echoed command characters to be read first
michaeljkoster 15:37a7a56a424f 208 return wifi.putc(c);
samux 1:fb4494783863 209 }
samux 1:fb4494783863 210
michaeljkoster 15:37a7a56a424f 211 void ESP8266::flush()
samux 1:fb4494783863 212 {
michaeljkoster 15:37a7a56a424f 213 buf_ESP8266.flush();
samux 1:fb4494783863 214 }
samux 1:fb4494783863 215
michaeljkoster 16:3f0efaa57a12 216 int ESP8266::send(const char * buf, int len)
michaeljkoster 15:37a7a56a424f 217 {
michaeljkoster 18:60422852e99c 218
michaeljkoster 16:3f0efaa57a12 219 const char* bufptr=buf;
michaeljkoster 16:3f0efaa57a12 220 for(int i=0; i<len; i++){
michaeljkoster 17:d11fa4c3ac65 221 putc((int)*bufptr++);
michaeljkoster 18:60422852e99c 222 }
michaeljkoster 19:fb8d5bff2076 223 return len;
michaeljkoster 15:37a7a56a424f 224 }
samux 1:fb4494783863 225
michaeljkoster 16:3f0efaa57a12 226 bool ESP8266::sendCommand(const char * cmd, const char * ACK, char * res, int timeout)
samux 1:fb4494783863 227 {
samux 1:fb4494783863 228 char read;
samux 1:fb4494783863 229 size_t found = string::npos;
samux 1:fb4494783863 230 string checking;
samux 1:fb4494783863 231 Timer tmr;
samux 1:fb4494783863 232 int result = 0;
samux 1:fb4494783863 233
michaeljkoster 17:d11fa4c3ac65 234 //pc.printf("will send: %s\r\n",cmd);
samux 1:fb4494783863 235
michaeljkoster 17:d11fa4c3ac65 236 attach_rx(true);
samux 1:fb4494783863 237
samux 1:fb4494783863 238 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 239 while (readable())
michaeljkoster 17:d11fa4c3ac65 240 getc();
michaeljkoster 16:3f0efaa57a12 241
samux 1:fb4494783863 242 if (!ACK || !strcmp(ACK, "NO")) {
michaeljkoster 17:d11fa4c3ac65 243 for (int i = 0; i < strlen(cmd); i++){
michaeljkoster 16:3f0efaa57a12 244 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
michaeljkoster 20:d764237405c2 245 wait(.005); // prevents stuck recieve ready (?) need to let echoed character get read first
michaeljkoster 16:3f0efaa57a12 246 }
michaeljkoster 16:3f0efaa57a12 247 putc(13); //CR
michaeljkoster 20:d764237405c2 248 wait(.005); // wait for echo
michaeljkoster 16:3f0efaa57a12 249 putc(10); //LF
michaeljkoster 16:3f0efaa57a12 250
samux 1:fb4494783863 251 } else {
samux 1:fb4494783863 252 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 253 while (readable())
michaeljkoster 17:d11fa4c3ac65 254 getc();
samux 1:fb4494783863 255
samux 1:fb4494783863 256 tmr.start();
michaeljkoster 17:d11fa4c3ac65 257 for (int i = 0; i < strlen(cmd); i++){
michaeljkoster 16:3f0efaa57a12 258 result = (putc(cmd[i]) == cmd[i]) ? result + 1 : result;
michaeljkoster 20:d764237405c2 259 wait(.005); // wait for echo
michaeljkoster 16:3f0efaa57a12 260 }
michaeljkoster 16:3f0efaa57a12 261 putc(13); //CR
michaeljkoster 20:d764237405c2 262 wait(.005); // wait for echo
michaeljkoster 16:3f0efaa57a12 263 putc(10); //LF
samux 1:fb4494783863 264
samux 1:fb4494783863 265 while (1) {
samux 1:fb4494783863 266 if (tmr.read_ms() > timeout) {
samux 1:fb4494783863 267 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 268 while (readable())
michaeljkoster 17:d11fa4c3ac65 269 getc();
samux 1:fb4494783863 270
samux 1:fb4494783863 271 DBG("check: %s\r\n", checking.c_str());
samux 1:fb4494783863 272
samux 1:fb4494783863 273 attach_rx(true);
samux 1:fb4494783863 274 return -1;
michaeljkoster 17:d11fa4c3ac65 275 } else if (readable()) {
michaeljkoster 17:d11fa4c3ac65 276 read = getc();
samux 1:fb4494783863 277 if ( read != '\r' && read != '\n') {
samux 1:fb4494783863 278 checking += read;
samux 1:fb4494783863 279 found = checking.find(ACK);
samux 1:fb4494783863 280 if (found != string::npos) {
samux 1:fb4494783863 281 wait(0.01);
samux 1:fb4494783863 282
samux 1:fb4494783863 283 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 284 while (readable())
michaeljkoster 17:d11fa4c3ac65 285 getc();
samux 1:fb4494783863 286
samux 1:fb4494783863 287 break;
samux 1:fb4494783863 288 }
samux 1:fb4494783863 289 }
samux 1:fb4494783863 290 }
samux 1:fb4494783863 291 }
samux 1:fb4494783863 292 DBG("check: %s\r\n", checking.c_str());
samux 1:fb4494783863 293
samux 1:fb4494783863 294 attach_rx(true);
samux 1:fb4494783863 295 return result;
samux 1:fb4494783863 296 }
samux 1:fb4494783863 297
samux 1:fb4494783863 298 //the user wants the result from the command (ACK == NULL, res != NULL)
samux 1:fb4494783863 299 if ( res != NULL) {
samux 1:fb4494783863 300 int i = 0;
samux 1:fb4494783863 301 Timer timeout;
samux 1:fb4494783863 302 timeout.start();
samux 1:fb4494783863 303 tmr.reset();
samux 1:fb4494783863 304 while (1) {
samux 1:fb4494783863 305 if (timeout.read() > 2) {
samux 1:fb4494783863 306 if (i == 0) {
samux 1:fb4494783863 307 res = NULL;
samux 1:fb4494783863 308 break;
samux 1:fb4494783863 309 }
samux 1:fb4494783863 310 res[i] = '\0';
samux 1:fb4494783863 311 DBG("user str 1: %s\r\n", res);
samux 1:fb4494783863 312
samux 1:fb4494783863 313 break;
samux 1:fb4494783863 314 } else {
samux 1:fb4494783863 315 if (tmr.read_ms() > 300) {
samux 1:fb4494783863 316 res[i] = '\0';
samux 1:fb4494783863 317 DBG("user str: %s\r\n", res);
samux 1:fb4494783863 318
samux 1:fb4494783863 319 break;
samux 1:fb4494783863 320 }
michaeljkoster 17:d11fa4c3ac65 321 if (readable()) {
samux 1:fb4494783863 322 tmr.start();
michaeljkoster 17:d11fa4c3ac65 323 read = getc();
samux 1:fb4494783863 324
samux 1:fb4494783863 325 // we drop \r and \n
samux 1:fb4494783863 326 if ( read != '\r' && read != '\n') {
samux 1:fb4494783863 327 res[i++] = read;
samux 1:fb4494783863 328 }
samux 1:fb4494783863 329 }
samux 1:fb4494783863 330 }
samux 1:fb4494783863 331 }
samux 1:fb4494783863 332 DBG("user str: %s\r\n", res);
samux 1:fb4494783863 333 }
samux 1:fb4494783863 334
samux 1:fb4494783863 335 //We flush the buffer
michaeljkoster 17:d11fa4c3ac65 336 while (readable())
michaeljkoster 17:d11fa4c3ac65 337 getc();
samux 1:fb4494783863 338
samux 1:fb4494783863 339 attach_rx(true);
samux 1:fb4494783863 340 DBG("result: %d\r\n", result)
samux 1:fb4494783863 341 return result;
michaeljkoster 15:37a7a56a424f 342 }