ESP8266 WiFi Module Web Server library

Committer:
sschocke
Date:
Thu Jan 01 16:27:58 2015 +0000
Revision:
3:4ef7db7a95a7
Parent:
2:6079554681d6
Child:
4:759de84e790b
Child:
5:48b7fd921bef
Added extra functions allowing Cache Control with replies; Added a few missing mimeTypes

Who changed what in which revision?

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