ESP8266 WiFi Module Web Server library
ESP8266_WebServer.cpp
- Committer:
- sschocke
- Date:
- 2015-01-06
- Revision:
- 8:5573f6f70a82
- Parent:
- 7:f6172ba3e807
File content as of revision 8:5573f6f70a82:
#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, sizeof(buffer)); 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) { if( string_waiting("\r\nready\r\n") == 0 ) { readBuffer(); serial->printf("ATE0\r\n"); wait_ms(1000); if( string_waiting("\r\nready\r\n") == 0 ) { 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); if( debugSerial != NULL ) { debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); } 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); if( debugSerial != NULL ) { debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); } 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); if( debugSerial != NULL ) { debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); } 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); } char* httpMethod = (char*)malloc(16); char* httpURI = (char*)malloc(256); 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); } free(httpMethod); free(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); } free(httpMethod); free(httpURI); } } ESP8266_WebRequest::~ESP8266_WebRequest() { free(data); }