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.
Fork of ESP8266_WebServer by
ESP8266_WebServer.cpp
- Committer:
- sschocke
- Date:
- 2015-01-05
- Revision:
- 7:f6172ba3e807
- Parent:
- 6:34d93ea4d519
- Child:
- 8:5573f6f70a82
File content as of revision 7:f6172ba3e807:
#include "ESP8266_WebServer.h"
const char* opModes[] = {"ERROR", "Station", "SoftAP", "Station+SoftAP"};
ESP8266_WebServer::ESP8266_WebServer(Serial *espUART) {
    serial = espUART;
    rxptr = buffer;
    debugSerial = NULL;
    reqMode = false;
    reqLen = 0;
}
void ESP8266_WebServer::rxint(void) {
    char c = serial->getc();
    if( (c != 0x0A) && (c != 0x0D) && ((c < 0x20) || (c > 0x80)) ) return;
    if( !reqMode && c == '+' ) {
        if( echoMode ) {
            debugSerial->putc('~');
        }
        rxptrStored = rxptr;
        rxptr = reqBuffer;
        reqMode = true;
    }
    if( echoMode ) {
        debugSerial->putc(c);
    }
    if( reqMode && reqLen == 0 && c == ':' ) {
        if( echoMode ) {
            debugSerial->putc('!');
        }
        int numMatched = sscanf(reqBuffer,"+IPD,%*d,%d%n", &reqLen, &ipdLen);
        if( numMatched < 1 ) {
            reqMode = false;
            reqLen = 0;
            rxptr = rxptrStored;
            return;
        }
        reqLen += ipdLen + 1;
    }
    *rxptr = c;
    rxptr++;
    *rxptr = 0;
    if( reqMode && reqLen > 0 ) {
        if( echoMode ) {
            debugSerial->putc('#');
        }
        if( (int)(rxptr - reqBuffer) == reqLen ) {
            // Process it
            queueRequest();
            // Return to normal buffer mode
            reqMode = false;
            reqLen = 0;
            rxptr = rxptrStored;
        }
    }
}
void ESP8266_WebServer::debugBuffers(Serial* target) {
    target->printf("\r\n\r\nRequest Buffer '%s'\r\nReqLen=%d,ReqMode=%d\r\n", reqBuffer, reqLen, reqMode);    
}
void ESP8266_WebServer::readBuffer(void) {
    strncpy(reply, buffer, 1024);
    while(reqMode == true ) { wait_ms(10); }
    
    rxptr = buffer;
    *rxptr = 0;
}
short ESP8266_WebServer::data_waiting(void)
{
    char* ok = strstr(buffer, "OK\r\n");
    char* error = strstr(buffer, "ERROR\r\n");
    char* nochange = strstr(buffer, "no change\r\n");
    
    if( (ok != NULL) || (error != NULL ) || (nochange != NULL ) )
    {
        return 1;
    }
    return 0;
}
short ESP8266_WebServer::string_waiting(const char* str)
{
    char* pr = strstr(buffer, str);
    char* error = strstr(buffer, "ERROR\r\n");
    
    if( (pr != NULL) || (error != NULL ) )
    {
        return 1;
    }
    return 0;
}
void ESP8266_WebServer::ResetModule(void) {
    readBuffer();
    serial->printf("ATE0\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    
    readBuffer();
    serial->printf("AT+RST\r\n");
    wait_ms(1000);
    while( string_waiting("\r\nready\r\n") == 0 ) {
        wait_ms(100);
    }
    
    readBuffer();
    serial->printf("ATE0\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
}    
    
void ESP8266_WebServer::Initialize(void) {
    if( debugSerial != NULL ) {
        debugSerial->printf("Done\r\nAccept Multiple connections...");
    }
    serial->printf("AT+CIPMUX=1\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    
    if( debugSerial != NULL ) {
        debugSerial->printf("Done\r\nStarting Web Server...");
    }
    
    serial->printf("AT+CIPSERVER=1,80\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
}
void ESP8266_WebServer::queueRequest(void) {
    if( strstr(reqBuffer, "HTTP") != NULL ) {
        ESP8266_WebRequest* request = new ESP8266_WebRequest(reqBuffer, debugSerial); 
        
        incoming.push(request);
    }
}
ESP8266_WebRequest* ESP8266_WebServer::GetRequest(void)
{
    if( incoming.empty() == false ) {
        ESP8266_WebRequest* temp = incoming.front();
        incoming.pop();
        temp->Read();
        
        return temp;
    }
        
    return NULL;
}
void ESP8266_WebServer::sendResponse(int linkID, int numBytes) {
    bool sent = false;
    
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("HTTP Reply Packet(%d bytes)\r\n", numBytes);
    }
    while( sent == false ) {
        while( reqMode == true ) { wait_ms(1); }
        serial->printf("AT+CIPSEND=%d,%d\r\n", linkID, numBytes);
        wait_ms(100);
        if( (string_waiting(">") == 1) ) {
            char* error = strstr(buffer, "ERROR\r\n");
            if( error != NULL ) { continue; }
            for( int i=0; i<numBytes; i++ ) {
                serial->putc(response[i]);
            }
            while( string_waiting("\r\nSEND OK\r\n") == 0 ) {
                wait_ms(10);
            }
            error = strstr(buffer, "ERROR\r\n");
            if( error != NULL ) { continue; }
            sent = true;
        }
    }
    readBuffer();
}
void ESP8266_WebServer::SendError(int linkID, std::string error) {
    SendError(linkID, error.c_str());
}
void ESP8266_WebServer::SendError(int linkID, const char* error) {
    sprintf(response, "HTTP/1.1 %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", error, strlen(error), error);
    sendResponse(linkID, strlen(response));
}
void ESP8266_WebServer::Send404Error(int linkID) {
    SendError(linkID, "404 Not Found");
}
void ESP8266_WebServer::SendReply(int linkID, std::string reply, const char* mimeType) {
    SendReply(linkID, reply.c_str(), reply.length(), mimeType, 60);
}
void ESP8266_WebServer::SendReply(int linkID, std::string reply, const char* mimeType, int maxAge) {
    SendReply(linkID, reply.c_str(), reply.length(), mimeType, maxAge);
}
void ESP8266_WebServer::SendReply(int linkID, char const* reply, int replySize, const char* mimeType) {
    SendReply(linkID, reply, replySize, mimeType, 600);
}
void ESP8266_WebServer::SendReply(int linkID, char const* reply, const char* mimeType, int maxAge) {
    SendReply(linkID, reply, strlen(reply), mimeType, maxAge);
}
void ESP8266_WebServer::SendReply(int linkID, char const* reply, int replySize, const char* mimeType, int maxAge) {
    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length: %d\r\nCache-Control:max-age=%d\r\n\r\n", mimeType, replySize, maxAge);
    sendResponse(linkID, strlen(response));
    char const* sendPtr = reply;
    int bytesSent = 0;
    while( bytesSent < replySize ) {
        int bytesToSend = replySize - bytesSent;
        if( bytesToSend > sizeof(response) ) {
            bytesToSend = sizeof(response);
        }
        
        memcpy(response, sendPtr, bytesToSend);
        sendResponse(linkID, bytesToSend);
        sendPtr += bytesToSend;
        bytesSent += bytesToSend;
    }
}
void ESP8266_WebServer::SendFile(int linkID, FileHandle* file, const char* mimeType) {
    SendFile(linkID, file, mimeType, 86400);
}
void ESP8266_WebServer::SendFile(int linkID, FileHandle* file, const char* mimeType, int maxAge) {
    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length: %d\r\nCache-Control:max-age=%d\r\n\r\n", mimeType, file->flen(), maxAge);
    sendResponse(linkID, strlen(response));
    int numBytes = file->read(response, sizeof(response));
    while( numBytes > 0) {
        sendResponse(linkID, numBytes);
        numBytes = file->read(response, sizeof(response));
    }
}
int ESP8266_WebServer::SendStream(int linkID, char const* reply, int StreamSize,  int WindowSize, const char* mimeType, int maxAge) {
    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length: %d\r\nCache-Control:max-age=%d\r\n\r\n", mimeType, StreamSize, maxAge);
    sendResponse(linkID, strlen(response));
    return SendStream(linkID, reply, WindowSize);
}
std::string ESP8266_WebServer::GetStationMAC(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CIPSTAMAC?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Station MAC Reply: %s\r\n", reply);
    }
    
    std::string mac = std::string(reply);
    mac = mac.substr(1, 17);
    
    return mac;
}
std::string ESP8266_WebServer::GetAPMAC(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CIPAPMAC?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("SoftAP MAC Reply: %s\r\n", reply);
    }
    
    std::string mac = std::string(reply);
    mac = mac.substr(1, 17);
    
    return mac;
}
std::string ESP8266_WebServer::GetStationIP(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CIPSTA?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Station IP Reply: %s\r\n", reply);
    }
    
    std::string ip = std::string(reply);
    ip = ip.substr(1, ip.find('"', 1) - 1);
    
    return ip;
}
std::string ESP8266_WebServer::GetAPIP(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CIPAP?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("SoftAP IP Reply: %s\r\n", reply);
    }
    
    std::string ip = std::string(reply);
    ip = ip.substr(1, ip.find('"', 1) - 1);
    
    return ip;
}
int ESP8266_WebServer::GetOperatingMode(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CWMODE?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Operating Mode Reply: %s\r\n", reply);
    }
    
    return atoi(reply);
}
std::string ESP8266_WebServer::GetStationSSID(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CWJAP?\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Station SSID Reply: %s\r\n", reply);
    }
    
    std::string ssid = std::string(reply);
    if( strstr(reply, "No AP\r\n") != NULL ) { return "(None)"; }
    ssid = ssid.substr(1, ssid.find('"', 1) - 1);
    
    return ssid;
}
std::list<std::string> ESP8266_WebServer::ListAvailableSSID(void) {
    std::list<std::string> apList;
    
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CWLAP\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("SSID List Reply: %s\r\n", reply);
    }
    
    char ssid[65];
    char apmac[20];
    int ecn;
    int rssi;
    int tokenLength;
    char* token = strstr(reply, "(");
    while( token != NULL ) {
        int numMatched = sscanf(token, "(%d,\"%[^\"]\",%d,\"%[0123456789abcdef:]\",%*d)\r\n%n", &ecn, ssid, &rssi, apmac, &tokenLength);
        if( numMatched < 4 ) {
            if( debugSerial != NULL ) {
                debugSerial->printf("SSID List Token Error: NumMatched=%d, SSID=%s\r\n", numMatched, ssid);
            }
            return apList;
        }
        if( debugSerial != NULL ) {
            debugSerial->printf("SSID List Token : SSID=%s, ECN=%d, RSSI=%d, APMAC=%s, TokenLength=%d\r\n", ssid, ecn, rssi, apmac, tokenLength);
        }
        apList.push_back(std::string(ssid));
        token += tokenLength;
        token = strstr(token, "(");
    }
    
    return apList;
}
std::string ESP8266_WebServer::GetFirmwareVersion(void) {
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+GMR\r\n");
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Firmware Version Reply: %s\r\n", reply);
    }
    
    std::string ver = std::string(reply);
    ver = ver.substr(0, ver.find('\r'));
    
    return ver;
}
int ESP8266_WebServer::SendStream(int linkID, char const* reply, int WindowSize) {
    char const* sendPtr = reply;
    int bytesSent = 0;
    while( bytesSent < WindowSize ) {
        int bytesToSend = WindowSize - bytesSent;
        if( bytesToSend > sizeof(response) ) {
            bytesToSend = sizeof(response);
        }
        
        memcpy(response, sendPtr, bytesToSend);
        sendResponse(linkID, bytesToSend);
        sendPtr += bytesToSend;
        bytesSent += bytesToSend;
    }
    
    return bytesSent;
}
bool ESP8266_WebServer::SetOperatingMode(int mode) {
    if( debugSerial != NULL ) {
        debugSerial->printf("Set Operating Mode to %s(%d)\r\n", opModes[mode], mode);
    }
    
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CWMODE=%d\r\n", mode);
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Set Operating Mode Reply: %s\r\n", reply);
    }
    if( strstr(reply, "\r\nOK\r\n") != NULL ) { return true; }
    return false;
}
bool ESP8266_WebServer::SetStationSSID(std::string newAP, std::string password) {
    if( debugSerial != NULL ) {
        debugSerial->printf("Set Station SSID to %s, Password=%s\r\n", newAP.c_str(), password.c_str());
    }
    while( reqMode == true ) { wait_ms(1); }
    readBuffer();
    serial->printf("AT+CWJAP=\"%s\",\"%s\"\r\n", newAP.c_str(), password.c_str());
    while( data_waiting() == 0 ) {
        wait_ms(10);
    }
    readBuffer();
    if( debugSerial != NULL ) {
        debugSerial->printf("Set Station SSID Reply: %s\r\n", reply);
    }
    if( strstr(reply, "\r\nOK\r\n") != NULL ) { return true; }
    
    return false;
}
ESP8266_WebRequest::ESP8266_WebRequest(const char* packet, Serial* debug) {
    int sz = strlen(packet);
    data = (char *)malloc(sz+1);
    memcpy(data, packet, sz+1);
    debugSerial = debug;
}
void ESP8266_WebRequest::Read(void) {
    int bytesRecv, ipdLen, linkID;
    int numMatched = sscanf(data,"+IPD,%d,%d:%n", &linkID, &bytesRecv, &ipdLen);
    if( numMatched != 2 ) {
        if( debugSerial != NULL ) {
            debugSerial->printf("IPD ERROR : Matched %d, LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", numMatched, linkID, bytesRecv, ipdLen);
        }
        return;
    }
    if( debugSerial != NULL ) {
        debugSerial->printf("IPD Data: LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", linkID, bytesRecv, ipdLen);
    }
    if( strstr(data, "HTTP") != NULL ) {
        if( debugSerial != NULL ) {
            debugSerial->printf("Got HTTP Request\r\n");
        }
        char* httpPacket = data + ipdLen;
        if( debugSerial != NULL ) {
            debugSerial->printf("HTTP Packet: %s\r\n", httpPacket);
        }
        int numMatched = sscanf(httpPacket, "%s %s HTTP/%*c.%*c", httpMethod, httpURI);
        if( numMatched != 2 ) {
            if( debugSerial != NULL ) {
                debugSerial->printf("HTTP ERROR : Matched %d, Method=%s, URI=%s\r\n", numMatched, httpMethod, httpURI);
            }
            return;
        }
        
        LinkID = linkID;
        Method = httpMethod;
        URI = httpURI;
        int pos = URI.find('?');
        if(pos != string::npos ) {
            string params = URI.substr(pos+1);
            URI = URI.substr(0,pos);
            pos = params.find('=');
            while( pos != string::npos ) {
                string name = params.substr(0,pos);
                string value = params.substr(pos+1);
                pos = params.find('&');
                if( pos == string::npos )
                {
                    if( debugSerial != NULL ) {
                        debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str());
                    }
                    Parameters[name] = value;
                    break;
                }
                
                value = value.substr(0,value.find('&'));
                params = params.substr(pos+1);
                pos = params.find('=');
                if( debugSerial != NULL ) {
                    debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str());
                }
                Parameters[name] = value;
            }
        }
        if( debugSerial != NULL ) {
            debugSerial->printf("HTTP %s %s\r\n", httpMethod, httpURI);
        }
    }
}
ESP8266_WebRequest::~ESP8266_WebRequest()
{
    free(data);
}
            
    