ESP8266 uart wifi module via AT command

Dependencies:   BufferedSerial

Dependents:   esb_gcc

Fork of ESP8266 by steeven lee

Committer:
ninad
Date:
Tue Nov 15 12:45:37 2016 +0000
Revision:
2:dcd2bd05e1f7
Parent:
1:32714c2fb1a9
-

Who changed what in which revision?

UserRevisionLine numberNew contents of line
steeven 0:ee86ca9e494d 1 #ifndef ESP8266_H_
steeven 0:ee86ca9e494d 2 #define ESP8266_H_
steeven 0:ee86ca9e494d 3
steeven 0:ee86ca9e494d 4 #include "mbed.h"
ninad 1:32714c2fb1a9 5 #include "BufferedSerial.h"
steeven 0:ee86ca9e494d 6
steeven 0:ee86ca9e494d 7 #define WIFI_TIME_OUT 5000
steeven 0:ee86ca9e494d 8 #define _DBG 1
steeven 0:ee86ca9e494d 9 #if _DBG==1
steeven 0:ee86ca9e494d 10 #define DBG(msg...) do{if(_logger && _dbg) _logger->printf(msg);}while(0)
steeven 0:ee86ca9e494d 11 #define LOG(msg...) do{if(_logger) _logger->printf(msg);}while(0)
steeven 0:ee86ca9e494d 12 #else
steeven 0:ee86ca9e494d 13 #define DBG(msg...)
steeven 0:ee86ca9e494d 14 #define LOG(msg...)
steeven 0:ee86ca9e494d 15 #endif
steeven 0:ee86ca9e494d 16 #define ASSERT(eval,msg...) if((r=eval)<=0) { LOG("%s():%d result: %d\n", __FUNCTION__, __LINE__, r); return r;}
steeven 0:ee86ca9e494d 17
steeven 0:ee86ca9e494d 18 namespace steeven {
steeven 0:ee86ca9e494d 19
steeven 0:ee86ca9e494d 20 /** Esp8266 WiFi serial module.
steeven 0:ee86ca9e494d 21 * Warnning:
steeven 0:ee86ca9e494d 22 * CH_PD pin has to connect VCC to boot from internal flash!
steeven 0:ee86ca9e494d 23 * Command has to end with "\r\n"
steeven 0:ee86ca9e494d 24 * If you can't get full AT output, set console same baudrate or higher, or set wifi baudrate low!!!
steeven 0:ee86ca9e494d 25 * DO NOT print console if you want get a long result from internet.
steeven 0:ee86ca9e494d 26 * Some bad data at beginning because the baudrate changed to 74880
steeven 0:ee86ca9e494d 27 * \r: 0xd \n: 0xa
steeven 0:ee86ca9e494d 28 */
steeven 0:ee86ca9e494d 29 class Esp8266 {
steeven 0:ee86ca9e494d 30
steeven 0:ee86ca9e494d 31 public:
steeven 0:ee86ca9e494d 32 /**
steeven 0:ee86ca9e494d 33 *
steeven 0:ee86ca9e494d 34 * @param pin LED pin with PWM support
steeven 0:ee86ca9e494d 35 * @param time Time for the brightness transition
steeven 0:ee86ca9e494d 36 * @param hold Time for holding the brightness before next transition.
steeven 0:ee86ca9e494d 37 * Effective for loop mode.
steeven 0:ee86ca9e494d 38 */
steeven 0:ee86ca9e494d 39 Esp8266(PinName tx, PinName rx, PinName ch_pd, PinName rst, int baudrate =
steeven 0:ee86ca9e494d 40 115200) :
steeven 0:ee86ca9e494d 41 _ch_pd(ch_pd), _rst(rst), _uart(tx, rx) {
steeven 0:ee86ca9e494d 42
steeven 0:ee86ca9e494d 43 _uart.baud(baudrate);
steeven 0:ee86ca9e494d 44 // _uart.attach(this, &Esp8266::on_rx, SerialBase::RxIrq);
steeven 0:ee86ca9e494d 45
steeven 0:ee86ca9e494d 46 _timer.start();
steeven 0:ee86ca9e494d 47 _timeout_ms = WIFI_TIME_OUT;
steeven 0:ee86ca9e494d 48
steeven 0:ee86ca9e494d 49 _ch_pd = 0; //uart mode
steeven 0:ee86ca9e494d 50 _rst = 0; //reset
steeven 0:ee86ca9e494d 51 }
steeven 0:ee86ca9e494d 52
steeven 0:ee86ca9e494d 53 void init();
steeven 0:ee86ca9e494d 54
steeven 0:ee86ca9e494d 55 void wait_rst();
steeven 0:ee86ca9e494d 56
steeven 0:ee86ca9e494d 57 // 1: client, 2: AP, 3: mixed
steeven 0:ee86ca9e494d 58 void switchClientMode(int mode);
steeven 0:ee86ca9e494d 59
steeven 0:ee86ca9e494d 60 int connect(const char *ap, const char *pswd);
steeven 0:ee86ca9e494d 61
steeven 0:ee86ca9e494d 62 int send(const char *host, int port, const char *tx,
steeven 0:ee86ca9e494d 63 void (*cb)(char *, int) = NULL);
steeven 0:ee86ca9e494d 64
steeven 0:ee86ca9e494d 65 void set_log(BufferedSerial* logger, int dbg) {
steeven 0:ee86ca9e494d 66 _logger = logger;
steeven 0:ee86ca9e494d 67 _dbg = dbg;
steeven 0:ee86ca9e494d 68 }
steeven 0:ee86ca9e494d 69
steeven 0:ee86ca9e494d 70 void log(char ch) {
steeven 0:ee86ca9e494d 71 if (_logger) {
steeven 0:ee86ca9e494d 72 _logger->putc(ch);
steeven 0:ee86ca9e494d 73 if (_dbg > 1) {
steeven 0:ee86ca9e494d 74 _logger->printf("[%x]", ch);
steeven 0:ee86ca9e494d 75 }
steeven 0:ee86ca9e494d 76 }
steeven 0:ee86ca9e494d 77 }
steeven 0:ee86ca9e494d 78
steeven 0:ee86ca9e494d 79 void dbg(char ch) {
steeven 0:ee86ca9e494d 80 if (_logger == NULL || _dbg == 0)
steeven 0:ee86ca9e494d 81 return;
steeven 0:ee86ca9e494d 82 _logger->putc(ch);
steeven 0:ee86ca9e494d 83 }
steeven 0:ee86ca9e494d 84
steeven 0:ee86ca9e494d 85 void dbg(const char *msg) {
steeven 0:ee86ca9e494d 86 if (_logger == NULL || _dbg == 0)
steeven 0:ee86ca9e494d 87 return;
steeven 0:ee86ca9e494d 88 _logger->puts(msg);
steeven 0:ee86ca9e494d 89 }
steeven 0:ee86ca9e494d 90
steeven 0:ee86ca9e494d 91 void dbg(const char * type, const char *msg) {
steeven 0:ee86ca9e494d 92 if (_logger == NULL || _dbg == 0)
steeven 0:ee86ca9e494d 93 return;
steeven 0:ee86ca9e494d 94 _logger->printf("::wifi:: %s: %s\n", type, msg);
steeven 0:ee86ca9e494d 95 }
steeven 0:ee86ca9e494d 96
steeven 0:ee86ca9e494d 97 void clear() {
steeven 0:ee86ca9e494d 98 while (_uart.readable()) {
steeven 0:ee86ca9e494d 99 log(_uart.getc());
steeven 0:ee86ca9e494d 100 }
steeven 0:ee86ca9e494d 101 }
steeven 0:ee86ca9e494d 102
steeven 0:ee86ca9e494d 103 /*
steeven 0:ee86ca9e494d 104 * query result of a command, command must end with '?'
steeven 0:ee86ca9e494d 105 * >>>AT+CWMODE?
steeven 0:ee86ca9e494d 106 * <<<+CWMODE:3
steeven 0:ee86ca9e494d 107 * <<<OK
steeven 0:ee86ca9e494d 108 * cmd CWMODE, result is 3.
steeven 0:ee86ca9e494d 109 */
steeven 0:ee86ca9e494d 110 char* query(const char *cmd) {
steeven 0:ee86ca9e494d 111 int r;
steeven 0:ee86ca9e494d 112 int len = strlen(cmd) - 3;
steeven 0:ee86ca9e494d 113
steeven 0:ee86ca9e494d 114 r = cmd_data(cmd, _buf, sizeof(_buf));
steeven 0:ee86ca9e494d 115 if (r < 0) {
steeven 0:ee86ca9e494d 116 dbg("query", "failed");
steeven 0:ee86ca9e494d 117 return NULL;
steeven 0:ee86ca9e494d 118 }
steeven 0:ee86ca9e494d 119 dbg("query result", _buf);
steeven 0:ee86ca9e494d 120 if (r < len + 2) { // has to be: +CMD:xxx
steeven 0:ee86ca9e494d 121 dbg("query", "invalid result length");
steeven 0:ee86ca9e494d 122 return NULL;
steeven 0:ee86ca9e494d 123 }
steeven 0:ee86ca9e494d 124 if (memcmp(cmd + 2, _buf, len) != 0) { //check: +CMD
steeven 0:ee86ca9e494d 125 dbg("query", "length not match");
steeven 0:ee86ca9e494d 126 return NULL;
steeven 0:ee86ca9e494d 127 }
steeven 0:ee86ca9e494d 128 if (_buf[len] != ':') {
steeven 0:ee86ca9e494d 129 dbg("query", "\":\" not found");
steeven 0:ee86ca9e494d 130 return NULL;
steeven 0:ee86ca9e494d 131 }
steeven 0:ee86ca9e494d 132 return _buf + len + 1;
steeven 0:ee86ca9e494d 133 }
steeven 0:ee86ca9e494d 134
steeven 0:ee86ca9e494d 135 int query_int(const char *cmd) {
steeven 0:ee86ca9e494d 136 return atoi(query(cmd));
steeven 0:ee86ca9e494d 137 }
steeven 0:ee86ca9e494d 138
steeven 0:ee86ca9e494d 139 int query_match(const char *cmd, const char *r) {
steeven 0:ee86ca9e494d 140 return strcmp(query(cmd), r);
steeven 0:ee86ca9e494d 141 }
steeven 0:ee86ca9e494d 142
steeven 0:ee86ca9e494d 143 /**
steeven 0:ee86ca9e494d 144 * Read data until match or reach max size
steeven 0:ee86ca9e494d 145 * return
steeven 0:ee86ca9e494d 146 * size of data
steeven 0:ee86ca9e494d 147 * -3: timeout
steeven 0:ee86ca9e494d 148 * -1: get error pattern
steeven 0:ee86ca9e494d 149 */
steeven 0:ee86ca9e494d 150 int read_until(char *buf, int max, const char *p_ok = "OK\r\n",
steeven 0:ee86ca9e494d 151 const char *p_error = "ERROR\r\n") {
steeven 0:ee86ca9e494d 152 int i = 0, i_ok = 0, i_err = 0;
steeven 0:ee86ca9e494d 153 char ch;
steeven 0:ee86ca9e494d 154
steeven 0:ee86ca9e494d 155 int ok_size = strlen(p_ok);
steeven 0:ee86ca9e494d 156 int err_size = strlen(p_error);
steeven 0:ee86ca9e494d 157
steeven 0:ee86ca9e494d 158 while (1) {
steeven 0:ee86ca9e494d 159 while (_uart.readable()) {
steeven 0:ee86ca9e494d 160 ch = _uart.getc();
steeven 0:ee86ca9e494d 161 if (buf)
steeven 0:ee86ca9e494d 162 buf[i] = ch;
steeven 0:ee86ca9e494d 163 log(ch);
steeven 0:ee86ca9e494d 164 i++;
steeven 0:ee86ca9e494d 165
steeven 0:ee86ca9e494d 166 //check ok pattern
steeven 0:ee86ca9e494d 167 if (p_ok) {
steeven 0:ee86ca9e494d 168 if (p_ok[i_ok] != ch) {
steeven 0:ee86ca9e494d 169 if (i_ok > 0 && _logger && _dbg > 0)
steeven 0:ee86ca9e494d 170 _logger->putc('*');
steeven 0:ee86ca9e494d 171 i_ok = 0;
steeven 0:ee86ca9e494d 172 }
steeven 0:ee86ca9e494d 173 if (p_ok[i_ok] == ch) {
steeven 0:ee86ca9e494d 174 i_ok++;
steeven 0:ee86ca9e494d 175 if (i_ok > 0)
steeven 0:ee86ca9e494d 176 if (_logger && _dbg > 1)
steeven 0:ee86ca9e494d 177 _logger->putc('_');
steeven 0:ee86ca9e494d 178 if (i_ok == ok_size) { //found ok pattern
steeven 0:ee86ca9e494d 179 if (buf)
steeven 0:ee86ca9e494d 180 buf[i - ok_size] = 0;
steeven 0:ee86ca9e494d 181 dbg("match", "done\n");
steeven 0:ee86ca9e494d 182 return i - ok_size;
steeven 0:ee86ca9e494d 183 }
steeven 0:ee86ca9e494d 184 }
steeven 0:ee86ca9e494d 185 }
steeven 0:ee86ca9e494d 186
steeven 0:ee86ca9e494d 187 //check error pattern
steeven 0:ee86ca9e494d 188 if (p_error) {
steeven 0:ee86ca9e494d 189 if (p_error[i_err] != ch)
steeven 0:ee86ca9e494d 190 i_err = 0;
steeven 0:ee86ca9e494d 191 if (p_error[i_err] == ch) {
steeven 0:ee86ca9e494d 192 i_err++;
steeven 0:ee86ca9e494d 193 if (i_err == err_size) { //match error
steeven 0:ee86ca9e494d 194 if (buf)
steeven 0:ee86ca9e494d 195 buf[i - err_size] = 0;
steeven 0:ee86ca9e494d 196 dbg("match", "error\n");
steeven 0:ee86ca9e494d 197 return -1;
steeven 0:ee86ca9e494d 198 }
steeven 0:ee86ca9e494d 199 }
steeven 0:ee86ca9e494d 200 }
steeven 0:ee86ca9e494d 201
steeven 0:ee86ca9e494d 202 if (buf) {
steeven 0:ee86ca9e494d 203 if (i >= max) {
steeven 0:ee86ca9e494d 204 dbg("buffer", "overflow\n");
steeven 0:ee86ca9e494d 205 // buf[i-1] = 0;
steeven 0:ee86ca9e494d 206 return i;
steeven 0:ee86ca9e494d 207 }
steeven 0:ee86ca9e494d 208 } else {
steeven 0:ee86ca9e494d 209 // Just continue check ok/error
steeven 0:ee86ca9e494d 210 }
steeven 0:ee86ca9e494d 211 }
steeven 0:ee86ca9e494d 212 if (_timer.read_ms() > _timeout_ms) {
steeven 0:ee86ca9e494d 213 dbg("cmd", "timeout\n");
steeven 0:ee86ca9e494d 214 return -3;
steeven 0:ee86ca9e494d 215 }
steeven 0:ee86ca9e494d 216 }
steeven 0:ee86ca9e494d 217
steeven 0:ee86ca9e494d 218 }
steeven 0:ee86ca9e494d 219
steeven 0:ee86ca9e494d 220 int cmd_send(const char* cmd, const char *echo = NULL) {
steeven 0:ee86ca9e494d 221 int r = 0;
steeven 0:ee86ca9e494d 222
steeven 0:ee86ca9e494d 223 _uart.attach(NULL, SerialBase::RxIrq);
steeven 0:ee86ca9e494d 224
steeven 0:ee86ca9e494d 225 _uart.puts(cmd);
steeven 0:ee86ca9e494d 226 _uart.puts("\r\n");
steeven 0:ee86ca9e494d 227 dbg("cmd", "sent");
steeven 0:ee86ca9e494d 228
steeven 0:ee86ca9e494d 229 //check echo
steeven 0:ee86ca9e494d 230 if (echo == NULL)
steeven 0:ee86ca9e494d 231 echo = cmd;
steeven 0:ee86ca9e494d 232
steeven 0:ee86ca9e494d 233 if (echo && strlen(echo) > 0) {
steeven 0:ee86ca9e494d 234 r = read_until(NULL, 0, echo, NULL);
steeven 0:ee86ca9e494d 235 if (r < 0) {
steeven 0:ee86ca9e494d 236 dbg("cmd", "no echo");
steeven 0:ee86ca9e494d 237 return r;
steeven 0:ee86ca9e494d 238 }
steeven 0:ee86ca9e494d 239
steeven 0:ee86ca9e494d 240 r = read_until(NULL, 0, "\r\r\n", NULL);
steeven 0:ee86ca9e494d 241 if (r < 0) {
steeven 0:ee86ca9e494d 242 dbg("cmd", "no echo end");
steeven 0:ee86ca9e494d 243 return r;
steeven 0:ee86ca9e494d 244 }
steeven 0:ee86ca9e494d 245 }
steeven 0:ee86ca9e494d 246
steeven 0:ee86ca9e494d 247 dbg("cmd", "sent");
steeven 0:ee86ca9e494d 248 return r;
steeven 0:ee86ca9e494d 249 }
steeven 0:ee86ca9e494d 250
steeven 0:ee86ca9e494d 251 /** every command has to end with "\r\n"
steeven 0:ee86ca9e494d 252 *
steeven 0:ee86ca9e494d 253 * >>>cmd
steeven 0:ee86ca9e494d 254 * <<<cmd
steeven 0:ee86ca9e494d 255 * <<<data
steeven 0:ee86ca9e494d 256 * <<<OK/ERROR
steeven 0:ee86ca9e494d 257 * <<<
steeven 0:ee86ca9e494d 258 *
steeven 0:ee86ca9e494d 259 * return size of result
steeven 0:ee86ca9e494d 260 * 0: ok
steeven 0:ee86ca9e494d 261 * -1: if error
steeven 0:ee86ca9e494d 262 * -2: if buffer overflow
steeven 0:ee86ca9e494d 263 * -3: timeout
steeven 0:ee86ca9e494d 264 * others: size of content
steeven 0:ee86ca9e494d 265 */
steeven 0:ee86ca9e494d 266 int cmd_data(const char *cmd, char* ret = NULL, int size = 0,
steeven 0:ee86ca9e494d 267 int timeout_ms =
steeven 0:ee86ca9e494d 268 WIFI_TIME_OUT, const char *end = "OK\r\n",
steeven 0:ee86ca9e494d 269 const char *echo = NULL) {
steeven 0:ee86ca9e494d 270 int r = 0;
steeven 0:ee86ca9e494d 271
steeven 0:ee86ca9e494d 272 _timer.reset();
steeven 0:ee86ca9e494d 273 _timeout_ms = timeout_ms;
steeven 0:ee86ca9e494d 274
steeven 0:ee86ca9e494d 275 dbg("cmd", cmd);
steeven 0:ee86ca9e494d 276
steeven 0:ee86ca9e494d 277 clear();
steeven 0:ee86ca9e494d 278 dbg("cmd", "cleared");
steeven 0:ee86ca9e494d 279
steeven 0:ee86ca9e494d 280 if (cmd) {
steeven 0:ee86ca9e494d 281 if ((r = cmd_send(cmd, echo)) < 0) {
steeven 0:ee86ca9e494d 282 dbg("cmd", "send failed");
steeven 0:ee86ca9e494d 283 return r;
steeven 0:ee86ca9e494d 284 }
steeven 0:ee86ca9e494d 285 }
steeven 0:ee86ca9e494d 286
steeven 0:ee86ca9e494d 287 if (end != NULL) {
steeven 0:ee86ca9e494d 288 /* check OK or ERROR */
steeven 0:ee86ca9e494d 289 dbg("cmd", "matching end...");
steeven 0:ee86ca9e494d 290 if ((r = read_until(ret, size, end)) < 0)
steeven 0:ee86ca9e494d 291 dbg("cmd", "check end failed");
steeven 0:ee86ca9e494d 292 return r;
steeven 0:ee86ca9e494d 293 }
steeven 0:ee86ca9e494d 294
steeven 0:ee86ca9e494d 295 clear();
steeven 0:ee86ca9e494d 296 dbg("cmd", "cleared");
steeven 0:ee86ca9e494d 297
steeven 0:ee86ca9e494d 298 dbg("cmd", "complete");
steeven 0:ee86ca9e494d 299 return r;
steeven 0:ee86ca9e494d 300 }
steeven 0:ee86ca9e494d 301
steeven 0:ee86ca9e494d 302 void ipd_rx();
steeven 0:ee86ca9e494d 303
steeven 0:ee86ca9e494d 304 // virtual ~Esp8266();
steeven 0:ee86ca9e494d 305
steeven 0:ee86ca9e494d 306 BufferedSerial *_logger;
steeven 0:ee86ca9e494d 307 int _dbg;
steeven 0:ee86ca9e494d 308
steeven 0:ee86ca9e494d 309 protected:
steeven 0:ee86ca9e494d 310 void ipd_dect();
steeven 0:ee86ca9e494d 311
steeven 0:ee86ca9e494d 312 DigitalOut _ch_pd; //ESP8266 CH_PD pin
steeven 0:ee86ca9e494d 313 DigitalOut _rst; //ESP8266 reset pin
steeven 0:ee86ca9e494d 314 Serial _uart;
steeven 0:ee86ca9e494d 315
steeven 0:ee86ca9e494d 316 char _buf[1600];
steeven 0:ee86ca9e494d 317 Timer _timer;
steeven 0:ee86ca9e494d 318 int _timeout_ms;
steeven 0:ee86ca9e494d 319
steeven 0:ee86ca9e494d 320 int _rcv_start; //"+IPD,xxx:"
steeven 0:ee86ca9e494d 321 int _rcv_cnt; // total buffer used
steeven 0:ee86ca9e494d 322 int _rcv_exp; // expected size
steeven 0:ee86ca9e494d 323 void (*_rcv_cb)(char *buf, int len);
steeven 0:ee86ca9e494d 324
steeven 0:ee86ca9e494d 325 }
steeven 0:ee86ca9e494d 326 ;
steeven 0:ee86ca9e494d 327 }
steeven 0:ee86ca9e494d 328 #endif /* ESP8266_H_ */