ESP8266 uart wifi module via AT command
Diff: Esp8266.h
- Revision:
- 0:ee86ca9e494d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Esp8266.h Sun May 03 14:45:51 2015 +0000 @@ -0,0 +1,328 @@ +#ifndef ESP8266_H_ +#define ESP8266_H_ + +#include "mbed.h" +#include "BufferedSerial/BufferedSerial.h" + +#define WIFI_TIME_OUT 5000 +#define _DBG 1 +#if _DBG==1 +#define DBG(msg...) do{if(_logger && _dbg) _logger->printf(msg);}while(0) +#define LOG(msg...) do{if(_logger) _logger->printf(msg);}while(0) +#else +#define DBG(msg...) +#define LOG(msg...) +#endif +#define ASSERT(eval,msg...) if((r=eval)<=0) { LOG("%s():%d result: %d\n", __FUNCTION__, __LINE__, r); return r;} + +namespace steeven { + +/** Esp8266 WiFi serial module. + * Warnning: + * CH_PD pin has to connect VCC to boot from internal flash! + * Command has to end with "\r\n" + * If you can't get full AT output, set console same baudrate or higher, or set wifi baudrate low!!! + * DO NOT print console if you want get a long result from internet. + * Some bad data at beginning because the baudrate changed to 74880 + * \r: 0xd \n: 0xa + */ +class Esp8266 { + +public: + /** + * + * @param pin LED pin with PWM support + * @param time Time for the brightness transition + * @param hold Time for holding the brightness before next transition. + * Effective for loop mode. + */ + Esp8266(PinName tx, PinName rx, PinName ch_pd, PinName rst, int baudrate = + 115200) : + _ch_pd(ch_pd), _rst(rst), _uart(tx, rx) { + + _uart.baud(baudrate); +// _uart.attach(this, &Esp8266::on_rx, SerialBase::RxIrq); + + _timer.start(); + _timeout_ms = WIFI_TIME_OUT; + + _ch_pd = 0; //uart mode + _rst = 0; //reset + } + + void init(); + + void wait_rst(); + + // 1: client, 2: AP, 3: mixed + void switchClientMode(int mode); + + int connect(const char *ap, const char *pswd); + + int send(const char *host, int port, const char *tx, + void (*cb)(char *, int) = NULL); + + void set_log(BufferedSerial* logger, int dbg) { + _logger = logger; + _dbg = dbg; + } + + void log(char ch) { + if (_logger) { + _logger->putc(ch); + if (_dbg > 1) { + _logger->printf("[%x]", ch); + } + } + } + + void dbg(char ch) { + if (_logger == NULL || _dbg == 0) + return; + _logger->putc(ch); + } + + void dbg(const char *msg) { + if (_logger == NULL || _dbg == 0) + return; + _logger->puts(msg); + } + + void dbg(const char * type, const char *msg) { + if (_logger == NULL || _dbg == 0) + return; + _logger->printf("::wifi:: %s: %s\n", type, msg); + } + + void clear() { + while (_uart.readable()) { + log(_uart.getc()); + } + } + + /* + * query result of a command, command must end with '?' + * >>>AT+CWMODE? + * <<<+CWMODE:3 + * <<<OK + * cmd CWMODE, result is 3. + */ + char* query(const char *cmd) { + int r; + int len = strlen(cmd) - 3; + + r = cmd_data(cmd, _buf, sizeof(_buf)); + if (r < 0) { + dbg("query", "failed"); + return NULL; + } + dbg("query result", _buf); + if (r < len + 2) { // has to be: +CMD:xxx + dbg("query", "invalid result length"); + return NULL; + } + if (memcmp(cmd + 2, _buf, len) != 0) { //check: +CMD + dbg("query", "length not match"); + return NULL; + } + if (_buf[len] != ':') { + dbg("query", "\":\" not found"); + return NULL; + } + return _buf + len + 1; + } + + int query_int(const char *cmd) { + return atoi(query(cmd)); + } + + int query_match(const char *cmd, const char *r) { + return strcmp(query(cmd), r); + } + + /** + * Read data until match or reach max size + * return + * size of data + * -3: timeout + * -1: get error pattern + */ + int read_until(char *buf, int max, const char *p_ok = "OK\r\n", + const char *p_error = "ERROR\r\n") { + int i = 0, i_ok = 0, i_err = 0; + char ch; + + int ok_size = strlen(p_ok); + int err_size = strlen(p_error); + + while (1) { + while (_uart.readable()) { + ch = _uart.getc(); + if (buf) + buf[i] = ch; + log(ch); + i++; + + //check ok pattern + if (p_ok) { + if (p_ok[i_ok] != ch) { + if (i_ok > 0 && _logger && _dbg > 0) + _logger->putc('*'); + i_ok = 0; + } + if (p_ok[i_ok] == ch) { + i_ok++; + if (i_ok > 0) + if (_logger && _dbg > 1) + _logger->putc('_'); + if (i_ok == ok_size) { //found ok pattern + if (buf) + buf[i - ok_size] = 0; + dbg("match", "done\n"); + return i - ok_size; + } + } + } + + //check error pattern + if (p_error) { + if (p_error[i_err] != ch) + i_err = 0; + if (p_error[i_err] == ch) { + i_err++; + if (i_err == err_size) { //match error + if (buf) + buf[i - err_size] = 0; + dbg("match", "error\n"); + return -1; + } + } + } + + if (buf) { + if (i >= max) { + dbg("buffer", "overflow\n"); +// buf[i-1] = 0; + return i; + } + } else { + // Just continue check ok/error + } + } + if (_timer.read_ms() > _timeout_ms) { + dbg("cmd", "timeout\n"); + return -3; + } + } + + } + + int cmd_send(const char* cmd, const char *echo = NULL) { + int r = 0; + + _uart.attach(NULL, SerialBase::RxIrq); + + _uart.puts(cmd); + _uart.puts("\r\n"); + dbg("cmd", "sent"); + + //check echo + if (echo == NULL) + echo = cmd; + + if (echo && strlen(echo) > 0) { + r = read_until(NULL, 0, echo, NULL); + if (r < 0) { + dbg("cmd", "no echo"); + return r; + } + + r = read_until(NULL, 0, "\r\r\n", NULL); + if (r < 0) { + dbg("cmd", "no echo end"); + return r; + } + } + + dbg("cmd", "sent"); + return r; + } + + /** every command has to end with "\r\n" + * + * >>>cmd + * <<<cmd + * <<<data + * <<<OK/ERROR + * <<< + * + * return size of result + * 0: ok + * -1: if error + * -2: if buffer overflow + * -3: timeout + * others: size of content + */ + int cmd_data(const char *cmd, char* ret = NULL, int size = 0, + int timeout_ms = + WIFI_TIME_OUT, const char *end = "OK\r\n", + const char *echo = NULL) { + int r = 0; + + _timer.reset(); + _timeout_ms = timeout_ms; + + dbg("cmd", cmd); + + clear(); + dbg("cmd", "cleared"); + + if (cmd) { + if ((r = cmd_send(cmd, echo)) < 0) { + dbg("cmd", "send failed"); + return r; + } + } + + if (end != NULL) { + /* check OK or ERROR */ + dbg("cmd", "matching end..."); + if ((r = read_until(ret, size, end)) < 0) + dbg("cmd", "check end failed"); + return r; + } + + clear(); + dbg("cmd", "cleared"); + + dbg("cmd", "complete"); + return r; + } + + void ipd_rx(); + +// virtual ~Esp8266(); + + BufferedSerial *_logger; + int _dbg; + +protected: + void ipd_dect(); + + DigitalOut _ch_pd; //ESP8266 CH_PD pin + DigitalOut _rst; //ESP8266 reset pin + Serial _uart; + + char _buf[1600]; + Timer _timer; + int _timeout_ms; + + int _rcv_start; //"+IPD,xxx:" + int _rcv_cnt; // total buffer used + int _rcv_exp; // expected size + void (*_rcv_cb)(char *buf, int len); + +} +; +} +#endif /* ESP8266_H_ */