ESP8266 WiFi Module Web Server library
Embed:
(wiki syntax)
Show/hide line numbers
ESP8266_WebServer.cpp
00001 #include "ESP8266_WebServer.h" 00002 00003 const char* opModes[] = {"ERROR", "Station", "SoftAP", "Station+SoftAP"}; 00004 00005 ESP8266_WebServer::ESP8266_WebServer(Serial *espUART) { 00006 serial = espUART; 00007 rxptr = buffer; 00008 debugSerial = NULL; 00009 reqMode = false; 00010 reqLen = 0; 00011 } 00012 00013 void ESP8266_WebServer::rxint(void) { 00014 char c = serial->getc(); 00015 if( (c != 0x0A) && (c != 0x0D) && ((c < 0x20) || (c > 0x80)) ) return; 00016 if( !reqMode && c == '+' ) { 00017 if( echoMode ) { 00018 debugSerial->putc('~'); 00019 } 00020 rxptrStored = rxptr; 00021 rxptr = reqBuffer; 00022 reqMode = true; 00023 } 00024 if( echoMode ) { 00025 debugSerial->putc(c); 00026 } 00027 if( reqMode && reqLen == 0 && c == ':' ) { 00028 if( echoMode ) { 00029 debugSerial->putc('!'); 00030 } 00031 int numMatched = sscanf(reqBuffer,"+IPD,%*d,%d%n", &reqLen, &ipdLen); 00032 if( numMatched < 1 ) { 00033 reqMode = false; 00034 reqLen = 0; 00035 rxptr = rxptrStored; 00036 return; 00037 } 00038 reqLen += ipdLen + 1; 00039 } 00040 *rxptr = c; 00041 rxptr++; 00042 *rxptr = 0; 00043 if( reqMode && reqLen > 0 ) { 00044 if( echoMode ) { 00045 debugSerial->putc('#'); 00046 } 00047 if( (int)(rxptr - reqBuffer) == reqLen ) { 00048 // Process it 00049 queueRequest(); 00050 // Return to normal buffer mode 00051 reqMode = false; 00052 reqLen = 0; 00053 rxptr = rxptrStored; 00054 } 00055 } 00056 } 00057 00058 void ESP8266_WebServer::debugBuffers(Serial* target) { 00059 target->printf("\r\n\r\nRequest Buffer '%s'\r\nReqLen=%d,ReqMode=%d\r\n", reqBuffer, reqLen, reqMode); 00060 } 00061 00062 void ESP8266_WebServer::readBuffer(void) { 00063 strncpy(reply, buffer, sizeof(buffer)); 00064 while(reqMode == true ) { wait_ms(10); } 00065 00066 rxptr = buffer; 00067 *rxptr = 0; 00068 } 00069 00070 short ESP8266_WebServer::data_waiting(void) 00071 { 00072 char* ok = strstr(buffer, "OK\r\n"); 00073 char* error = strstr(buffer, "ERROR\r\n"); 00074 char* nochange = strstr(buffer, "no change\r\n"); 00075 00076 if( (ok != NULL) || (error != NULL ) || (nochange != NULL ) ) 00077 { 00078 return 1; 00079 } 00080 00081 return 0; 00082 } 00083 00084 short ESP8266_WebServer::string_waiting(const char* str) 00085 { 00086 char* pr = strstr(buffer, str); 00087 char* error = strstr(buffer, "ERROR\r\n"); 00088 00089 if( (pr != NULL) || (error != NULL ) ) 00090 { 00091 return 1; 00092 } 00093 00094 return 0; 00095 } 00096 00097 void ESP8266_WebServer::ResetModule(void) { 00098 if( string_waiting("\r\nready\r\n") == 0 ) { 00099 readBuffer(); 00100 serial->printf("ATE0\r\n"); 00101 wait_ms(1000); 00102 00103 if( string_waiting("\r\nready\r\n") == 0 ) { 00104 readBuffer(); 00105 serial->printf("AT+RST\r\n"); 00106 wait_ms(1000); 00107 while( string_waiting("\r\nready\r\n") == 0 ) { 00108 wait_ms(100); 00109 } 00110 } 00111 } 00112 00113 readBuffer(); 00114 serial->printf("ATE0\r\n"); 00115 while( data_waiting() == 0 ) { 00116 wait_ms(10); 00117 } 00118 readBuffer(); 00119 } 00120 00121 void ESP8266_WebServer::Initialize(void) { 00122 if( debugSerial != NULL ) { 00123 debugSerial->printf("Done\r\nAccept Multiple connections..."); 00124 } 00125 serial->printf("AT+CIPMUX=1\r\n"); 00126 while( data_waiting() == 0 ) { 00127 wait_ms(10); 00128 } 00129 readBuffer(); 00130 00131 if( debugSerial != NULL ) { 00132 debugSerial->printf("Done\r\nStarting Web Server..."); 00133 } 00134 00135 serial->printf("AT+CIPSERVER=1,80\r\n"); 00136 while( data_waiting() == 0 ) { 00137 wait_ms(10); 00138 } 00139 readBuffer(); 00140 } 00141 00142 void ESP8266_WebServer::queueRequest(void) { 00143 if( strstr(reqBuffer, "HTTP") != NULL ) { 00144 ESP8266_WebRequest* request = new ESP8266_WebRequest(reqBuffer, debugSerial); 00145 00146 incoming.push(request); 00147 } 00148 } 00149 00150 ESP8266_WebRequest* ESP8266_WebServer::GetRequest(void) 00151 { 00152 if( incoming.empty() == false ) { 00153 ESP8266_WebRequest* temp = incoming.front(); 00154 incoming.pop(); 00155 temp->Read(); 00156 00157 return temp; 00158 } 00159 00160 return NULL; 00161 } 00162 00163 void ESP8266_WebServer::sendResponse(int linkID, int numBytes) { 00164 bool sent = false; 00165 00166 readBuffer(); 00167 if( debugSerial != NULL ) { 00168 debugSerial->printf("HTTP Reply Packet(%d bytes)\r\n", numBytes); 00169 } 00170 while( sent == false ) { 00171 while( reqMode == true ) { wait_ms(1); } 00172 serial->printf("AT+CIPSEND=%d,%d\r\n", linkID, numBytes); 00173 wait_ms(100); 00174 if( (string_waiting(">") == 1) ) { 00175 char* error = strstr(buffer, "ERROR\r\n"); 00176 if( error != NULL ) { continue; } 00177 for( int i=0; i<numBytes; i++ ) { 00178 serial->putc(response[i]); 00179 } 00180 while( string_waiting("\r\nSEND OK\r\n") == 0 ) { 00181 wait_ms(10); 00182 } 00183 error = strstr(buffer, "ERROR\r\n"); 00184 if( error != NULL ) { continue; } 00185 sent = true; 00186 } 00187 } 00188 readBuffer(); 00189 } 00190 00191 void ESP8266_WebServer::SendError(int linkID, std::string error) { 00192 SendError(linkID, error.c_str()); 00193 } 00194 void ESP8266_WebServer::SendError(int linkID, const char* error) { 00195 sprintf(response, "HTTP/1.1 %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", error, strlen(error), error); 00196 sendResponse(linkID, strlen(response)); 00197 } 00198 void ESP8266_WebServer::Send404Error(int linkID) { 00199 SendError(linkID, "404 Not Found"); 00200 } 00201 00202 void ESP8266_WebServer::SendReply(int linkID, std::string reply, const char* mimeType) { 00203 SendReply(linkID, reply.c_str(), reply.length(), mimeType, 60); 00204 } 00205 void ESP8266_WebServer::SendReply(int linkID, std::string reply, const char* mimeType, int maxAge) { 00206 SendReply(linkID, reply.c_str(), reply.length(), mimeType, maxAge); 00207 } 00208 00209 void ESP8266_WebServer::SendReply(int linkID, char const* reply, int replySize, const char* mimeType) { 00210 SendReply(linkID, reply, replySize, mimeType, 600); 00211 } 00212 void ESP8266_WebServer::SendReply(int linkID, char const* reply, const char* mimeType, int maxAge) { 00213 SendReply(linkID, reply, strlen(reply), mimeType, maxAge); 00214 } 00215 void ESP8266_WebServer::SendReply(int linkID, char const* reply, int replySize, const char* mimeType, int maxAge) { 00216 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); 00217 if( debugSerial != NULL ) { 00218 debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); 00219 } 00220 sendResponse(linkID, strlen(response)); 00221 char const* sendPtr = reply; 00222 int bytesSent = 0; 00223 while( bytesSent < replySize ) { 00224 int bytesToSend = replySize - bytesSent; 00225 if( bytesToSend > sizeof(response) ) { 00226 bytesToSend = sizeof(response); 00227 } 00228 00229 memcpy(response, sendPtr, bytesToSend); 00230 sendResponse(linkID, bytesToSend); 00231 sendPtr += bytesToSend; 00232 bytesSent += bytesToSend; 00233 } 00234 } 00235 00236 void ESP8266_WebServer::SendFile(int linkID, FileHandle* file, const char* mimeType) { 00237 SendFile(linkID, file, mimeType, 86400); 00238 } 00239 void ESP8266_WebServer::SendFile(int linkID, FileHandle* file, const char* mimeType, int maxAge) { 00240 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); 00241 if( debugSerial != NULL ) { 00242 debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); 00243 } 00244 sendResponse(linkID, strlen(response)); 00245 int numBytes = file->read(response, sizeof(response)); 00246 while( numBytes > 0) { 00247 sendResponse(linkID, numBytes); 00248 numBytes = file->read(response, sizeof(response)); 00249 } 00250 } 00251 00252 int ESP8266_WebServer::SendStream(int linkID, char const* reply, int StreamSize, int WindowSize, const char* mimeType, int maxAge) { 00253 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); 00254 if( debugSerial != NULL ) { 00255 debugSerial->printf("HTTP Reply Header(%d bytes): %s\r\n", strlen(response), response); 00256 } 00257 sendResponse(linkID, strlen(response)); 00258 return SendStream(linkID, reply, WindowSize); 00259 } 00260 00261 std::string ESP8266_WebServer::GetStationMAC(void) { 00262 while( reqMode == true ) { wait_ms(1); } 00263 readBuffer(); 00264 serial->printf("AT+CIPSTAMAC?\r\n"); 00265 while( data_waiting() == 0 ) { 00266 wait_ms(10); 00267 } 00268 readBuffer(); 00269 if( debugSerial != NULL ) { 00270 debugSerial->printf("Station MAC Reply: %s\r\n", reply); 00271 } 00272 00273 std::string mac = std::string(reply); 00274 mac = mac.substr(1, 17); 00275 00276 return mac; 00277 } 00278 std::string ESP8266_WebServer::GetAPMAC(void) { 00279 while( reqMode == true ) { wait_ms(1); } 00280 readBuffer(); 00281 serial->printf("AT+CIPAPMAC?\r\n"); 00282 while( data_waiting() == 0 ) { 00283 wait_ms(10); 00284 } 00285 readBuffer(); 00286 if( debugSerial != NULL ) { 00287 debugSerial->printf("SoftAP MAC Reply: %s\r\n", reply); 00288 } 00289 00290 std::string mac = std::string(reply); 00291 mac = mac.substr(1, 17); 00292 00293 return mac; 00294 } 00295 std::string ESP8266_WebServer::GetStationIP(void) { 00296 while( reqMode == true ) { wait_ms(1); } 00297 readBuffer(); 00298 serial->printf("AT+CIPSTA?\r\n"); 00299 while( data_waiting() == 0 ) { 00300 wait_ms(10); 00301 } 00302 readBuffer(); 00303 if( debugSerial != NULL ) { 00304 debugSerial->printf("Station IP Reply: %s\r\n", reply); 00305 } 00306 00307 std::string ip = std::string(reply); 00308 ip = ip.substr(1, ip.find('"', 1) - 1); 00309 00310 return ip; 00311 } 00312 std::string ESP8266_WebServer::GetAPIP(void) { 00313 while( reqMode == true ) { wait_ms(1); } 00314 readBuffer(); 00315 serial->printf("AT+CIPAP?\r\n"); 00316 while( data_waiting() == 0 ) { 00317 wait_ms(10); 00318 } 00319 readBuffer(); 00320 if( debugSerial != NULL ) { 00321 debugSerial->printf("SoftAP IP Reply: %s\r\n", reply); 00322 } 00323 00324 std::string ip = std::string(reply); 00325 ip = ip.substr(1, ip.find('"', 1) - 1); 00326 00327 return ip; 00328 } 00329 int ESP8266_WebServer::GetOperatingMode(void) { 00330 while( reqMode == true ) { wait_ms(1); } 00331 readBuffer(); 00332 serial->printf("AT+CWMODE?\r\n"); 00333 while( data_waiting() == 0 ) { 00334 wait_ms(10); 00335 } 00336 readBuffer(); 00337 if( debugSerial != NULL ) { 00338 debugSerial->printf("Operating Mode Reply: %s\r\n", reply); 00339 } 00340 00341 return atoi(reply); 00342 } 00343 std::string ESP8266_WebServer::GetStationSSID(void) { 00344 while( reqMode == true ) { wait_ms(1); } 00345 readBuffer(); 00346 serial->printf("AT+CWJAP?\r\n"); 00347 while( data_waiting() == 0 ) { 00348 wait_ms(10); 00349 } 00350 readBuffer(); 00351 if( debugSerial != NULL ) { 00352 debugSerial->printf("Station SSID Reply: %s\r\n", reply); 00353 } 00354 00355 std::string ssid = std::string(reply); 00356 if( strstr(reply, "No AP\r\n") != NULL ) { return "(None)"; } 00357 ssid = ssid.substr(1, ssid.find('"', 1) - 1); 00358 00359 return ssid; 00360 } 00361 std::list<std::string> ESP8266_WebServer::ListAvailableSSID(void) { 00362 std::list<std::string> apList; 00363 00364 while( reqMode == true ) { wait_ms(1); } 00365 readBuffer(); 00366 serial->printf("AT+CWLAP\r\n"); 00367 while( data_waiting() == 0 ) { 00368 wait_ms(10); 00369 } 00370 readBuffer(); 00371 if( debugSerial != NULL ) { 00372 debugSerial->printf("SSID List Reply: %s\r\n", reply); 00373 } 00374 00375 char ssid[65]; 00376 char apmac[20]; 00377 int ecn; 00378 int rssi; 00379 int tokenLength; 00380 char* token = strstr(reply, "("); 00381 while( token != NULL ) { 00382 int numMatched = sscanf(token, "(%d,\"%[^\"]\",%d,\"%[0123456789abcdef:]\",%*d)\r\n%n", &ecn, ssid, &rssi, apmac, &tokenLength); 00383 if( numMatched < 4 ) { 00384 if( debugSerial != NULL ) { 00385 debugSerial->printf("SSID List Token Error: NumMatched=%d, SSID=%s\r\n", numMatched, ssid); 00386 } 00387 return apList; 00388 } 00389 if( debugSerial != NULL ) { 00390 debugSerial->printf("SSID List Token : SSID=%s, ECN=%d, RSSI=%d, APMAC=%s, TokenLength=%d\r\n", ssid, ecn, rssi, apmac, tokenLength); 00391 } 00392 apList.push_back(std::string(ssid)); 00393 token += tokenLength; 00394 token = strstr(token, "("); 00395 } 00396 00397 return apList; 00398 } 00399 std::string ESP8266_WebServer::GetFirmwareVersion(void) { 00400 while( reqMode == true ) { wait_ms(1); } 00401 readBuffer(); 00402 serial->printf("AT+GMR\r\n"); 00403 while( data_waiting() == 0 ) { 00404 wait_ms(10); 00405 } 00406 readBuffer(); 00407 if( debugSerial != NULL ) { 00408 debugSerial->printf("Firmware Version Reply: %s\r\n", reply); 00409 } 00410 00411 std::string ver = std::string(reply); 00412 ver = ver.substr(0, ver.find('\r')); 00413 00414 return ver; 00415 } 00416 00417 int ESP8266_WebServer::SendStream(int linkID, char const* reply, int WindowSize) { 00418 char const* sendPtr = reply; 00419 int bytesSent = 0; 00420 while( bytesSent < WindowSize ) { 00421 int bytesToSend = WindowSize - bytesSent; 00422 if( bytesToSend > sizeof(response) ) { 00423 bytesToSend = sizeof(response); 00424 } 00425 00426 memcpy(response, sendPtr, bytesToSend); 00427 sendResponse(linkID, bytesToSend); 00428 sendPtr += bytesToSend; 00429 bytesSent += bytesToSend; 00430 } 00431 00432 return bytesSent; 00433 } 00434 00435 bool ESP8266_WebServer::SetOperatingMode(int mode) { 00436 if( debugSerial != NULL ) { 00437 debugSerial->printf("Set Operating Mode to %s(%d)\r\n", opModes[mode], mode); 00438 } 00439 00440 while( reqMode == true ) { wait_ms(1); } 00441 readBuffer(); 00442 serial->printf("AT+CWMODE=%d\r\n", mode); 00443 while( data_waiting() == 0 ) { 00444 wait_ms(10); 00445 } 00446 readBuffer(); 00447 if( debugSerial != NULL ) { 00448 debugSerial->printf("Set Operating Mode Reply: %s\r\n", reply); 00449 } 00450 if( strstr(reply, "\r\nOK\r\n") != NULL ) { return true; } 00451 return false; 00452 } 00453 00454 bool ESP8266_WebServer::SetStationSSID(std::string newAP, std::string password) { 00455 if( debugSerial != NULL ) { 00456 debugSerial->printf("Set Station SSID to %s, Password=%s\r\n", newAP.c_str(), password.c_str()); 00457 } 00458 while( reqMode == true ) { wait_ms(1); } 00459 readBuffer(); 00460 serial->printf("AT+CWJAP=\"%s\",\"%s\"\r\n", newAP.c_str(), password.c_str()); 00461 while( data_waiting() == 0 ) { 00462 wait_ms(10); 00463 } 00464 readBuffer(); 00465 if( debugSerial != NULL ) { 00466 debugSerial->printf("Set Station SSID Reply: %s\r\n", reply); 00467 } 00468 if( strstr(reply, "\r\nOK\r\n") != NULL ) { return true; } 00469 00470 return false; 00471 } 00472 00473 ESP8266_WebRequest::ESP8266_WebRequest(const char* packet, Serial* debug) { 00474 int sz = strlen(packet); 00475 data = (char *)malloc(sz+1); 00476 memcpy(data, packet, sz+1); 00477 debugSerial = debug; 00478 } 00479 00480 void ESP8266_WebRequest::Read(void) { 00481 int bytesRecv, ipdLen, linkID; 00482 int numMatched = sscanf(data,"+IPD,%d,%d:%n", &linkID, &bytesRecv, &ipdLen); 00483 if( numMatched != 2 ) { 00484 if( debugSerial != NULL ) { 00485 debugSerial->printf("IPD ERROR : Matched %d, LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", numMatched, linkID, bytesRecv, ipdLen); 00486 } 00487 return; 00488 } 00489 00490 if( debugSerial != NULL ) { 00491 debugSerial->printf("IPD Data: LinkID=%d, BytesRecv=%d, IPD Header Len=%d\r\n", linkID, bytesRecv, ipdLen); 00492 } 00493 if( strstr(data, "HTTP") != NULL ) { 00494 if( debugSerial != NULL ) { 00495 debugSerial->printf("Got HTTP Request\r\n"); 00496 } 00497 char* httpPacket = data + ipdLen; 00498 if( debugSerial != NULL ) { 00499 debugSerial->printf("HTTP Packet: %s\r\n", httpPacket); 00500 } 00501 char* httpMethod = (char*)malloc(16); 00502 char* httpURI = (char*)malloc(256); 00503 00504 int numMatched = sscanf(httpPacket, "%s %s HTTP/%*c.%*c", httpMethod, httpURI); 00505 if( numMatched != 2 ) { 00506 if( debugSerial != NULL ) { 00507 debugSerial->printf("HTTP ERROR : Matched %d, Method=%s, URI=%s\r\n", numMatched, httpMethod, httpURI); 00508 } 00509 00510 free(httpMethod); 00511 free(httpURI); 00512 return; 00513 } 00514 00515 LinkID = linkID; 00516 Method = httpMethod; 00517 URI = httpURI; 00518 int pos = URI.find('?'); 00519 if(pos != string::npos ) { 00520 string params = URI.substr(pos+1); 00521 URI = URI.substr(0,pos); 00522 pos = params.find('='); 00523 while( pos != string::npos ) { 00524 string name = params.substr(0,pos); 00525 string value = params.substr(pos+1); 00526 pos = params.find('&'); 00527 if( pos == string::npos ) 00528 { 00529 if( debugSerial != NULL ) { 00530 debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str()); 00531 } 00532 Parameters[name] = value; 00533 break; 00534 } 00535 00536 value = value.substr(0,value.find('&')); 00537 params = params.substr(pos+1); 00538 pos = params.find('='); 00539 if( debugSerial != NULL ) { 00540 debugSerial->printf("HTTP GET Parameter %s=%s\r\n", name.c_str(), value.c_str()); 00541 } 00542 Parameters[name] = value; 00543 } 00544 } 00545 if( debugSerial != NULL ) { 00546 debugSerial->printf("HTTP %s %s\r\n", httpMethod, httpURI); 00547 } 00548 00549 free(httpMethod); 00550 free(httpURI); 00551 } 00552 } 00553 00554 ESP8266_WebRequest::~ESP8266_WebRequest() 00555 { 00556 free(data); 00557 }
Generated on Mon Jul 18 2022 04:24:01 by 1.7.2