Clinton Lee Taylor / Mbed 2 deprecated WiFiLamp

Dependencies:   ESP8266_WebServer mbed

Fork of WiFiLamp by Sebastian Schocke

Committer:
sschocke
Date:
Wed Dec 31 15:15:50 2014 +0000
Revision:
20:f5a6527bfda6
Parent:
18:cdfe5eb7d3ad
Rework of Web Server to handle multiple simultaneous requests

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sschocke 5:42c6f9d916bc 1 #include "ESP8266_WebServer.h"
sschocke 7:f15c81074400 2
sschocke 7:f15c81074400 3 ESP8266_WebServer::ESP8266_WebServer(Serial *espUART) {
sschocke 7:f15c81074400 4 serial = espUART;
sschocke 7:f15c81074400 5 rxptr = buffer;
sschocke 7:f15c81074400 6 debugSerial = NULL;
sschocke 20:f5a6527bfda6 7 reqMode = false;
sschocke 20:f5a6527bfda6 8 reqLen = 0;
sschocke 7:f15c81074400 9 }
sschocke 7:f15c81074400 10
sschocke 7:f15c81074400 11 void ESP8266_WebServer::rxint(void) {
sschocke 7:f15c81074400 12 char c = serial->getc();
sschocke 13:1e8f27da036a 13 if( (c != 0x0A) && (c != 0x0D) && ((c < 0x20) || (c > 0x80)) ) return;
sschocke 20:f5a6527bfda6 14 if( !reqMode && c == '+' ) {
sschocke 20:f5a6527bfda6 15 if( echoMode ) {
sschocke 20:f5a6527bfda6 16 debugSerial->putc('~');
sschocke 20:f5a6527bfda6 17 }
sschocke 20:f5a6527bfda6 18 rxptrStored = rxptr;
sschocke 20:f5a6527bfda6 19 rxptr = reqBuffer;
sschocke 20:f5a6527bfda6 20 reqMode = true;
sschocke 20:f5a6527bfda6 21 }
sschocke 20:f5a6527bfda6 22 if( echoMode ) {
sschocke 7:f15c81074400 23 debugSerial->putc(c);
sschocke 7:f15c81074400 24 }
sschocke 20:f5a6527bfda6 25 if( reqMode && reqLen == 0 && c == ':' ) {
sschocke 20:f5a6527bfda6 26 if( echoMode ) {
sschocke 20:f5a6527bfda6 27 debugSerial->putc('!');
sschocke 20:f5a6527bfda6 28 }
sschocke 20:f5a6527bfda6 29 int numMatched = sscanf(reqBuffer,"+IPD,%*d,%d%n", &reqLen, &ipdLen);
sschocke 20:f5a6527bfda6 30 if( numMatched < 1 ) {
sschocke 20:f5a6527bfda6 31 reqMode = false;
sschocke 20:f5a6527bfda6 32 reqLen = 0;
sschocke 20:f5a6527bfda6 33 rxptr = rxptrStored;
sschocke 20:f5a6527bfda6 34 return;
sschocke 20:f5a6527bfda6 35 }
sschocke 20:f5a6527bfda6 36 reqLen += ipdLen + 1;
sschocke 20:f5a6527bfda6 37 }
sschocke 20:f5a6527bfda6 38 if( echoMode ) {
sschocke 20:f5a6527bfda6 39 debugSerial->putc('@');
sschocke 20:f5a6527bfda6 40 }
sschocke 7:f15c81074400 41 *rxptr = c;
sschocke 7:f15c81074400 42 rxptr++;
sschocke 20:f5a6527bfda6 43 *rxptr = 0;
sschocke 20:f5a6527bfda6 44 if( reqMode && reqLen > 0 ) {
sschocke 20:f5a6527bfda6 45 if( echoMode ) {
sschocke 20:f5a6527bfda6 46 debugSerial->putc('#');
sschocke 20:f5a6527bfda6 47 }
sschocke 20:f5a6527bfda6 48 if( (int)(rxptr - reqBuffer) == reqLen ) {
sschocke 20:f5a6527bfda6 49 // Process it
sschocke 20:f5a6527bfda6 50 queueRequest();
sschocke 20:f5a6527bfda6 51 // Return to normal buffer mode
sschocke 20:f5a6527bfda6 52 reqMode = false;
sschocke 20:f5a6527bfda6 53 reqLen = 0;
sschocke 20:f5a6527bfda6 54 rxptr = rxptrStored;
sschocke 20:f5a6527bfda6 55 }
sschocke 20:f5a6527bfda6 56 }
sschocke 20:f5a6527bfda6 57 }
sschocke 20:f5a6527bfda6 58
sschocke 20:f5a6527bfda6 59 void ESP8266_WebServer::debugBuffers(Serial* target) {
sschocke 20:f5a6527bfda6 60 target->printf("\r\n\r\nRequest Buffer '%s'\r\nReqLen=%d,ReqMode=%d\r\n", reqBuffer, reqLen, reqMode);
sschocke 7:f15c81074400 61 }
sschocke 7:f15c81074400 62
sschocke 7:f15c81074400 63 void ESP8266_WebServer::readBuffer(void) {
sschocke 7:f15c81074400 64 strncpy(reply, buffer, 1024);
sschocke 20:f5a6527bfda6 65 while(reqMode == true ) { wait_ms(10); }
sschocke 20:f5a6527bfda6 66
sschocke 7:f15c81074400 67 rxptr = buffer;
sschocke 7:f15c81074400 68 *rxptr = 0;
sschocke 7:f15c81074400 69 }
sschocke 7:f15c81074400 70
sschocke 7:f15c81074400 71 short ESP8266_WebServer::data_waiting(void)
sschocke 7:f15c81074400 72 {
sschocke 7:f15c81074400 73 char* ok = strstr(buffer, "OK\r\n");
sschocke 7:f15c81074400 74 char* error = strstr(buffer, "ERROR\r\n");
sschocke 7:f15c81074400 75 char* nochange = strstr(buffer, "no change\r\n");
sschocke 7:f15c81074400 76
sschocke 7:f15c81074400 77 if( (ok != NULL) || (error != NULL ) || (nochange != NULL ) )
sschocke 7:f15c81074400 78 {
sschocke 7:f15c81074400 79 return 1;
sschocke 7:f15c81074400 80 }
sschocke 7:f15c81074400 81
sschocke 7:f15c81074400 82 return 0;
sschocke 7:f15c81074400 83 }
sschocke 7:f15c81074400 84
sschocke 7:f15c81074400 85 short ESP8266_WebServer::string_waiting(const char* str)
sschocke 7:f15c81074400 86 {
sschocke 7:f15c81074400 87 char* pr = strstr(buffer, str);
sschocke 7:f15c81074400 88 char* error = strstr(buffer, "ERROR\r\n");
sschocke 7:f15c81074400 89
sschocke 7:f15c81074400 90 if( (pr != NULL) || (error != NULL ) )
sschocke 7:f15c81074400 91 {
sschocke 7:f15c81074400 92 return 1;
sschocke 7:f15c81074400 93 }
sschocke 7:f15c81074400 94
sschocke 7:f15c81074400 95 return 0;
sschocke 7:f15c81074400 96 }
sschocke 5:42c6f9d916bc 97
sschocke 7:f15c81074400 98 void ESP8266_WebServer::Initialize(void) {
sschocke 7:f15c81074400 99 readBuffer();
sschocke 13:1e8f27da036a 100 serial->printf("AT+RST\r\n");
sschocke 13:1e8f27da036a 101 wait_ms(1000);
sschocke 7:f15c81074400 102 while( string_waiting("\r\nready\r\n") == 0 ) {
sschocke 13:1e8f27da036a 103 wait_ms(100);
sschocke 13:1e8f27da036a 104 }
sschocke 13:1e8f27da036a 105 readBuffer();
sschocke 13:1e8f27da036a 106 serial->printf("ATE0\r\n");
sschocke 13:1e8f27da036a 107 while( data_waiting() == 0 ) {
sschocke 7:f15c81074400 108 wait_ms(10);
sschocke 7:f15c81074400 109 }
sschocke 7:f15c81074400 110 readBuffer();
sschocke 7:f15c81074400 111
sschocke 7:f15c81074400 112 if( debugSerial != NULL ) {
sschocke 7:f15c81074400 113 debugSerial->printf("Done\r\nSetting operating mode...");
sschocke 7:f15c81074400 114 }
sschocke 7:f15c81074400 115 serial->printf("AT+CWMODE=3\r\n");
sschocke 7:f15c81074400 116 while( data_waiting() == 0 ) {
sschocke 7:f15c81074400 117 wait_ms(10);
sschocke 7:f15c81074400 118 }
sschocke 7:f15c81074400 119 readBuffer();
sschocke 7:f15c81074400 120
sschocke 7:f15c81074400 121 if( debugSerial != NULL ) {
sschocke 7:f15c81074400 122 debugSerial->printf("Done\r\nAccept Multiple connections...");
sschocke 7:f15c81074400 123 }
sschocke 7:f15c81074400 124 serial->printf("AT+CIPMUX=1\r\n");
sschocke 7:f15c81074400 125 while( data_waiting() == 0 ) {
sschocke 7:f15c81074400 126 wait_ms(10);
sschocke 7:f15c81074400 127 }
sschocke 7:f15c81074400 128 readBuffer();
sschocke 7:f15c81074400 129
sschocke 7:f15c81074400 130 if( debugSerial != NULL ) {
sschocke 7:f15c81074400 131 debugSerial->printf("Done\r\nStarting Web Server...");
sschocke 7:f15c81074400 132 }
sschocke 7:f15c81074400 133
sschocke 7:f15c81074400 134 serial->printf("AT+CIPSERVER=1,80\r\n");
sschocke 7:f15c81074400 135 while( data_waiting() == 0 ) {
sschocke 7:f15c81074400 136 wait_ms(10);
sschocke 7:f15c81074400 137 }
sschocke 7:f15c81074400 138 readBuffer();
sschocke 7:f15c81074400 139 }
sschocke 7:f15c81074400 140
sschocke 20:f5a6527bfda6 141 void ESP8266_WebServer::queueRequest(void) {
sschocke 20:f5a6527bfda6 142 if( strstr(reqBuffer, "HTTP") != NULL ) {
sschocke 20:f5a6527bfda6 143 ESP8266_WebRequest* request = new ESP8266_WebRequest(reqBuffer, debugSerial);
sschocke 20:f5a6527bfda6 144
sschocke 20:f5a6527bfda6 145 incoming.push(request);
sschocke 20:f5a6527bfda6 146 }
sschocke 20:f5a6527bfda6 147 }
sschocke 20:f5a6527bfda6 148
sschocke 9:319aeb6e0123 149 ESP8266_WebRequest* ESP8266_WebServer::GetRequest(void)
sschocke 5:42c6f9d916bc 150 {
sschocke 20:f5a6527bfda6 151 if( incoming.empty() == false ) {
sschocke 20:f5a6527bfda6 152 ESP8266_WebRequest* temp = incoming.front();
sschocke 20:f5a6527bfda6 153 incoming.pop();
sschocke 20:f5a6527bfda6 154 temp->Read();
sschocke 20:f5a6527bfda6 155
sschocke 20:f5a6527bfda6 156 return temp;
sschocke 7:f15c81074400 157 }
sschocke 20:f5a6527bfda6 158
sschocke 9:319aeb6e0123 159 return NULL;
sschocke 7:f15c81074400 160 }
sschocke 7:f15c81074400 161
sschocke 11:3ab606a42227 162 void ESP8266_WebServer::sendResponse(int linkID, int numBytes) {
sschocke 20:f5a6527bfda6 163 bool sent = false;
sschocke 20:f5a6527bfda6 164
sschocke 20:f5a6527bfda6 165 readBuffer();
sschocke 7:f15c81074400 166 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 167 debugSerial->printf("HTTP Reply Packet(%d bytes)\r\n", numBytes);
sschocke 7:f15c81074400 168 }
sschocke 20:f5a6527bfda6 169 while( sent == false ) {
sschocke 20:f5a6527bfda6 170 while( reqMode == true ) { wait_ms(1); }
sschocke 20:f5a6527bfda6 171 serial->printf("AT+CIPSEND=%d,%d\r\n", linkID, numBytes);
sschocke 20:f5a6527bfda6 172 wait_ms(100);
sschocke 20:f5a6527bfda6 173 if( (string_waiting(">") == 1) ) {
sschocke 20:f5a6527bfda6 174 char* error = strstr(buffer, "ERROR\r\n");
sschocke 20:f5a6527bfda6 175 if( error != NULL ) { continue; }
sschocke 20:f5a6527bfda6 176 for( int i=0; i<numBytes; i++ ) {
sschocke 20:f5a6527bfda6 177 serial->putc(response[i]);
sschocke 20:f5a6527bfda6 178 }
sschocke 20:f5a6527bfda6 179 while( string_waiting("\r\nSEND OK\r\n") == 0 ) {
sschocke 20:f5a6527bfda6 180 wait_ms(10);
sschocke 20:f5a6527bfda6 181 }
sschocke 20:f5a6527bfda6 182 error = strstr(buffer, "ERROR\r\n");
sschocke 20:f5a6527bfda6 183 if( error != NULL ) { continue; }
sschocke 20:f5a6527bfda6 184 sent = true;
sschocke 13:1e8f27da036a 185 }
sschocke 7:f15c81074400 186 }
sschocke 20:f5a6527bfda6 187 readBuffer();
sschocke 7:f15c81074400 188 }
sschocke 7:f15c81074400 189
sschocke 11:3ab606a42227 190 void ESP8266_WebServer::SendError(int linkID, std::string error) {
sschocke 11:3ab606a42227 191 SendError(linkID, error.c_str());
sschocke 11:3ab606a42227 192 }
sschocke 11:3ab606a42227 193 void ESP8266_WebServer::SendError(int linkID, const char* error) {
sschocke 11:3ab606a42227 194 sprintf(response, "HTTP/1.1 %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", error, strlen(error), error);
sschocke 11:3ab606a42227 195 sendResponse(linkID, strlen(response));
sschocke 11:3ab606a42227 196 }
sschocke 11:3ab606a42227 197 void ESP8266_WebServer::Send404Error(int linkID) {
sschocke 11:3ab606a42227 198 SendError(linkID, "404 Not Found");
sschocke 7:f15c81074400 199 }
sschocke 7:f15c81074400 200
sschocke 11:3ab606a42227 201 void ESP8266_WebServer::SendReply(int linkID, std::string reply, const char* mimeType) {
sschocke 11:3ab606a42227 202 SendReply(linkID, reply.c_str(), reply.length(), mimeType);
sschocke 11:3ab606a42227 203 }
sschocke 11:3ab606a42227 204
sschocke 11:3ab606a42227 205 void ESP8266_WebServer::SendReply(int linkID, const char* reply, int replySize, const char* mimeType) {
sschocke 14:416fff90cd0f 206 sprintf(response, "HTTP/1.1 200 OK\r\nContent-Type:%s\r\nContent-Length: %d\r\n\r\n", mimeType, replySize);
sschocke 14:416fff90cd0f 207 sendResponse(linkID, strlen(response));
sschocke 15:ad68100221b8 208 memcpy(response, reply, replySize);
sschocke 20:f5a6527bfda6 209 sendResponse(linkID, replySize);
sschocke 7:f15c81074400 210 }
sschocke 9:319aeb6e0123 211
sschocke 20:f5a6527bfda6 212 ESP8266_WebRequest::ESP8266_WebRequest(const char* packet, Serial* debug) {
sschocke 20:f5a6527bfda6 213 int sz = strlen(packet);
sschocke 20:f5a6527bfda6 214 data = (char *)malloc(sz+1);
sschocke 20:f5a6527bfda6 215 memcpy(data, packet, sz+1);
sschocke 20:f5a6527bfda6 216 debugSerial = debug;
sschocke 20:f5a6527bfda6 217 }
sschocke 20:f5a6527bfda6 218
sschocke 20:f5a6527bfda6 219 void ESP8266_WebRequest::Read(void) {
sschocke 20:f5a6527bfda6 220 int bytesRecv, ipdLen, linkID;
sschocke 20:f5a6527bfda6 221 int numMatched = sscanf(data,"+IPD,%d,%d:%n", &linkID, &bytesRecv, &ipdLen);
sschocke 9:319aeb6e0123 222 if( numMatched != 2 ) {
sschocke 9:319aeb6e0123 223 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 224 debugSerial->printf("IPD ERROR : Matched %d, LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", numMatched, linkID, bytesRecv, ipdLen);
sschocke 9:319aeb6e0123 225 }
sschocke 9:319aeb6e0123 226 return;
sschocke 9:319aeb6e0123 227 }
sschocke 20:f5a6527bfda6 228
sschocke 9:319aeb6e0123 229 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 230 debugSerial->printf("IPD Data: LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", linkID, bytesRecv, ipdLen);
sschocke 9:319aeb6e0123 231 }
sschocke 20:f5a6527bfda6 232 if( strstr(data, "HTTP") != NULL ) {
sschocke 20:f5a6527bfda6 233 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 234 debugSerial->printf("Got HTTP Request\r\n");
sschocke 20:f5a6527bfda6 235 }
sschocke 20:f5a6527bfda6 236 char* httpPacket = data + ipdLen;
sschocke 9:319aeb6e0123 237 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 238 debugSerial->printf("HTTP Packet: %s\r\n", httpPacket);
sschocke 20:f5a6527bfda6 239 }
sschocke 20:f5a6527bfda6 240 int numMatched = sscanf(httpPacket, "%s %s HTTP/%*c.%*c", httpMethod, httpURI);
sschocke 20:f5a6527bfda6 241 if( numMatched != 2 ) {
sschocke 20:f5a6527bfda6 242 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 243 debugSerial->printf("HTTP ERROR : Matched %d, Method=%s, URI=%s\r\n", numMatched, httpMethod, httpURI);
sschocke 20:f5a6527bfda6 244 }
sschocke 20:f5a6527bfda6 245 return;
sschocke 9:319aeb6e0123 246 }
sschocke 20:f5a6527bfda6 247
sschocke 20:f5a6527bfda6 248 LinkID = linkID;
sschocke 20:f5a6527bfda6 249 Method = httpMethod;
sschocke 20:f5a6527bfda6 250 URI = httpURI;
sschocke 20:f5a6527bfda6 251 int pos = URI.find('?');
sschocke 20:f5a6527bfda6 252 if(pos != string::npos ) {
sschocke 20:f5a6527bfda6 253 string params = URI.substr(pos+1);
sschocke 20:f5a6527bfda6 254 URI = URI.substr(0,pos);
sschocke 20:f5a6527bfda6 255 pos = params.find('=');
sschocke 20:f5a6527bfda6 256 while( pos != string::npos ) {
sschocke 20:f5a6527bfda6 257 string name = params.substr(0,pos);
sschocke 20:f5a6527bfda6 258 string value = params.substr(pos+1);
sschocke 20:f5a6527bfda6 259 pos = params.find('&');
sschocke 20:f5a6527bfda6 260 if( pos == string::npos )
sschocke 20:f5a6527bfda6 261 {
sschocke 20:f5a6527bfda6 262 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 263 debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str());
sschocke 20:f5a6527bfda6 264 }
sschocke 20:f5a6527bfda6 265 Parameters[name] = value;
sschocke 20:f5a6527bfda6 266 break;
sschocke 20:f5a6527bfda6 267 }
sschocke 20:f5a6527bfda6 268
sschocke 20:f5a6527bfda6 269 value = value.substr(0,value.find('&'));
sschocke 20:f5a6527bfda6 270 params = params.substr(pos+1);
sschocke 20:f5a6527bfda6 271 pos = params.find('=');
sschocke 9:319aeb6e0123 272 if( debugSerial != NULL ) {
sschocke 9:319aeb6e0123 273 debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str());
sschocke 9:319aeb6e0123 274 }
sschocke 9:319aeb6e0123 275 Parameters[name] = value;
sschocke 9:319aeb6e0123 276 }
sschocke 20:f5a6527bfda6 277 }
sschocke 20:f5a6527bfda6 278 if( debugSerial != NULL ) {
sschocke 20:f5a6527bfda6 279 debugSerial->printf("HTTP %s %s\r\n", httpMethod, httpURI);
sschocke 9:319aeb6e0123 280 }
sschocke 9:319aeb6e0123 281 }
sschocke 20:f5a6527bfda6 282 }
sschocke 20:f5a6527bfda6 283
sschocke 20:f5a6527bfda6 284 ESP8266_WebRequest::~ESP8266_WebRequest()
sschocke 20:f5a6527bfda6 285 {
sschocke 20:f5a6527bfda6 286 free(data);
sschocke 9:319aeb6e0123 287 }