WiFi WebServer for ESP8266

Fork of ESP8266_WebServer by Sebastian Schocke

Revision:
0:56c72c87d2f5
Child:
1:1c4333ce7448
diff -r 000000000000 -r 56c72c87d2f5 ESP8266_WebServer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ESP8266_WebServer.cpp	Thu Jan 01 10:11:55 2015 +0000
@@ -0,0 +1,287 @@
+#include "ESP8266_WebServer.h"
+
+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;
+    }
+    if( echoMode ) {
+        debugSerial->putc('@');
+    }
+    *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::Initialize(void) {
+    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();
+    
+    if( debugSerial != NULL ) {
+        debugSerial->printf("Done\r\nSetting operating mode...");
+    }
+    serial->printf("AT+CWMODE=3\r\n");
+    while( data_waiting() == 0 ) {
+        wait_ms(10);
+    }
+    readBuffer();
+    
+    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);
+}
+
+void ESP8266_WebServer::SendReply(int linkID, const char* reply, int replySize, const char* mimeType) {
+    sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length: %d\r\n\r\n", mimeType, replySize);
+    sendResponse(linkID, strlen(response));
+    memcpy(response, reply, replySize);
+    sendResponse(linkID, replySize);
+}
+
+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);
+}
\ No newline at end of file