ESP8266 uart wifi module via AT command

Dependents:   mbed_esp8266_demo

Esp8266.cpp

Committer:
steeven
Date:
2015-05-03
Revision:
0:ee86ca9e494d

File content as of revision 0:ee86ca9e494d:

#include <ESP8266/Esp8266.h>

namespace steeven {

void Esp8266::init() {
    _ch_pd = 1;
    _rst = 1;
    wait_rst();
    cmd_data("AT+GMR"); //get version

}

void Esp8266::wait_rst() {
    cmd_data(NULL, NULL, 0, 10000, "\r\nready\r\n");
}

// 1: client, 2: AP, 3: mixed
void Esp8266::switchClientMode(int mode) {
    int reset = 0;

    //remembered in flash, don't change and restart if not changed.
    if (query_int("AT+CWMODE?") != mode) {
        sprintf(_buf, "AT+CWMODE=%d", mode);
        cmd_data(_buf);
        reset = 1;
    }
    if (query_int("AT+CIPMUX?") != 0) {
        cmd_data("AT+CIPMUX=0", NULL, 0, 3000, "OK\r"); // no multiple connection
        reset = 1;
    }
    if (reset) {
        cmd_data("AT+RST");
        wait_rst();
    }
}

int Esp8266::connect(const char *ap, const char *pswd) {
    char buf[100];
    int n = 0;
    const char *noip = "+CIFSR:STAIP,\"0.0.0.0\"";

    if (strcmp(ap, query("AT+CWJAP?")) != 0) {
        sprintf(buf, "AT+SWJAP=\"%s\",\"%s\"", ap, pswd);
        cmd_data(buf);
    }

    while (cmd_data("AT+CIFSR", buf, sizeof(buf)) && n++ < 10) {
        if (memcmp(buf, noip, strlen(noip)) != 0)
            return 1;
        wait(0.3);
    }
    return 0;
}

int Esp8266::send(const char *host, int port, const char *tx,
        void (*cb)(char *, int)) {
    char buf[100];
    int r;

    ASSERT(cmd_data("AT+CIPMODE=0")); //none-transparent data xfer mode
    //TODO
    cmd_data("AT+CIPCLOSE");
    // AT+CIPSTART="TCP","www.baidu.com",80
    sprintf(buf, "AT+CIPSTART=\"TCP\",\"%s\",%d", host, port);
    ASSERT(cmd_data(buf));
    sprintf(buf, "AT+CIPSEND=%d", strlen(tx));
    // AT+CIPSEND=4
    ASSERT(cmd_data(buf, NULL, 0, 5000, "OK\r\n", NULL));
//      _dbg = 2;
    ASSERT(cmd_data(tx, NULL, 0, 5000, "SEND OK\r\n\r\n", ""));
//      _dbg = 0;
    _rcv_cnt = 0;
    _rcv_exp = 0;
    _rcv_start = 0;
    _rcv_cb = cb;
    _uart.attach(this, &Esp8266::ipd_rx, SerialBase::RxIrq);
    return 1;
}

//Esp8266::~Esp8266() {
//  _uart.close();
//}

//"+IPD,xxx:"
void Esp8266::ipd_dect() {
    int i;
    DBG("testing IPD...\n");
    if (memcmp("+IPD,", _buf, 5) == 0) {
        DBG("IPD found...\n");
        for (i = 5; i < _rcv_cnt; ++i) {
            if (_buf[i] >= '0' && _buf[i] <= '9')
                continue;
            if (_buf[i] == ':') {
                DBG("':' found...\n");
                _buf[i] = 0;
                break;
            }
        }
        if (i == _rcv_cnt) //not found
            return;
        _rcv_exp = atoi(&_buf[5]);
        _rcv_start = i + 1;
        log('[');
        DBG("IPD:%d %d\n", _rcv_start, _rcv_exp);
    } else if (memcmp(_buf, "CLOSED", 5) == 0) {
        DBG("connection closed\n");
        if (_rcv_cb != NULL)
            _rcv_cb(NULL, 0); //end of rcv
        _rcv_cb = NULL;
        //notify receiver
        _uart.attach(NULL, SerialBase::RxIrq);
    }
}

void Esp8266::ipd_rx() {
    char ch;
    int i = 0;
    while (_uart.readable()) {
        ch = _uart.getc();
        log(ch);
        if (_rcv_exp == 0 && (ch == '\r' || ch == '\n')) {
            DBG("ignore leading blank");
            continue;
        }
        _buf[_rcv_cnt++] = ch;
        i++;
        if (_rcv_exp == 0) {
            if (_rcv_cnt > 5 && _rcv_cnt <= 11) { // expecting "+IPD:xxx" or "CLOSED"
                ipd_dect();
            }
            if (_rcv_cnt>11 && _rcv_exp==0) { //failed to detect IPD
                _uart.attach(NULL, SerialBase::RxIrq);
                _buf[_rcv_cnt] = 0;
                LOG("\nFailed to detect IPD: %s", _buf);
                return;
            }
        }
        if (_rcv_cnt >= (int) sizeof(_buf)) {
            error("rx buffer overflow size\n");
        }
        if (_rcv_exp > 0 && _rcv_exp + _rcv_start == _rcv_cnt) { //reach end of pkt
            if (_rcv_cb != NULL)
                _rcv_cb(&_buf[_rcv_start], _rcv_exp); //end of IPD
            _rcv_exp = 0;
            _rcv_cnt = 0;
            _rcv_start = 0;
            log(']');
        }
    }
    DBG(" %d %d\n", i, _rcv_cnt);
}

}   // namespace steeven