├── .gitattributes ├── .gitignore ├── README.md ├── UtilityFunctions ├── UtilityFunctions.cpp ├── UtilityFunctions.h └── library.properties ├── coap ├── coap.c └── coap.h ├── html └── mqtt_server.html ├── http_coap_mqtt_server ├── endpoints.c ├── http_coap_mqtt_server.ino └── sketch.h └── webserver ├── lwipopts.h ├── mem_manager.h └── user_webserver.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

ESP8266 Triple Server

2 | 3 | This project provides a Web Server Framework that supports 3 simultaneous protocols: 4 | 5 | 1. http 6 | 2. MQTT 7 | 3. CoAP 8 | 9 | Setup: 10 | 11 | 1. Copy the http_coap_mqtt_server folder to your Arduino sketch folder. 12 | 2. Copy the UtilityFunctions folder to your Arduino libraries folder. 13 | 3. Copy the coap folder to your Arduino libraries folder. 14 | 4. Copy the webserver folder to your Arduino libraries folder. 15 | 5. Change the following in the http_coap_mqtt_server.ino file to match your network settings: 16 | 17 | const char* ssid = "YOURWIFISSID"; 18 | const char* password = "YOURWIFIPASSWORD"; 19 | const IPAddress ipadd(192,168,0,132); 20 | const IPAddress ipgat(192,168,0,1); 21 | 22 | define SVRPORT 9701 23 | 24 | 6.0 Server Setting 25 | 26 | 6.1 To use the standard Arduino Web Server library, which polls for connections, use this define in the sketch: 27 | 28 | define SVR_TYPE SVR_HTTP_LIB 29 | 30 | 6.2 To use the EspressIf SDK Web Server API, which uses event callbacks, use this define in the sketch.h file: 31 | 32 | define SVR_TYPE SVR_HTTP_SDK 33 | 34 | Operation: 35 | 36 | While not necessary, the code assumes an LED is connected to GPIO16. This LED is ON upon 37 | power-up and is turned OFF once initialization completes. 38 | 39 | 40 | Server test: 41 | 42 | Note: In order to test the CoAP server, Mozilla Firefox must be installed with the 43 | Copper (Cu) add-on user-agent installed. 44 | 45 | To install Copper:
46 | a. Open the Mozilla Firefox browser
47 | b. Enter the URL:
48 | https://addons.mozilla.org/en-US/firefox/addon/copper-270430/
49 | c. Click on the "Add to Firefox" button
50 | 51 | Here is the test... 52 | 53 | First, compile and load the sketch to the ESP8266. With the sketch running, follow 54 | the following 3 server-specific steps: 55 | 56 | 1. http server:
57 | a. Open the html file mqtt_server.html in a web browser
58 | b. Click the "Request via HTTP" button
59 | 60 | 2. mqtt server:
61 | a. pen the html file mqtt_server.html in a web browser
62 | b. Click the "Request via MQTT" button
63 | 64 | 3. coap server:
65 | a. open the Mozilla Firefox web browser and enter the URL:
66 | coap://192.168.0.132:5683
67 | b. Click the "Discover" button
68 | c. Click the "request" service (left part of web browser window)
69 | d. Enter "/?request=GetSensors" in the Outgoing Payload tab (center of web browser window)
70 | e. Click the "Put" button 71 | 72 | For each of the 3 servers: 73 | 74 | A JSON string will be returned with the sensor values in this format: 75 | 76 | {
77 | "Ain0":"316.00",
78 | "Ain1":"326.00",
79 | "Ain2":"325.00",
80 | "Ain3":"314.00",
81 | "Ain4":"316.00",
82 | "Ain5":"163.00",
83 | "Ain6":"208.00",
84 | "Ain7":"333.00",
85 | "SYS_Heap":"25408",
86 | "SYS_Time":"26"
87 | }
88 | 89 | -------------------------------------------------------------------------------- /UtilityFunctions/UtilityFunctions.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | This is a library of utility functions 3 | 4 | Designed specifically to work with ESP8266 in the 5 | Arduino IDE platform. 6 | 7 | Written by Dave St. Aubin. 8 | Creative Commons license. 9 | *******************************************************/ 10 | #include "UtilityFunctions.h" 11 | 12 | /******************************************************* 13 | * Replaces the math.h pwr function since we cannot 14 | * successfully link to it with the ESP8266 Arduino IDE 15 | *******************************************************/ 16 | float powr(float x, int y) 17 | { 18 | float temp; 19 | if( y == 0) 20 | return 1; 21 | temp = powr(x, y/2); 22 | if (y%2 == 0) 23 | return temp*temp; 24 | else 25 | { 26 | if(y > 0) 27 | return x*temp*temp; 28 | else 29 | return (temp*temp)/x; 30 | } 31 | } 32 | 33 | // reverses a string 'str' of length 'len' 34 | void reverse(char *str, int len) 35 | { 36 | int i=0, j=len-1, temp; 37 | while (i 5 | sentence=Utility Functions to overcome ESP8266 shortcomings 6 | paragraph=Utility Functions to overcome ESP8266 shortcomings 7 | category=Sensors 8 | url=* 9 | architectures=* 10 | -------------------------------------------------------------------------------- /coap/coap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "coap.h" 8 | 9 | extern void endpoint_setup(void); 10 | extern const coap_endpoint_t endpoints[]; 11 | 12 | #ifdef DEBUG 13 | void coap_dumpHeader(coap_header_t *hdr) 14 | { 15 | printf("Header:\n"); 16 | printf(" ver 0x%02X\n", hdr->ver); 17 | printf(" t 0x%02X\n", hdr->t); 18 | printf(" tkl 0x%02X\n", hdr->tkl); 19 | printf(" code 0x%02X\n", hdr->code); 20 | printf(" id 0x%02X%02X\n", hdr->id[0], hdr->id[1]); 21 | } 22 | #endif 23 | 24 | #ifdef DEBUG 25 | void coap_dump(const uint8_t *buf, size_t buflen, bool bare) 26 | { 27 | if (bare) 28 | { 29 | while(buflen--) 30 | printf("%02X%s", *buf++, (buflen > 0) ? " " : ""); 31 | } 32 | else 33 | { 34 | printf("Dump: "); 35 | while(buflen--) 36 | printf("%02X%s", *buf++, (buflen > 0) ? " " : ""); 37 | printf("\n"); 38 | } 39 | } 40 | #endif 41 | 42 | int coap_parseHeader(coap_header_t *hdr, const uint8_t *buf, size_t buflen) 43 | { 44 | if (buflen < 4) 45 | return COAP_ERR_HEADER_TOO_SHORT; 46 | hdr->ver = (buf[0] & 0xC0) >> 6; 47 | if (hdr->ver != 1) 48 | return COAP_ERR_VERSION_NOT_1; 49 | hdr->t = (buf[0] & 0x30) >> 4; 50 | hdr->tkl = buf[0] & 0x0F; 51 | hdr->code = buf[1]; 52 | hdr->id[0] = buf[2]; 53 | hdr->id[1] = buf[3]; 54 | return 0; 55 | } 56 | 57 | int coap_parseToken(coap_buffer_t *tokbuf, const coap_header_t *hdr, const uint8_t *buf, size_t buflen) 58 | { 59 | if (hdr->tkl == 0) 60 | { 61 | tokbuf->p = NULL; 62 | tokbuf->len = 0; 63 | return 0; 64 | } 65 | else 66 | if (hdr->tkl <= 8) 67 | { 68 | if (4U + hdr->tkl > buflen) 69 | return COAP_ERR_TOKEN_TOO_SHORT; // tok bigger than packet 70 | tokbuf->p = buf+4; // past header 71 | tokbuf->len = hdr->tkl; 72 | return 0; 73 | } 74 | else 75 | { 76 | // invalid size 77 | return COAP_ERR_TOKEN_TOO_SHORT; 78 | } 79 | } 80 | 81 | // advances p 82 | int coap_parseOption(coap_option_t *option, uint16_t *running_delta, const uint8_t **buf, size_t buflen) 83 | { 84 | const uint8_t *p = *buf; 85 | uint8_t headlen = 1; 86 | uint16_t len, delta; 87 | 88 | if (buflen < headlen) // too small 89 | return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 90 | 91 | delta = (p[0] & 0xF0) >> 4; 92 | len = p[0] & 0x0F; 93 | 94 | // These are untested and may be buggy 95 | if (delta == 13) 96 | { 97 | headlen++; 98 | if (buflen < headlen) 99 | return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 100 | delta = p[1] + 13; 101 | p++; 102 | } 103 | else 104 | if (delta == 14) 105 | { 106 | headlen += 2; 107 | if (buflen < headlen) 108 | return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 109 | delta = ((p[1] << 8) | p[2]) + 269; 110 | p+=2; 111 | } 112 | else 113 | if (delta == 15) 114 | return COAP_ERR_OPTION_DELTA_INVALID; 115 | 116 | if (len == 13) 117 | { 118 | headlen++; 119 | if (buflen < headlen) 120 | return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 121 | len = p[1] + 13; 122 | p++; 123 | } 124 | else 125 | if (len == 14) 126 | { 127 | headlen += 2; 128 | if (buflen < headlen) 129 | return COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER; 130 | len = ((p[1] << 8) | p[2]) + 269; 131 | p+=2; 132 | } 133 | else 134 | if (len == 15) 135 | return COAP_ERR_OPTION_LEN_INVALID; 136 | 137 | if ((p + 1 + len) > (*buf + buflen)) 138 | return COAP_ERR_OPTION_TOO_BIG; 139 | 140 | //printf("option num=%d\n", delta + *running_delta); 141 | option->num = delta + *running_delta; 142 | option->buf.p = p+1; 143 | option->buf.len = len; 144 | //coap_dump(p+1, len, false); 145 | 146 | // advance buf 147 | *buf = p + 1 + len; 148 | *running_delta += delta; 149 | 150 | return 0; 151 | } 152 | 153 | // http://tools.ietf.org/html/rfc7252#section-3.1 154 | int coap_parseOptionsAndPayload(coap_option_t *options, uint8_t *numOptions, coap_buffer_t *payload, const coap_header_t *hdr, const uint8_t *buf, size_t buflen) 155 | { 156 | size_t optionIndex = 0; 157 | uint16_t delta = 0; 158 | const uint8_t *p = buf + 4 + hdr->tkl; 159 | const uint8_t *end = buf + buflen; 160 | int rc; 161 | if (p > end) 162 | return COAP_ERR_OPTION_OVERRUNS_PACKET; // out of bounds 163 | 164 | //coap_dump(p, end - p); 165 | 166 | // 0xFF is payload marker 167 | while((optionIndex < *numOptions) && (p < end) && (*p != 0xFF)) 168 | { 169 | if (0 != (rc = coap_parseOption(&options[optionIndex], &delta, &p, end-p))) 170 | return rc; 171 | optionIndex++; 172 | } 173 | *numOptions = optionIndex; 174 | 175 | if (p+1 < end && *p == 0xFF) // payload marker 176 | { 177 | payload->p = p+1; 178 | payload->len = end-(p+1); 179 | } 180 | else 181 | { 182 | payload->p = NULL; 183 | payload->len = 0; 184 | } 185 | 186 | return 0; 187 | } 188 | 189 | #ifdef DEBUG 190 | void coap_dumpOptions(coap_option_t *opts, size_t numopt) 191 | { 192 | size_t i; 193 | printf(" Options:\n"); 194 | for (i=0;ihdr); 207 | coap_dumpOptions(pkt->opts, pkt->numopts); 208 | printf("Payload: "); 209 | coap_dump(pkt->payload.p, pkt->payload.len, true); 210 | printf("\n"); 211 | } 212 | #endif 213 | 214 | int coap_parse(coap_packet_t *pkt, const uint8_t *buf, size_t buflen) 215 | { 216 | int rc; 217 | 218 | // coap_dump(buf, buflen, false); 219 | 220 | if (0 != (rc = coap_parseHeader(&pkt->hdr, buf, buflen))) 221 | return rc; 222 | // coap_dumpHeader(&hdr); 223 | if (0 != (rc = coap_parseToken(&pkt->tok, &pkt->hdr, buf, buflen))) 224 | return rc; 225 | pkt->numopts = MAXOPT; 226 | if (0 != (rc = coap_parseOptionsAndPayload(pkt->opts, &(pkt->numopts), &(pkt->payload), &pkt->hdr, buf, buflen))) 227 | return rc; 228 | // coap_dumpOptions(opts, numopt); 229 | return 0; 230 | } 231 | 232 | // options are always stored consecutively, so can return a block with same option num 233 | const coap_option_t *coap_findOptions(const coap_packet_t *pkt, uint8_t num, uint8_t *count) 234 | { 235 | // FIXME, options is always sorted, can find faster than this 236 | size_t i; 237 | const coap_option_t *first = NULL; 238 | *count = 0; 239 | for (i=0;inumopts;i++) 240 | { 241 | if (pkt->opts[i].num == num) 242 | { 243 | if (NULL == first) 244 | first = &pkt->opts[i]; 245 | (*count)++; 246 | } 247 | else 248 | { 249 | if (NULL != first) 250 | break; 251 | } 252 | } 253 | return first; 254 | } 255 | 256 | int coap_buffer_to_string(char *strbuf, size_t strbuflen, const coap_buffer_t *buf) 257 | { 258 | if (buf->len+1 > strbuflen) 259 | return COAP_ERR_BUFFER_TOO_SMALL; 260 | memcpy(strbuf, buf->p, buf->len); 261 | strbuf[buf->len] = 0; 262 | return 0; 263 | } 264 | 265 | int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt) 266 | { 267 | size_t opts_len = 0; 268 | size_t i; 269 | uint8_t *p; 270 | uint16_t running_delta = 0; 271 | 272 | // build header 273 | if (*buflen < (4U + pkt->hdr.tkl)) 274 | return COAP_ERR_BUFFER_TOO_SMALL; 275 | 276 | buf[0] = (pkt->hdr.ver & 0x03) << 6; 277 | buf[0] |= (pkt->hdr.t & 0x03) << 4; 278 | buf[0] |= (pkt->hdr.tkl & 0x0F); 279 | buf[1] = pkt->hdr.code; 280 | buf[2] = pkt->hdr.id[0]; 281 | buf[3] = pkt->hdr.id[1]; 282 | 283 | // inject token 284 | p = buf + 4; 285 | if ((pkt->hdr.tkl > 0) && (pkt->hdr.tkl != pkt->tok.len)) 286 | return COAP_ERR_UNSUPPORTED; 287 | 288 | if (pkt->hdr.tkl > 0) 289 | memcpy(p, pkt->tok.p, pkt->hdr.tkl); 290 | 291 | // // http://tools.ietf.org/html/rfc7252#section-3.1 292 | // inject options 293 | p += pkt->hdr.tkl; 294 | 295 | for (i=0;inumopts;i++) 296 | { 297 | uint32_t optDelta; 298 | uint8_t len, delta = 0; 299 | 300 | if (((size_t)(p-buf)) > *buflen) 301 | return COAP_ERR_BUFFER_TOO_SMALL; 302 | optDelta = pkt->opts[i].num - running_delta; 303 | coap_option_nibble(optDelta, &delta); 304 | coap_option_nibble((uint32_t)pkt->opts[i].buf.len, &len); 305 | 306 | *p++ = (0xFF & (delta << 4 | len)); 307 | if (delta == 13) 308 | { 309 | *p++ = (optDelta - 13); 310 | } 311 | else 312 | if (delta == 14) 313 | { 314 | *p++ = ((optDelta-269) >> 8); 315 | *p++ = (0xFF & (optDelta-269)); 316 | } 317 | if (len == 13) 318 | { 319 | *p++ = (pkt->opts[i].buf.len - 13); 320 | } 321 | else 322 | if (len == 14) 323 | { 324 | *p++ = (pkt->opts[i].buf.len >> 8); 325 | *p++ = (0xFF & (pkt->opts[i].buf.len-269)); 326 | } 327 | 328 | memcpy(p, pkt->opts[i].buf.p, pkt->opts[i].buf.len); 329 | p += pkt->opts[i].buf.len; 330 | running_delta = pkt->opts[i].num; 331 | } 332 | 333 | opts_len = (p - buf) - 4; // number of bytes used by options 334 | 335 | if (pkt->payload.len > 0) 336 | { 337 | if (*buflen < 4 + 1 + pkt->payload.len + opts_len) 338 | return COAP_ERR_BUFFER_TOO_SMALL; 339 | buf[4 + opts_len] = 0xFF; // payload marker 340 | memcpy(buf+5 + opts_len, pkt->payload.p, pkt->payload.len); 341 | *buflen = opts_len + 5 + pkt->payload.len; 342 | } 343 | else 344 | *buflen = opts_len + 4; 345 | return 0; 346 | } 347 | 348 | void coap_option_nibble(uint32_t value, uint8_t *nibble) 349 | { 350 | if (value<13) 351 | { 352 | *nibble = (0xFF & value); 353 | } 354 | else 355 | if (value<=0xFF+13) 356 | { 357 | *nibble = 13; 358 | } else if (value<=0xFFFF+269) 359 | { 360 | *nibble = 14; 361 | } 362 | } 363 | 364 | int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type) 365 | { 366 | pkt->hdr.ver = 0x01; 367 | pkt->hdr.t = COAP_TYPE_ACK; 368 | pkt->hdr.tkl = 0; 369 | pkt->hdr.code = rspcode; 370 | pkt->hdr.id[0] = msgid_hi; 371 | pkt->hdr.id[1] = msgid_lo; 372 | pkt->numopts = 1; 373 | 374 | // need token in response 375 | if (tok) { 376 | pkt->hdr.tkl = tok->len; 377 | pkt->tok = *tok; 378 | } 379 | 380 | // safe because 1 < MAXOPT 381 | pkt->opts[0].num = COAP_OPTION_CONTENT_FORMAT; 382 | pkt->opts[0].buf.p = scratch->p; 383 | if (scratch->len < 2) 384 | return COAP_ERR_BUFFER_TOO_SMALL; 385 | scratch->p[0] = ((uint16_t)content_type & 0xFF00) >> 8; 386 | scratch->p[1] = ((uint16_t)content_type & 0x00FF); 387 | pkt->opts[0].buf.len = 2; 388 | pkt->payload.p = content; 389 | pkt->payload.len = content_len; 390 | return 0; 391 | } 392 | 393 | // FIXME, if this looked in the table at the path before the method then 394 | // it could more easily return 405 errors 395 | int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt) 396 | { 397 | const coap_option_t *opt; 398 | uint8_t count; 399 | int i; 400 | const coap_endpoint_t *ep = endpoints; 401 | 402 | while(NULL != ep->handler) 403 | { 404 | if (ep->method != inpkt->hdr.code) 405 | goto next; 406 | if (NULL != (opt = coap_findOptions(inpkt, COAP_OPTION_URI_PATH, &count))) 407 | { 408 | if (count != ep->path->count) 409 | goto next; 410 | for (i=0;ipath->elems[i])) 413 | goto next; 414 | if (0 != memcmp(ep->path->elems[i], opt[i].buf.p, opt[i].buf.len)) 415 | goto next; 416 | } 417 | // match! 418 | return ep->handler(scratch, inpkt, outpkt, inpkt->hdr.id[0], inpkt->hdr.id[1]); 419 | } 420 | next: 421 | ep++; 422 | } 423 | 424 | coap_make_response(scratch, outpkt, NULL, 0, inpkt->hdr.id[0], inpkt->hdr.id[1], &inpkt->tok, COAP_RSPCODE_NOT_FOUND, COAP_CONTENTTYPE_NONE); 425 | 426 | return 0; 427 | } 428 | 429 | void coap_setup(void) 430 | { 431 | } 432 | 433 | -------------------------------------------------------------------------------- /coap/coap.h: -------------------------------------------------------------------------------- 1 | #ifndef COAP_H 2 | #define COAP_H 1 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #define MAXOPT 16 13 | 14 | //http://tools.ietf.org/html/rfc7252#section-3 15 | typedef struct 16 | { 17 | uint8_t ver; /* CoAP version number */ 18 | uint8_t t; /* CoAP Message Type */ 19 | uint8_t tkl; /* Token length: indicates length of the Token field */ 20 | uint8_t code; /* CoAP status code. Can be request (0.xx), success reponse (2.xx), 21 | * client error response (4.xx), or rever error response (5.xx) 22 | * For possible values, see http://tools.ietf.org/html/rfc7252#section-12.1 */ 23 | uint8_t id[2]; 24 | } coap_header_t; 25 | 26 | typedef struct 27 | { 28 | const uint8_t *p; 29 | size_t len; 30 | } coap_buffer_t; 31 | 32 | typedef struct 33 | { 34 | uint8_t *p; 35 | size_t len; 36 | } coap_rw_buffer_t; 37 | 38 | typedef struct 39 | { 40 | uint8_t num; /* Option number. See http://tools.ietf.org/html/rfc7252#section-5.10 */ 41 | coap_buffer_t buf; /* Option value */ 42 | } coap_option_t; 43 | 44 | typedef struct 45 | { 46 | coap_header_t hdr; /* Header of the packet */ 47 | coap_buffer_t tok; /* Token value, size as specified by hdr.tkl */ 48 | uint8_t numopts; /* Number of options */ 49 | coap_option_t opts[MAXOPT]; /* Options of the packet. For possible entries see 50 | * http://tools.ietf.org/html/rfc7252#section-5.10 */ 51 | coap_buffer_t payload; /* Payload carried by the packet */ 52 | } coap_packet_t; 53 | 54 | ///////////////////////////////////////// 55 | 56 | //http://tools.ietf.org/html/rfc7252#section-12.2 57 | typedef enum 58 | { 59 | COAP_OPTION_IF_MATCH = 1, 60 | COAP_OPTION_URI_HOST = 3, 61 | COAP_OPTION_ETAG = 4, 62 | COAP_OPTION_IF_NONE_MATCH = 5, 63 | COAP_OPTION_OBSERVE = 6, 64 | COAP_OPTION_URI_PORT = 7, 65 | COAP_OPTION_LOCATION_PATH = 8, 66 | COAP_OPTION_URI_PATH = 11, 67 | COAP_OPTION_CONTENT_FORMAT = 12, 68 | COAP_OPTION_MAX_AGE = 14, 69 | COAP_OPTION_URI_QUERY = 15, 70 | COAP_OPTION_ACCEPT = 17, 71 | COAP_OPTION_LOCATION_QUERY = 20, 72 | COAP_OPTION_PROXY_URI = 35, 73 | COAP_OPTION_PROXY_SCHEME = 39 74 | } coap_option_num_t; 75 | 76 | //http://tools.ietf.org/html/rfc7252#section-12.1.1 77 | typedef enum 78 | { 79 | COAP_METHOD_GET = 1, 80 | COAP_METHOD_POST = 2, 81 | COAP_METHOD_PUT = 3, 82 | COAP_METHOD_DELETE = 4 83 | } coap_method_t; 84 | 85 | //http://tools.ietf.org/html/rfc7252#section-12.1.1 86 | typedef enum 87 | { 88 | COAP_TYPE_CON = 0, 89 | COAP_TYPE_NONCON = 1, 90 | COAP_TYPE_ACK = 2, 91 | COAP_TYPE_RESET = 3 92 | } coap_msgtype_t; 93 | 94 | //http://tools.ietf.org/html/rfc7252#section-5.2 95 | //http://tools.ietf.org/html/rfc7252#section-12.1.2 96 | #define MAKE_RSPCODE(clas, det) ((clas << 5) | (det)) 97 | typedef enum 98 | { 99 | COAP_RSPCODE_CONTENT = MAKE_RSPCODE(2, 5), 100 | COAP_RSPCODE_NOT_FOUND = MAKE_RSPCODE(4, 4), 101 | COAP_RSPCODE_BAD_REQUEST = MAKE_RSPCODE(4, 0), 102 | COAP_RSPCODE_CHANGED = MAKE_RSPCODE(2, 4) 103 | } coap_responsecode_t; 104 | 105 | //http://tools.ietf.org/html/rfc7252#section-12.3 106 | typedef enum 107 | { 108 | COAP_CONTENTTYPE_NONE = -1, // bodge to allow us not to send option block 109 | COAP_CONTENTTYPE_TEXT_PLAIN = 0, 110 | COAP_CONTENTTYPE_APPLICATION_LINKFORMAT = 40, 111 | } coap_content_type_t; 112 | 113 | /////////////////////// 114 | 115 | typedef enum 116 | { 117 | COAP_ERR_NONE = 0, 118 | COAP_ERR_HEADER_TOO_SHORT = 1, 119 | COAP_ERR_VERSION_NOT_1 = 2, 120 | COAP_ERR_TOKEN_TOO_SHORT = 3, 121 | COAP_ERR_OPTION_TOO_SHORT_FOR_HEADER = 4, 122 | COAP_ERR_OPTION_TOO_SHORT = 5, 123 | COAP_ERR_OPTION_OVERRUNS_PACKET = 6, 124 | COAP_ERR_OPTION_TOO_BIG = 7, 125 | COAP_ERR_OPTION_LEN_INVALID = 8, 126 | COAP_ERR_BUFFER_TOO_SMALL = 9, 127 | COAP_ERR_UNSUPPORTED = 10, 128 | COAP_ERR_OPTION_DELTA_INVALID = 11, 129 | } coap_error_t; 130 | 131 | /////////////////////// 132 | 133 | typedef int (*coap_endpoint_func)(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 134 | #define MAX_SEGMENTS 2 // 2 = /foo/bar, 3 = /foo/bar/baz 135 | typedef struct 136 | { 137 | int count; 138 | const char *elems[MAX_SEGMENTS]; 139 | } coap_endpoint_path_t; 140 | 141 | typedef struct 142 | { 143 | coap_method_t method; /* (i.e. POST, PUT or GET) */ 144 | coap_endpoint_func handler; /* callback function which handles this 145 | * type of endpoint (and calls 146 | * coap_make_response() at some point) */ 147 | const coap_endpoint_path_t *path; /* path towards a resource (i.e. foo/bar/) */ 148 | const char *core_attr; /* the 'ct' attribute, as defined in RFC7252, section 7.2.1.: 149 | * "The Content-Format code "ct" attribute 150 | * provides a hint about the 151 | * Content-Formats this resource returns." 152 | * (Section 12.3. lists possible ct values.) */ 153 | } coap_endpoint_t; 154 | 155 | 156 | /////////////////////// 157 | void coap_dumpPacket(coap_packet_t *pkt); 158 | int coap_parse(coap_packet_t *pkt, const uint8_t *buf, size_t buflen); 159 | int coap_buffer_to_string(char *strbuf, size_t strbuflen, const coap_buffer_t *buf); 160 | const coap_option_t *coap_findOptions(const coap_packet_t *pkt, uint8_t num, uint8_t *count); 161 | int coap_build(uint8_t *buf, size_t *buflen, const coap_packet_t *pkt); 162 | void coap_dump(const uint8_t *buf, size_t buflen, bool bare); 163 | int coap_make_response(coap_rw_buffer_t *scratch, coap_packet_t *pkt, const uint8_t *content, size_t content_len, uint8_t msgid_hi, uint8_t msgid_lo, const coap_buffer_t* tok, coap_responsecode_t rspcode, coap_content_type_t content_type); 164 | int coap_handle_req(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt); 165 | void coap_option_nibble(uint32_t value, uint8_t *nibble); 166 | void coap_setup(void); 167 | void endpoint_setup(void); 168 | 169 | #ifdef __cplusplus 170 | } 171 | #endif 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /html/mqtt_server.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MQTT JavaScript Client Example 5 | 6 | 7 | 8 | 9 |
ESP8266 MQTT vs HTTP Servers

10 |
11 |

12 | Request:
13 | 14 | 15 | 16 |

17 | Sent Timestamp:
18 |
19 | Recv Timestamp:
20 |
21 | Lapse Time (ms):
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /http_coap_mqtt_server/endpoints.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "coap.h" 4 | 5 | #define LED_IND 16 // LED used for server command testing 6 | #define LOW 0 7 | #define HIGH 1 8 | 9 | //Server actions 10 | #define SET_LED_OFF 0 11 | #define SET_LED_ON 1 12 | #define Get_SENSORS 2 13 | #define INVALID_REQUEST 99 14 | 15 | static char light[10] = "000"; 16 | static char rqst[256] = ""; 17 | static char replystring[256]; 18 | 19 | const uint16_t rsplen = 1500; 20 | static char rsp[1500] = ""; 21 | 22 | #include 23 | void blinkLed(int nblink); 24 | static int led = LED_IND; 25 | 26 | ////////////////////////////////////////////////////////////////////////// 27 | // Local function prototypes 28 | ////////////////////////////////////////////////////////////////////////// 29 | void endpoint_setup(void); 30 | int numbers_only(const char *s); 31 | void build_rsp(void); 32 | static int handle_get_well_known_core(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 33 | static int handle_get_light_blink(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 34 | static int handle_put_light_blink(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 35 | static int handle_get_request(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 36 | static int handle_put_request(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 37 | static int handle_get_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 38 | static int handle_put_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 39 | static int handle_get_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 40 | static int handle_put_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo); 41 | 42 | 43 | ////////////////////////////////////////////////////////////////////////// 44 | // Endpoint Setup 45 | ////////////////////////////////////////////////////////////////////////// 46 | void endpoint_setup(void) 47 | { 48 | build_rsp(); 49 | } 50 | 51 | ////////////////////////////////////////////////////////////////////////// 52 | // Return 1 if all numbers, 0 if not 53 | ////////////////////////////////////////////////////////////////////////// 54 | int numbers_only(const char *s) 55 | { 56 | while (*s) { 57 | if (isdigit(*s++) == 0) return 0; 58 | } 59 | return 1; 60 | } 61 | 62 | ////////////////////////////////////////////////////////////////////////// 63 | // Define URI path for all CoAP Methods for this Server 64 | ////////////////////////////////////////////////////////////////////////// 65 | static const coap_endpoint_path_t path_well_known_core = {2, {".well-known", "core"}}; 66 | static const coap_endpoint_path_t path_light_blink = {1, {"light_blink"}}; 67 | static const coap_endpoint_path_t path_request = {1, {"request"}}; 68 | static const coap_endpoint_path_t path_light = {1, {"light"}}; 69 | 70 | ////////////////////////////////////////////////////////////////////////// 71 | // Define all CoAP Methods for this Server 72 | ////////////////////////////////////////////////////////////////////////// 73 | const coap_endpoint_t endpoints[] = 74 | { 75 | {COAP_METHOD_GET, handle_get_well_known_core, &path_well_known_core, "ct=40"}, 76 | {COAP_METHOD_GET, handle_get_light, &path_light, "ct=0"}, 77 | {COAP_METHOD_GET, handle_get_light_blink, &path_light_blink, "ct=0"}, 78 | {COAP_METHOD_GET, handle_get_request, &path_request, "ct=0"}, 79 | {COAP_METHOD_PUT, handle_put_request, &path_request, NULL}, 80 | {COAP_METHOD_PUT, handle_put_light, &path_light, NULL}, 81 | {COAP_METHOD_PUT, handle_put_light_blink, &path_light_blink, NULL}, 82 | {(coap_method_t)0, NULL, NULL, NULL} 83 | }; 84 | 85 | ////////////////////////////////////////////////////////////////////////// 86 | // Method function: get_well_known_core 87 | ////////////////////////////////////////////////////////////////////////// 88 | static int handle_get_well_known_core(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 89 | { 90 | return coap_make_response(scratch, outpkt, (const uint8_t *)rsp, strlen(rsp), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_APPLICATION_LINKFORMAT); 91 | } 92 | 93 | ////////////////////////////////////////////////////////////////////////// 94 | // Method function: get_light_blink 95 | ////////////////////////////////////////////////////////////////////////// 96 | static int handle_get_light_blink(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 97 | { 98 | return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN); 99 | } 100 | 101 | ////////////////////////////////////////////////////////////////////////// 102 | // Method function: put_light_blink 103 | ////////////////////////////////////////////////////////////////////////// 104 | static int handle_put_light_blink(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 105 | { 106 | int i,nblink; 107 | if (inpkt->payload.len == 0) 108 | { 109 | return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN); 110 | } 111 | if(inpkt->payload.len<9) 112 | { 113 | strcpy(light,(const char *)&inpkt->payload.p[0]); 114 | } 115 | if(numbers_only(light)) { 116 | nblink = atoi(inpkt->payload); 117 | blinkLed(nblink); //Blink Led nblink times using non-blocking timer 118 | } 119 | return coap_make_response(scratch, outpkt, (const uint8_t *)&light[0], inpkt->payload.len, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); 120 | } 121 | 122 | ////////////////////////////////////////////////////////////////////////// 123 | // Method function: get_request 124 | ////////////////////////////////////////////////////////////////////////// 125 | static int handle_get_request(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 126 | { 127 | return coap_make_response(scratch, outpkt, (const uint8_t *)&rqst, strlen(rqst), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN); 128 | } 129 | 130 | ////////////////////////////////////////////////////////////////////////// 131 | // Method function: put_request 132 | ////////////////////////////////////////////////////////////////////////// 133 | static int handle_put_request(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 134 | { 135 | if (inpkt->payload.len == 0) 136 | return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN); 137 | 138 | strncpy(rqst,(const char *)&inpkt->payload.p[0],inpkt->payload.len); 139 | 140 | // Process request & get reply string 141 | ProcessCoAPrequest(rqst,&replystring[0]); 142 | 143 | return coap_make_response(scratch, outpkt, (const uint8_t *)&replystring[0], strlen(replystring), id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); 144 | } 145 | 146 | ////////////////////////////////////////////////////////////////////////// 147 | // Method function: get_light 148 | ////////////////////////////////////////////////////////////////////////// 149 | static int handle_get_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 150 | { 151 | return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CONTENT, COAP_CONTENTTYPE_TEXT_PLAIN); 152 | } 153 | 154 | ////////////////////////////////////////////////////////////////////////// 155 | // Method function: put_light 156 | ////////////////////////////////////////////////////////////////////////// 157 | static int handle_put_light(coap_rw_buffer_t *scratch, const coap_packet_t *inpkt, coap_packet_t *outpkt, uint8_t id_hi, uint8_t id_lo) 158 | { 159 | if (inpkt->payload.len == 0) 160 | return coap_make_response(scratch, outpkt, NULL, 0, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_BAD_REQUEST, COAP_CONTENTTYPE_TEXT_PLAIN); 161 | if (inpkt->payload.p[0] == '1') 162 | { 163 | light[0] = '1'; 164 | digitalWrite(led, HIGH); 165 | //printf("ON\n"); 166 | 167 | return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); 168 | } 169 | else 170 | { 171 | light[0] = '0'; 172 | digitalWrite(led, LOW); 173 | //printf("OFF\n"); 174 | 175 | return coap_make_response(scratch, outpkt, (const uint8_t *)&light, 1, id_hi, id_lo, &inpkt->tok, COAP_RSPCODE_CHANGED, COAP_CONTENTTYPE_TEXT_PLAIN); 176 | } 177 | } 178 | 179 | void build_rsp(void) 180 | { 181 | uint16_t len = rsplen; 182 | const coap_endpoint_t *ep = endpoints; 183 | int i; 184 | 185 | len--; // Null-terminated string 186 | 187 | while(NULL != ep->handler) 188 | { 189 | if (NULL == ep->core_attr) { 190 | ep++; 191 | continue; 192 | } 193 | 194 | if (0 < strlen(rsp)) { 195 | strncat(rsp, ",", len); 196 | len--; 197 | } 198 | 199 | strncat(rsp, "<", len); 200 | len--; 201 | 202 | for (i = 0; i < ep->path->count; i++) { 203 | strncat(rsp, "/", len); 204 | len--; 205 | 206 | strncat(rsp, ep->path->elems[i], len); 207 | len -= strlen(ep->path->elems[i]); 208 | } 209 | 210 | strncat(rsp, ">;", len); 211 | len -= 2; 212 | 213 | strncat(rsp, ep->core_attr, len); 214 | len -= strlen(ep->core_attr); 215 | 216 | ep++; 217 | } 218 | } 219 | 220 | -------------------------------------------------------------------------------- /http_coap_mqtt_server/http_coap_mqtt_server.ino: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | * web_server - example code providing a framework that supports 3 | * either an Arduino library or SDK API web server 4 | * 5 | * created Dec-17, 2015 6 | * by Dave St. Aubin 7 | * 8 | * This example code is in the public domain. 9 | ********************************************************************/ 10 | 11 | #include //http server library 12 | #include //udp library 13 | #include //MQTT server library 14 | #include 15 | #include 16 | #include "coap.h" 17 | #include "sketch.h" 18 | 19 | // Include API-Headers 20 | extern "C" { //SDK functions for Arduino IDE access 21 | #include "ets_sys.h" 22 | #include "os_type.h" 23 | #include "osapi.h" 24 | #include "mem_manager.h" 25 | #include "mem.h" 26 | #include "user_interface.h" 27 | #include "cont.h" 28 | #include "espconn.h" 29 | #include "eagle_soc.h" 30 | #include 31 | //void * pvPortZalloc(int size); 32 | void * pvPortZalloc(int size,char*,int); 33 | } 34 | 35 | /******************************************************** 36 | * Global Variables 37 | ********************************************************/ 38 | const char* ssid = "YOURWIFISSID"; 39 | const char* password = "YOURWIFIPASSWORD"; 40 | const IPAddress ipadd(192,168,0,132); 41 | const IPAddress ipgat(192,168,0,1); 42 | const IPAddress ipsub(255,255,255,0); 43 | 44 | uint8_t packetbuf[UDP_TX_PACKET_MAX_SIZE]; 45 | static uint8_t scratch_raw[32]; 46 | static coap_rw_buffer_t scratch_buf = {scratch_raw, sizeof(scratch_raw)}; 47 | 48 | long lastMsg = 0; 49 | uint32_t state=0; 50 | int initRx=0; 51 | int stoprepub = 0; 52 | int sz,blinkarg[4]; 53 | static int busy=0; 54 | float Ain; 55 | char Ain0[20],Ain1[20],Ain2[20],Ain3[20],Ain4[20],Ain5[20],Ain6[20],Ain7[20]; 56 | bool complete=false; 57 | int lc=0; 58 | 59 | //sdk web server 60 | char *precvbuffer; 61 | static uint32 dat_sumlength = 0; 62 | 63 | /******************************************************** 64 | * Local Function Prototypes 65 | ********************************************************/ 66 | void SdkWebServer_Init(int port); 67 | void SdkWebServer_listen(void *arg); 68 | void SdkWebServer_recv(void *arg, char *pusrdata, unsigned short length); 69 | void SdkWebServer_discon(void *arg); 70 | void SdkWebServer_recon(void *arg, sint8 err); 71 | void SdkWebServer_senddata(void *arg, bool responseOK, char *psend); 72 | bool SdkWebServer_savedata(char *precv, uint16 length); 73 | void SdkWebServer_parse_url_params(char *precv, URL_Param *purl_param); 74 | 75 | void util_printStatus(char * status, int s); 76 | void util_startWIFI(void); 77 | 78 | void jsonEncode(int pos, String * s, String key, String val); 79 | void jsonAdd(String *s, String key,String val); 80 | 81 | void ArduinoWebServer_Init(void); 82 | void ArduinoWebServer_Processor(void); 83 | void ArduinoWebServer_KillClient(WiFiClient client, bool *busy); 84 | 85 | void MqttServer_Init(void); 86 | void MqttServer_reconnect(void); 87 | void MqttServer_callback(char* topic, byte* payload, unsigned int length); 88 | void MqttServer_Processor(void); 89 | 90 | void Server_ProcessRequest(int servertype, char *payload, char *reply); 91 | void Server_ExecuteRequest(int servertype,RQST_Param rparam, String* reply); 92 | 93 | void ReadSensors(int interval); 94 | 95 | void BlinkCallback(int *pArg); 96 | void ProcessCOAPMsg(void); 97 | void udp_send(const uint8_t *buf, int buflen); 98 | 99 | extern "C"{ 100 | void ProcessCoAPrequest(char * rqst,char * replystring); 101 | void blinkLed(int nblink); 102 | } 103 | 104 | /******************************************************** 105 | * Instantiate class objects 106 | ********************************************************/ 107 | #if SVR_TYPE==SVR_HTTP_LIB 108 | WiFiServer server(SVRPORT); //Create Arduino Library web server object 109 | #endif 110 | 111 | WiFiClient espClient; //Create Wifi Client object 112 | WiFiClient httpClient; //Create http server Client object 113 | PubSubClient client(espClient); //Create Mqtt Client object 114 | WiFiUDP udp; //Create UDP instance for CoAP PUT and GET 115 | os_timer_t BlinkLedTimer; //Timer to blink LED 116 | struct espconn *ptrespconn; 117 | 118 | /******************************************************** 119 | * Proces COAPCallback timer callback 120 | * Function: Process COAPMsg(void) 121 | * 122 | * Parameter Description 123 | * --------- --------------------------------------- 124 | * return no return value 125 | ********************************************************/ 126 | void ProcessCOAPMsg(void) { 127 | int rc; 128 | coap_packet_t pkt; 129 | int i; 130 | 131 | yield(); 132 | 133 | if(busy==1) return; 134 | busy=1; 135 | if ((sz = udp.parsePacket()) > 0) 136 | { 137 | 138 | udp.read(packetbuf, sizeof(packetbuf)); 139 | 140 | Serial.println("COAP Recvd Packet:"); 141 | 142 | for (i=0;i1) 254 | { 255 | Serial.print("."); 256 | } 257 | else 258 | { 259 | Serial.println("..."); 260 | } 261 | digitalWrite(LED_IND, HIGH); 262 | blinkarg[1] = 0; 263 | os_timer_arm(&BlinkLedTimer, 500, false); 264 | } 265 | else 266 | { 267 | digitalWrite(LED_IND, LOW); 268 | blinkarg[1] = 1; //start with led on cmd 269 | if(--nblinks!=0) { 270 | --blinkarg[0]; //remaining blinks 271 | os_timer_arm(&BlinkLedTimer, 500, false); 272 | } 273 | } 274 | } 275 | 276 | /******************************************************** 277 | * Send UDP Packet 278 | * Function: udp_send(const uint8_t *buf, int buflen) 279 | * 280 | * Parameter Description 281 | * --------- --------------------------------------- 282 | * *buf pointer to bytes to send 283 | * buflen buffer length 284 | * return no return value 285 | ********************************************************/ 286 | void udp_send(const uint8_t *buf, int buflen) 287 | { 288 | udp.beginPacket(udp.remoteIP(), udp.remotePort()); 289 | while(buflen--) 290 | udp.write(*buf++); 291 | udp.endPacket(); 292 | } 293 | 294 | 295 | /******************************************************** 296 | * SDK API Web Server Initialization 297 | * Function: SdkWebServer_Init(int port) 298 | * 299 | * Parameter Description 300 | * --------- --------------------------------------- 301 | * port http server listen port 302 | * return no return value 303 | ********************************************************/ 304 | void SdkWebServer_Init(int port) { 305 | LOCAL struct espconn esp_conn; 306 | LOCAL esp_tcp esptcp; 307 | //Fill the connection structure, including "listen" port 308 | esp_conn.type = ESPCONN_TCP; 309 | esp_conn.state = ESPCONN_NONE; 310 | esp_conn.proto.tcp = &esptcp; 311 | esp_conn.proto.tcp->local_port = port; 312 | esp_conn.recv_callback = NULL; 313 | esp_conn.sent_callback = NULL; 314 | esp_conn.reverse = NULL; 315 | //Register the connection timeout(0=no timeout) 316 | espconn_regist_time(&esp_conn,0,0); 317 | //Register connection callback 318 | espconn_regist_connectcb(&esp_conn, SdkWebServer_listen); 319 | //Start Listening for connections 320 | espconn_accept(&esp_conn); 321 | Serial.print("Web Server initialized: Type = SDK API\n"); 322 | } 323 | 324 | /******************************************************** 325 | * SDK API Web Server TCP Client Connection Callback 326 | * Function: SdkWebServer_listen(void *arg) 327 | * 328 | * Parameter Description 329 | * --------- --------------------------------------- 330 | * *arg pointer to espconn structure 331 | * return no return value 332 | ********************************************************/ 333 | void SdkWebServer_listen(void *arg) 334 | { 335 | struct espconn *pesp_conn = ( espconn *)arg; 336 | 337 | espconn_regist_recvcb(pesp_conn, SdkWebServer_recv); 338 | espconn_regist_reconcb(pesp_conn, SdkWebServer_recon); 339 | espconn_regist_disconcb(pesp_conn, SdkWebServer_discon); 340 | } 341 | 342 | /******************************************************** 343 | * SDK API Web Server Receive Data Callback 344 | * Function: SdkWebServer_recv(void *arg, char *pusrdata, 345 | * unsigned short length) 346 | * 347 | * Parameter Description 348 | * --------- --------------------------------------- 349 | * *arg pointer to espconn structure 350 | * *pusrdata data received after IP:port 351 | * length data length (bytes) 352 | * return no return value 353 | ********************************************************/ 354 | void SdkWebServer_recv(void *arg, char *pusrdata, unsigned short length) 355 | { 356 | URL_Param *pURL_Param = NULL; 357 | char *pParseBuffer = NULL; 358 | char * pRequest = NULL; 359 | char * pReply = NULL; 360 | 361 | bool parse_flag = false; 362 | 363 | ptrespconn = ( espconn *)arg; 364 | espconn_set_opt(ptrespconn, ESPCONN_REUSEADDR); 365 | 366 | parse_flag = SdkWebServer_savedata(pusrdata, length); 367 | pURL_Param = (URL_Param *)os_zalloc(sizeof(URL_Param)); 368 | 369 | pRequest = (char *)os_zalloc(512); 370 | pReply = (char *)os_zalloc(512); 371 | os_memcpy(pRequest, precvbuffer, length); 372 | 373 | Serial.println(F("-------------------------------------")); 374 | Serial.println(F("HTTP Message Rx: [Code: SDK API]")); 375 | Serial.println(F("-------------------------------------")); 376 | 377 | Server_ProcessRequest(SVR_HTTP_SDK, pRequest, pReply); 378 | 379 | //Clean up the memory 380 | if (precvbuffer != NULL) 381 | { 382 | os_free(precvbuffer); 383 | precvbuffer = NULL; 384 | } 385 | os_free(pURL_Param); 386 | os_free(pRequest); 387 | os_free(pReply); 388 | pURL_Param = NULL; 389 | pRequest=NULL; 390 | pReply=NULL; 391 | } 392 | 393 | /****************************************************************************************** 394 | * Get Request & Process 395 | ******************************************************************************************/ 396 | void Server_ProcessRequest(int servertype, char *payload, char *reply) 397 | { 398 | int i,nblink; 399 | String payld = ""; 400 | RQST_Param rparam; 401 | URL_Param *pURL_Param = NULL; 402 | pURL_Param = (URL_Param *)os_zalloc(sizeof(URL_Param)); 403 | SdkWebServer_parse_url_params(payload, pURL_Param); 404 | unsigned short length = strlen(payload); 405 | char * pRx = NULL; 406 | pRx = (char *)os_zalloc(512); 407 | os_memcpy(pRx, payload, length); 408 | 409 | switch (pURL_Param->Type) { 410 | case GET: 411 | if(os_strcmp(pURL_Param->pParam[0], "request")==0) { 412 | // GetSensors is 1 of 4 requests the server currently supports 413 | if(os_strcmp(pURL_Param->pParVal[0], "GetSensors")==0) { 414 | rparam.request = Get_SENSORS; 415 | rparam.requestval = 0; 416 | // Execute request & get reply string 417 | Server_ExecuteRequest(servertype, rparam, &payld); 418 | } 419 | // LedOn is 2 of 4 requests the server currently supports 420 | else if(os_strcmp(pURL_Param->pParVal[0], "LedOn")==0) { 421 | rparam.request = SET_LED_ON; 422 | rparam.requestval = 0; 423 | // Execute request & get reply string 424 | Server_ExecuteRequest(servertype, rparam, &payld); 425 | } 426 | // LedOff is 3 of 4 requests the server currently supports 427 | else if(os_strcmp(pURL_Param->pParVal[0], "LedOff")==0) { 428 | rparam.request = SET_LED_OFF; 429 | rparam.requestval = 0; 430 | // Execute request & get reply string 431 | Server_ExecuteRequest(servertype, rparam, &payld); 432 | } 433 | // BlinkLed is 4 of 4 requests the server currently supports 434 | else if(os_strcmp(pURL_Param->pParVal[0], "BlinkLed")==0) { 435 | rparam.request = BLINK_LED; 436 | if(os_strcmp(pURL_Param->pParam[1], "nblink")==0) { 437 | rparam.requestval = atoi(pURL_Param->pParVal[1]); 438 | } 439 | else 440 | { 441 | rparam.requestval = 1; 442 | } 443 | // Execute request & get reply string 444 | Server_ExecuteRequest(servertype, rparam, &payld); 445 | } 446 | // Add additional requests here 447 | else //Invalid request 448 | { 449 | rparam.request == INVALID_REQUEST; 450 | payld = "Invalid Request"; 451 | } 452 | // Now send reply 453 | Serial.println(F("-------------------------------------")); 454 | Serial.println(F("Reply Payload:")); 455 | Serial.println(payld); 456 | Serial.println(F("-------------------------------------")); 457 | switch(servertype) 458 | { 459 | case SVR_MQTT: 460 | client.publish(tx_topic, payld.c_str(), false); 461 | break; 462 | case SVR_HTTP_LIB: 463 | httpClient.print(payld); 464 | break; 465 | case SVR_HTTP_SDK: 466 | SdkWebServer_senddata(ptrespconn, true, (char *)payld.c_str()); 467 | break; 468 | case SVR_COAP: //endpoint api returns reply 469 | break; 470 | } 471 | } 472 | break; 473 | 474 | case POST: 475 | Serial.print(F("We have a POST request.\n")); 476 | break; 477 | } 478 | strcpy(reply,(char *)payld.c_str()); 479 | os_free(pURL_Param); 480 | os_free(pRx); 481 | //os_free(payld); 482 | pURL_Param = NULL; 483 | pRx = NULL; 484 | //payld = NULL; 485 | } 486 | 487 | /******************************************************** 488 | * SDK API Web Server TCP Connection Closed Callback 489 | * Function: SdkWebServer_discon(void *arg) 490 | * 491 | * Parameter Description 492 | * --------- --------------------------------------- 493 | * *arg pointer to espconn structure 494 | * return no return value 495 | ********************************************************/ 496 | void SdkWebServer_discon(void *arg) 497 | { 498 | struct espconn *pesp_conn = ( espconn *)arg; 499 | 500 | os_printf("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0], 501 | pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2], 502 | pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port); 503 | } 504 | 505 | /******************************************************** 506 | * SDK API Web Server TCP Disconnect on error Callback 507 | * Function: SdkWebServer_recon(void *arg, sint8 err) 508 | * 509 | * Parameter Description 510 | * --------- --------------------------------------- 511 | * *arg pointer to espconn structure 512 | * err error code 513 | * return no return value 514 | ********************************************************/ 515 | void SdkWebServer_recon(void *arg, sint8 err) 516 | { 517 | struct espconn *pesp_conn = ( espconn *)arg; 518 | 519 | os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0], 520 | pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2], 521 | pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err); 522 | } 523 | 524 | /******************************************************** 525 | * SDK API Web Server send data to connected client 526 | * Function: SdkWebServer_senddata(void *arg, 527 | * bool responseOK, 528 | * char *psend) 529 | * 530 | * Parameter Description 531 | * --------- --------------------------------------- 532 | * *arg pointer to espconn structure 533 | * responseOK reply status 534 | * *psend string to send 535 | * return no return value 536 | ********************************************************/ 537 | void SdkWebServer_senddata(void *arg, bool responseOK, char *psend) 538 | { 539 | uint16 length = 0; 540 | char *pbuf = NULL; 541 | char httphead[256]; 542 | //struct espconn *ptrespconn = ( espconn *)arg; 543 | os_memset(httphead, 0, 256); 544 | 545 | if (responseOK) { 546 | os_sprintf(httphead, 547 | "HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\nAccess-Control-Allow-Origin: *\r\n", 548 | psend ? os_strlen(psend) : 0); 549 | 550 | if (psend) { 551 | os_sprintf(httphead + os_strlen(httphead), 552 | "Content-type: application/json\r\nExpires: Fri, 10 Apr 2015 14:00:00 GMT\r\nPragma: no-cache\r\n\r\n"); 553 | length = os_strlen(httphead) + os_strlen(psend); 554 | pbuf = (char *)os_zalloc(length + 1); 555 | os_memcpy(pbuf, httphead, os_strlen(httphead)); 556 | os_memcpy(pbuf + os_strlen(httphead), psend, os_strlen(psend)); 557 | } else { 558 | os_sprintf(httphead + os_strlen(httphead), "\n"); 559 | length = os_strlen(httphead); 560 | } 561 | } else { 562 | os_sprintf(httphead, "HTTP/1.0 400 BadRequest\r\n\ 563 | Content-Length: 0\r\nServer: lwIP/1.4.0\r\n\n"); 564 | length = os_strlen(httphead); 565 | } 566 | 567 | if (psend) { 568 | espconn_sent(ptrespconn, (uint8 *)pbuf, length); 569 | } else { 570 | espconn_sent(ptrespconn, (uint8 *)httphead, length); 571 | } 572 | 573 | if (pbuf) { 574 | os_free(pbuf); 575 | pbuf = NULL; 576 | } 577 | } 578 | 579 | /******************************************************** 580 | * SDK API Web Server save data from connected client 581 | * Function: bool SdkWebServer_savedata(char *precv, 582 | * uint16 length) 583 | * 584 | * Parameter Description 585 | * --------- --------------------------------------- 586 | * *precv string received 587 | * length string length 588 | * return true if succes ful save 589 | ********************************************************/ 590 | bool SdkWebServer_savedata(char *precv, uint16 length) 591 | { 592 | bool flag = false; 593 | char length_buf[10] = {0}; 594 | char *ptemp = NULL; 595 | char *pdata = NULL; 596 | uint16 headlength = 0; 597 | static uint32 totallength = 0; 598 | 599 | ptemp = (char *)os_strstr(precv, "\r\n\r\n"); 600 | 601 | if (ptemp != NULL) { 602 | length -= ptemp - precv; 603 | length -= 4; 604 | totallength += length; 605 | headlength = ptemp - precv + 4; 606 | pdata = (char *)os_strstr(precv, "Content-Length: "); 607 | 608 | if (pdata != NULL) { 609 | pdata += 16; 610 | precvbuffer = (char *)os_strstr(pdata, "\r\n"); 611 | 612 | if (precvbuffer != NULL) { 613 | os_memcpy(length_buf, pdata, precvbuffer - pdata); 614 | dat_sumlength = atoi(length_buf); 615 | } 616 | } else { 617 | if (totallength != 0x00){ 618 | totallength = 0; 619 | dat_sumlength = 0; 620 | return false; 621 | } 622 | } 623 | if ((dat_sumlength + headlength) >= 1024) { 624 | precvbuffer = (char *)os_zalloc(headlength + 1); 625 | os_memcpy(precvbuffer, precv, headlength + 1); 626 | } else { 627 | precvbuffer = (char *)os_zalloc(dat_sumlength + headlength + 1); 628 | os_memcpy(precvbuffer, precv, os_strlen(precv)); 629 | } 630 | } else { 631 | if (precvbuffer != NULL) { 632 | totallength += length; 633 | os_memcpy(precvbuffer + os_strlen(precvbuffer), precv, length); 634 | } else { 635 | totallength = 0; 636 | dat_sumlength = 0; 637 | return false; 638 | } 639 | } 640 | 641 | if (totallength == dat_sumlength) { 642 | totallength = 0; 643 | dat_sumlength = 0; 644 | return true; 645 | } else { 646 | return false; 647 | } 648 | } 649 | 650 | /******************************************************** 651 | * SDK API Web Server parse received parameters 652 | * Function: void SdkWebServer_ parse_url_params( 653 | * char *precv, URL_Param *purl_param) 654 | * 655 | * Parameter Description 656 | * --------- --------------------------------------- 657 | * *precv string received 658 | * *purl_param parsed parameter structure 659 | * return no return value 660 | ********************************************************/ 661 | void SdkWebServer_parse_url_params(char *precv, URL_Param *purl_param) 662 | { 663 | char *str = NULL; 664 | uint8 length = 0; 665 | char *pbuffer = NULL; 666 | char *pbufer = NULL; 667 | char *pget = NULL; 668 | char *ppost = NULL; 669 | int ipar=0; 670 | char *szStart = NULL; 671 | 672 | if (purl_param == NULL || precv == NULL) { 673 | return; 674 | } 675 | 676 | szStart = (char *)os_zalloc(5); 677 | os_memcpy(szStart, precv, 4); 678 | szStart[4]=(char)'\0'; 679 | 680 | pget = (char *)os_strstr(szStart, "GET "); 681 | ppost = (char *)os_strstr(szStart, "POST"); 682 | //Check if we only have request string 683 | if( (precv[0]=='/')||(pget != NULL)||(ppost != NULL) ) 684 | { 685 | length = strlen(precv); 686 | pbufer = (char *)os_zalloc(length + 1); 687 | pbuffer = pbufer; 688 | os_memcpy(pbuffer, precv, length); 689 | os_memset(purl_param->pParam, 0, URLSize*URLSize); 690 | os_memset(purl_param->pParVal, 0, URLSize*URLSize); 691 | purl_param->Type = GET; 692 | if (pget != NULL) 693 | { 694 | purl_param->Type = GET; 695 | pbuffer += 4; 696 | } 697 | else if (ppost != NULL) 698 | { 699 | purl_param->Type = POST; 700 | pbuffer += 5; 701 | } 702 | } 703 | else 704 | { 705 | //pbuffer = (char *)os_strstr(precv, "Host:"); 706 | pbuffer = (char *)os_strstr(precv, "Accept:"); 707 | 708 | if (pbuffer != NULL) { 709 | length = pbuffer - precv; 710 | pbufer = (char *)os_zalloc(length + 1); 711 | pbuffer = pbufer; 712 | os_memcpy(pbuffer, precv, length); 713 | os_memset(purl_param->pParam, 0, URLSize*URLSize); 714 | os_memset(purl_param->pParVal, 0, URLSize*URLSize); 715 | 716 | if (os_strncmp(pbuffer, "GET /favicon.ico", 16) == 0) { 717 | purl_param->Type = GET_FAVICON; 718 | os_free(pbufer); 719 | os_free(szStart); 720 | return; 721 | } else if (os_strncmp(pbuffer, "GET ", 4) == 0) { 722 | purl_param->Type = GET; 723 | pbuffer += 4; 724 | } else if (os_strncmp(pbuffer, "POST ", 5) == 0) { 725 | purl_param->Type = POST; 726 | pbuffer += 5; 727 | } 728 | } 729 | else 730 | { 731 | return; 732 | } 733 | } 734 | pbuffer ++; 735 | str = (char *)os_strstr(pbuffer, "?"); 736 | 737 | if (str != NULL) { 738 | str ++; 739 | do { 740 | pbuffer = (char *)os_strstr(str, "="); 741 | length = pbuffer - str; 742 | os_memcpy(purl_param->pParam[ipar], str, length); 743 | str = (char *)os_strstr(++pbuffer, "&"); 744 | if(str != NULL) { 745 | length = str - pbuffer; 746 | os_memcpy(purl_param->pParVal[ipar++], pbuffer, length); 747 | str++; 748 | } 749 | else { 750 | str = (char *)os_strstr(pbuffer, " HTTP"); 751 | if(str != NULL) { 752 | length = str - pbuffer; 753 | os_memcpy(purl_param->pParVal[ipar++], pbuffer, length); 754 | str = NULL; 755 | } 756 | else { 757 | os_memcpy(purl_param->pParVal[ipar++], pbuffer, strlen(pbuffer)); 758 | } 759 | } 760 | } 761 | while (str!=NULL); 762 | } 763 | purl_param->nPar = ipar; 764 | 765 | os_free(pbufer); 766 | os_free(szStart); 767 | } 768 | 769 | 770 | /******************************************************** 771 | * print status to serial port 772 | * Function: util_printStatus(char * status, int s) 773 | * 774 | * Parameter Description 775 | * --------- --------------------------------------- 776 | * *status status string 777 | * s status code 778 | * return no return value 779 | ********************************************************/ 780 | 781 | void util_printStatus(char * status, int s) { 782 | Serial.print(system_get_free_heap_size()); 783 | delay(100); 784 | Serial.print(" "); 785 | delay(100); 786 | Serial.print(millis()/1000); 787 | delay(100); 788 | Serial.print(" "); 789 | delay(100); 790 | if(s>=0) Serial.print(s); 791 | else Serial.print(""); 792 | delay(100); 793 | Serial.print(" "); 794 | delay(100); 795 | Serial.println(status); 796 | // } 797 | delay(100); 798 | } 799 | 800 | /******************************************************** 801 | * connect to local Wifi 802 | * Function: util_startWIFI(void) 803 | * 804 | * Parameter Description 805 | * --------- --------------------------------------- 806 | * return no return value 807 | ********************************************************/ 808 | void util_startWIFI(void) { 809 | //connect wifi if not connected 810 | if (WiFi.status() != WL_CONNECTED) 811 | { 812 | delay(1); 813 | //set IP if not correct 814 | IPAddress ip = WiFi.localIP(); 815 | if( ip!= ipadd) { 816 | WiFi.config(ipadd, ipgat, ipsub); //dsa added 12.04.2015 817 | Serial.println(); 818 | delay(10); 819 | Serial.print("ESP8266 IP:"); 820 | delay(10); 821 | Serial.println(ip); 822 | delay(10); 823 | Serial.print("Fixed IP:"); 824 | delay(10); 825 | Serial.println(ipadd); 826 | delay(10); 827 | Serial.print("IP now set to: "); 828 | delay(10); 829 | Serial.println(WiFi.localIP()); 830 | delay(10); 831 | } 832 | // Connect to WiFi network 833 | Serial.println(); 834 | delay(10); 835 | Serial.println(); 836 | delay(10); 837 | Serial.print("Connecting to "); 838 | delay(10); 839 | Serial.println(ssid); 840 | delay(10); 841 | WiFi.begin(ssid, password); 842 | 843 | while (WiFi.status() != WL_CONNECTED) { 844 | Serial.print("."); 845 | delay(500); 846 | } 847 | Serial.println(""); 848 | Serial.println("WiFi connected"); 849 | 850 | // Print the IP addres 851 | Serial.print("ESP8266 IP: "); 852 | Serial.println(WiFi.localIP()); 853 | 854 | Serial.print("ESP8266 WebServer Port: "); 855 | Serial.println(SVRPORT); 856 | delay(300); 857 | 858 | udp.begin(COAPPORT); 859 | coap_setup(); 860 | endpoint_setup(); 861 | } 862 | } 863 | 864 | /******************************************************** 865 | * Start Arduino library based web server 866 | * Function: ArduinoWebServer_Init(void) 867 | * 868 | * Parameter Description 869 | * --------- --------------------------------------- 870 | * return no return value 871 | ********************************************************/ 872 | #if SVR_TYPE==SVR_HTTP_LIB 873 | void ArduinoWebServer_Init(void) { 874 | server.begin(); 875 | Serial.print(F("Web Server initialized: Type = Arduino library\n")); 876 | } 877 | #endif 878 | 879 | /******************************************************** 880 | * terminate TCP client connection 881 | * Function: ArduinoWebServer_KillClient(WiFiClient client, bool *busy) 882 | * 883 | * Parameter Description 884 | * --------- --------------------------------------- 885 | * client Wifi client object 886 | * busy busy flag 887 | * return no return value 888 | ********************************************************/ 889 | void ArduinoWebServer_KillClient(WiFiClient client, bool *busy) { 890 | lc=0; 891 | delay(1); 892 | client.flush(); 893 | client.stop(); 894 | complete=false; 895 | *busy = false; 896 | } 897 | 898 | /******************************************************** 899 | * Proces http GET request using Arduino library 900 | * Function: ArduinoWebServer_Proces or(void) 901 | * 902 | * Parameter Description 903 | * --------- --------------------------------------- 904 | * return no return value 905 | ********************************************************/ 906 | #if SVR_TYPE==SVR_HTTP_LIB 907 | void ArduinoWebServer_Processor(void) { 908 | static bool busy=false; 909 | static int timeout_busy=0; 910 | String payld=""; 911 | char pReply[256]; 912 | 913 | ///String *payld=NULL; 914 | //char *pReply=NULL; 915 | //payld = (String *)os_zalloc(256); 916 | //pReply = (char *)os_zalloc(512); 917 | 918 | 919 | //connect wifi if not connected 920 | if (WiFi.status() != WL_CONNECTED) { 921 | delay(1); 922 | util_startWIFI(); 923 | return; 924 | } 925 | //return if busy 926 | if(busy) { 927 | delay(1); 928 | if(timeout_busy++ >10000) { 929 | util_printStatus((char *)F(" Status: Busy timeout-resetting.."),-1); 930 | ESP.reset(); 931 | busy = false; 932 | } 933 | return; 934 | } 935 | else { 936 | busy = true; 937 | timeout_busy=0; 938 | } 939 | delay(1); 940 | 941 | // Check if a client has connected 942 | httpClient = server.available(); 943 | if (!httpClient) { 944 | busy = false; 945 | return; 946 | } 947 | // Wait until the client sends some data 948 | while((!httpClient.available())&&(timeout_busy++<5000)){ 949 | delay(1); 950 | if(complete==true) { 951 | ArduinoWebServer_KillClient(httpClient, &busy); 952 | return; 953 | } 954 | } 955 | //kill client if timeout 956 | if(timeout_busy>=5000) { 957 | ArduinoWebServer_KillClient(httpClient, &busy); 958 | return; 959 | } 960 | 961 | complete=false; 962 | ESP.wdtFeed(); 963 | 964 | // Read the first line of the request 965 | payld = httpClient.readStringUntil('\r'); 966 | httpClient.flush(); 967 | if (payld.indexOf("/favicon.ico") != -1) { 968 | httpClient.stop(); 969 | complete=true; 970 | busy = false; 971 | //os_free(payld); 972 | //os_free(pReply); 973 | return; 974 | } 975 | Serial.println(F("-------------------------------------")); 976 | Serial.println(F("HTTP Message Rx: [Code: Arduino LIB]")); 977 | Serial.println(F("-------------------------------------")); 978 | 979 | httpClient.flush(); 980 | 981 | Server_ProcessRequest(SVR_HTTP_LIB, (char*)payld.c_str(),(char*)pReply); 982 | 983 | yield(); 984 | 985 | delay(150); 986 | complete=true; 987 | busy = false; 988 | ESP.wdtFeed(); 989 | ArduinoWebServer_KillClient(httpClient, &busy); 990 | //os_free(payld); 991 | //os_free(pReply); 992 | } 993 | #endif 994 | 995 | /******************************************************** 996 | * Read 1 sensor each time function is called 997 | * Current sensors: ESP8266 ADC with 8-1 MUX input 998 | * Function: void ReadSensors(int interval) 999 | * 1000 | * Parameter Description 1001 | * --------- --------------------------------------- 1002 | * interval milliseconds (minimum) between reads 1003 | * return no return value 1004 | ********************************************************/ 1005 | void ReadSensors(int interval) { 1006 | yield(); 1007 | long now = millis(); 1008 | if (now - lastMsg > interval) { // Read 1 sensor every "interval" milliseconds or longer 1009 | lastMsg = now; 1010 | } 1011 | else { 1012 | return; 1013 | } 1014 | switch(state++) { 1015 | case 0: 1016 | //Set 8-1 amux to position 0 1017 | digitalWrite(AMUXSEL0, 0); 1018 | digitalWrite(AMUXSEL1, 0); 1019 | digitalWrite(AMUXSEL2, 0); 1020 | delay(100); 1021 | //Read analog input 1022 | Ain = (float) analogRead(A0); 1023 | ftoa(Ain,Ain0, 2); 1024 | break; 1025 | case 1: 1026 | //Set 8-1 amux to position 1 1027 | digitalWrite(AMUXSEL0, 1); 1028 | digitalWrite(AMUXSEL1, 0); 1029 | digitalWrite(AMUXSEL2, 0); 1030 | delay(100); 1031 | //Read analog input 1032 | Ain = (float) analogRead(A0); 1033 | ftoa(Ain,Ain1, 2); 1034 | break; 1035 | case 2: 1036 | //Set 8-1 amux to position 2 1037 | digitalWrite(AMUXSEL0, 0); 1038 | digitalWrite(AMUXSEL1, 1); 1039 | digitalWrite(AMUXSEL2, 0); 1040 | delay(100); 1041 | //Read analog input 1042 | Ain = (float) analogRead(A0); 1043 | ftoa(Ain,Ain2, 2); 1044 | break; 1045 | case 3: 1046 | //Set 8-1 amux to position 3 1047 | digitalWrite(AMUXSEL0, 1); 1048 | digitalWrite(AMUXSEL1, 1); 1049 | digitalWrite(AMUXSEL2, 0); 1050 | delay(100); 1051 | //Read analog input 1052 | Ain = (float) analogRead(A0); 1053 | ftoa(Ain,Ain3, 2); 1054 | break; 1055 | case 4: 1056 | //Set 8-1 amux to position 4 1057 | digitalWrite(AMUXSEL0, 0); 1058 | digitalWrite(AMUXSEL1, 0); 1059 | digitalWrite(AMUXSEL2, 1); 1060 | delay(100); 1061 | //Read analog input 1062 | Ain = (float) analogRead(A0); 1063 | ftoa(Ain,Ain4, 2); 1064 | break; 1065 | case 5: 1066 | //Set 8-1 amux to position 5 1067 | digitalWrite(AMUXSEL0, 1); 1068 | digitalWrite(AMUXSEL1, 0); 1069 | digitalWrite(AMUXSEL2, 1); 1070 | delay(100); 1071 | //Read analog input 1072 | Ain = (float) analogRead(A0); 1073 | ftoa(Ain,Ain5, 2); 1074 | break; 1075 | case 6: 1076 | //Set 8-1 amux to position 6 1077 | digitalWrite(AMUXSEL0, 0); 1078 | digitalWrite(AMUXSEL1, 1); 1079 | digitalWrite(AMUXSEL2, 1); 1080 | delay(100); 1081 | //Read analog input 1082 | Ain = (float) analogRead(A0); 1083 | ftoa(Ain,Ain6, 2); 1084 | break; 1085 | case 7: 1086 | //Set 8-1 amux to position 7 1087 | digitalWrite(AMUXSEL0, 1); 1088 | digitalWrite(AMUXSEL1, 1); 1089 | digitalWrite(AMUXSEL2, 1); 1090 | delay(100); 1091 | //Read analog input 1092 | Ain = (float) analogRead(A0); 1093 | ftoa(Ain,Ain7, 2); 1094 | state = 0; 1095 | break; 1096 | default: 1097 | break; 1098 | } 1099 | ESP.wdtFeed(); 1100 | yield(); 1101 | } 1102 | 1103 | /******************************************************** 1104 | * add key/value entry into json string 1105 | * Function: jsonAdd( 1106 | * String * s, 1107 | * String key, 1108 | * String val) 1109 | * 1110 | * Parameter Description 1111 | * --------- --------------------------------------- 1112 | * *s pointer to current json string 1113 | * key this json string key 1114 | * val this json string value 1115 | * return no return value 1116 | ********************************************************/ 1117 | void jsonAdd(String *s, String key,String val) { 1118 | *s += '"' + key + '"' + ":" + '"' + val + '"'; 1119 | } 1120 | 1121 | /******************************************************** 1122 | * encode key/value entry into json string 1123 | * Function: jsonEncode(int pos, 1124 | * String * s, 1125 | * String key, 1126 | * String val) 1127 | * 1128 | * Parameter Description 1129 | * --------- --------------------------------------- 1130 | * pos position of this json entry 1131 | * *s pointer to current json string 1132 | * key this json string key 1133 | * val this json string value 1134 | * return no return value 1135 | ********************************************************/ 1136 | void jsonEncode(int pos, String * s, String key, String val) { 1137 | switch (pos) { 1138 | case ONEJSON: 1139 | case FIRSTJSON: 1140 | *s += "{\r\n"; 1141 | jsonAdd(s,key,val); 1142 | *s+= (pos==ONEJSON) ? "\r\n}" : ",\r\n"; 1143 | break; 1144 | case NEXTJSON: 1145 | jsonAdd(s,key,val); 1146 | *s+= ",\r\n"; 1147 | break; 1148 | case LASTJSON: 1149 | jsonAdd(s,key,val); 1150 | *s+= "\r\n}"; 1151 | break; 1152 | } 1153 | } 1154 | 1155 | /******************************************************** 1156 | * Create request reply string to request 1157 | * Function: Server_ExecuteRequest(int servertype, int request, int requestval) 1158 | * 1159 | * Parameter Description 1160 | * --------- --------------------------------------- 1161 | * servertype server type (SDK or LIB) 1162 | * request request enumberation 1163 | * requestval value as ociated with request - such as value to set 1164 | * return reply string 1165 | ********************************************************/ 1166 | void Server_ExecuteRequest(int servertype, RQST_Param rparam, String* s) { 1167 | String v = ""; 1168 | if(servertype == SVR_HTTP_LIB) { 1169 | // Prepare Response header 1170 | *s = "HTTP/1.1 200 OK\r\n"; 1171 | *s += "Access-Control-Allow-Origin: *\r\n"; 1172 | ESP.wdtFeed(); 1173 | } 1174 | switch (rparam.request) { 1175 | case SET_LED_OFF: 1176 | case SET_LED_ON: 1177 | // Set GPIOn according to the request 1178 | digitalWrite(LED_IND , rparam.request); //SET_LED_OFF=0.SET_LED_ON=1 1179 | // Prepare the response for GPIO state 1180 | switch(servertype) { 1181 | case SVR_HTTP_LIB: 1182 | *s += "Content-Type: text/html\r\n\r\n"; 1183 | *s += "\r\nLED is now "; 1184 | *s += (rparam.request)?"ON":"OFF"; 1185 | *s += "\n"; 1186 | break; 1187 | case SVR_COAP: 1188 | case SVR_MQTT: 1189 | case SVR_HTTP_SDK: 1190 | *s += "LED is now "; 1191 | *s += (rparam.request)?"ON":"OFF"; 1192 | *s += "\n"; 1193 | break; 1194 | } 1195 | break; 1196 | case BLINK_LED: 1197 | blinkLed(rparam.requestval); //Blink Led requestval times using non-blocking timer 1198 | // Prepare the response for LED Blinking state 1199 | switch(servertype) { 1200 | case SVR_HTTP_LIB: 1201 | *s += "Content-Type: text/html\r\n\r\n"; 1202 | *s += "\r\nLED is now blinking "; 1203 | *s += rparam.requestval; 1204 | *s += " times."; 1205 | *s += "\n"; 1206 | break; 1207 | case SVR_COAP: 1208 | case SVR_MQTT: 1209 | case SVR_HTTP_SDK: 1210 | *s += "LED is now blinking "; 1211 | *s += rparam.requestval; 1212 | *s += " times."; 1213 | *s += "\n"; 1214 | break; 1215 | } 1216 | break; 1217 | case Get_SENSORS: 1218 | //Create JSON return string 1219 | if(servertype == SVR_HTTP_LIB) { 1220 | *s += "Content-Type: application/json\r\n\r\n"; 1221 | } 1222 | jsonEncode(FIRSTJSON,s ,"Ain0", Ain0); 1223 | jsonEncode(NEXTJSON,s ,"Ain1", Ain1); 1224 | jsonEncode(NEXTJSON,s ,"Ain2", Ain2); 1225 | jsonEncode(NEXTJSON,s ,"Ain3", Ain3); 1226 | jsonEncode(NEXTJSON,s ,"Ain4", Ain4); 1227 | jsonEncode(NEXTJSON,s ,"Ain5", Ain5); 1228 | jsonEncode(NEXTJSON,s ,"Ain6", Ain6); 1229 | jsonEncode(NEXTJSON,s ,"Ain7", Ain7); 1230 | v = system_get_free_heap_size(); 1231 | jsonEncode(NEXTJSON,s ,"SYS_Heap", v); 1232 | v = millis()/1000; 1233 | jsonEncode(LASTJSON,s ,"SYS_Time", v); 1234 | break; 1235 | case INVALID_REQUEST: 1236 | default: 1237 | switch(servertype) 1238 | { 1239 | case SVR_HTTP_LIB: 1240 | httpClient.stop(); 1241 | complete=true; 1242 | busy = false; 1243 | httpClient.flush(); 1244 | break; 1245 | case SVR_COAP: 1246 | case SVR_MQTT: 1247 | case SVR_HTTP_SDK: 1248 | default: 1249 | break; 1250 | } 1251 | *s += "Invalid Request\n"; 1252 | break; 1253 | } 1254 | //return s ; 1255 | } 1256 | 1257 | 1258 | /******************************************************** 1259 | * Connect to MQTT broker - then subscribe to server topic 1260 | * Function: MqttServer_reconnect(void) 1261 | * 1262 | * Parameter Description 1263 | * --------- --------------------------------------- 1264 | * return no return value 1265 | ********************************************************/ 1266 | void MqttServer_reconnect(void) { 1267 | // Loop until we're reconnected 1268 | while (!client.connected()) { 1269 | Serial.print("Attempting MQTT connection..."); 1270 | // Connect to MQTT Server 1271 | if (client.connect("Test4MyMQTT")) { 1272 | // Succes ful connection mes age & subscribe 1273 | Serial.println("connected"); 1274 | client.subscribe(rx_topic); 1275 | } else { 1276 | // Failed to connect mes age 1277 | Serial.print("failed, rc="); 1278 | Serial.print(client.state()); 1279 | Serial.println(" try again in 5 seconds"); 1280 | // Wait 5 seconds before retrying 1281 | delay(5000); 1282 | } 1283 | } 1284 | } 1285 | /******************************************************** 1286 | * MQTT server topic callback 1287 | * Function: MqttServer_callback(char* topic, 1288 | * byte* payload, 1289 | * unsigned int length) 1290 | * 1291 | * Parameter Description 1292 | * --------- --------------------------------------- 1293 | * topic topic string 1294 | * payload value received 1295 | * length value length (bytes) 1296 | * return no return value 1297 | ********************************************************/ 1298 | void MqttServer_callback(char* topic, byte* payload, unsigned int length) 1299 | { 1300 | String payld = ""; 1301 | //String* payld = NULL; 1302 | char* pReply = NULL; 1303 | RQST_Param rparam; 1304 | pReply = (char *)os_zalloc(512); 1305 | //payld = (String *)os_zalloc(256); 1306 | //Msg rx message 1307 | Serial.println(F("-------------------------------------")); 1308 | Serial.print(F("MQTT Message Rx: topic[")); 1309 | Serial.print(topic); 1310 | Serial.print("] \n"); 1311 | Serial.println(F("-------------------------------------")); 1312 | // Extract payload 1313 | for (int i = 0; i < length; i++) { 1314 | payld = payld + String((char)payload[i]); 1315 | } 1316 | // Ignore if not Server Request 1317 | if(String(topic) != rx_topic) { 1318 | os_free(pReply); 1319 | //os_free(payld); 1320 | return; 1321 | } 1322 | 1323 | Server_ProcessRequest(SVR_MQTT, (char*)payld.c_str(),(char*)pReply); 1324 | os_free(pReply); 1325 | //os_free(payld); 1326 | } 1327 | 1328 | /******************************************************** 1329 | * MQTT loop() service 1330 | * Function: MqttServer_Processor(void) 1331 | * 1332 | * Parameter Description 1333 | * --------- --------------------------------------- 1334 | * return no return value 1335 | ********************************************************/ 1336 | void MqttServer_Processor(void) { 1337 | yield(); 1338 | if (!client.connected()) { 1339 | MqttServer_reconnect(); 1340 | } 1341 | client.loop(); 1342 | yield(); 1343 | } 1344 | 1345 | /******************************************************** 1346 | * Initialize MQTT Broker Parameters 1347 | * Function: MqttServer_Init(void) 1348 | * 1349 | * Parameter Description 1350 | * --------- --------------------------------------- 1351 | * return no return value 1352 | ********************************************************/ 1353 | void MqttServer_Init(void) { 1354 | client.setServer(mqtt_server, 1883); // Start Mqtt server 1355 | client.setCallback(MqttServer_callback); 1356 | } 1357 | 1358 | /******************************************************** 1359 | * Sketch setup() function: Executes 1 time 1360 | * Function: setup(void) 1361 | * 1362 | * Parameter Description 1363 | * --------- --------------------------------------- 1364 | * return no return value 1365 | ********************************************************/ 1366 | void setup() { 1367 | Serial.begin(SERBAUD); // Initialize serial port 1368 | util_startWIFI(); // Connect to local Wifi 1369 | 1370 | #if SVR_TYPE==SVR_HTTP_LIB 1371 | ArduinoWebServer_Init(); // Start Arduino library based web server 1372 | #endif 1373 | #if SVR_TYPE==SVR_HTTP_SDK 1374 | SdkWebServer_Init(SVRPORT); // Start SDK based web server 1375 | #endif 1376 | 1377 | #if MQTT_SVR_ENABLE==1 1378 | MqttServer_Init(); // Start MQTT Server 1379 | #endif 1380 | 1381 | pinMode(LED_IND , OUTPUT); // Set Indicator LED as output 1382 | digitalWrite(LED_IND, 0); // Turn LED off 1383 | } 1384 | 1385 | /******************************************************** 1386 | * Sketch loop() function: Executes repeatedly 1387 | * Function: loop(void) 1388 | * 1389 | * Parameter Description 1390 | * --------- --------------------------------------- 1391 | * return no return value 1392 | ********************************************************/ 1393 | void loop() { 1394 | util_startWIFI(); // Connect wifi if connection dropped 1395 | 1396 | #if MQTT_SVR_ENABLE==1 1397 | MqttServer_Processor(); // Service MQTT 1398 | #endif 1399 | 1400 | #if SVR_TYPE==SVR_HTTP_LIB 1401 | ArduinoWebServer_Processor(); // Service Web Server 1402 | #endif 1403 | 1404 | ProcessCOAPMsg(); // Service CoAP Messages 1405 | 1406 | ReadSensors(2500); // Read 1 sensor every 2.5 seconds or longer 1407 | } 1408 | 1409 | -------------------------------------------------------------------------------- /http_coap_mqtt_server/sketch.h: -------------------------------------------------------------------------------- 1 | #ifndef SKETCH_H 2 | #define SKETCH_H 1 3 | 4 | 5 | //Server actions 6 | #define SET_LED_OFF 0 7 | #define SET_LED_ON 1 8 | #define BLINK_LED 2 9 | #define Get_SENSORS 3 10 | #define INVALID_REQUEST 99 11 | 12 | //Server Type 13 | #define SVR_MQTT 0 14 | #define SVR_HTTP_LIB 1 15 | #define SVR_HTTP_SDK 2 16 | #define SVR_COAP 3 17 | 18 | //Set this to desired server type (see above 4 types) 19 | #define SVR_TYPE SVR_HTTP_SDK 20 | #define MQTT_SVR_ENABLE 1 21 | 22 | #define SERBAUD 115200 23 | #define SVRPORT 9701 24 | #define COAPPORT 5683 25 | 26 | //JSON string type 27 | #define ONEJSON 0 28 | #define FIRSTJSON 1 29 | #define NEXTJSON 2 30 | #define LASTJSON 3 31 | 32 | //GPIO pin as ignments 33 | #define AMUXSEL0 14 // AMUX Selector 0 34 | #define AMUXSEL1 12 // AMUX Selector 1 35 | #define AMUXSEL2 13 // AMUX Selector 2 36 | #define LED_IND 16 // LED used for initial code testing (not included in final hardware design) 37 | 38 | #define URLSize 10 39 | #define DATASize 10 40 | 41 | #define mqtt_server "test.mosquitto.org" 42 | #define mqtt_user "your_username" 43 | #define mqtt_password "your_pas word" 44 | 45 | #define rx_topic "MyMqttSvrRqst" 46 | #define tx_topic "MyMqttSvrRply" 47 | 48 | typedef struct RQST_Param { 49 | int request; 50 | int requestval; 51 | } RQST_Param; 52 | 53 | typedef enum ProtocolType { 54 | GET = 0, 55 | POST, 56 | GET_FAVICON 57 | } ProtocolType; 58 | 59 | typedef struct URL_Param { 60 | enum ProtocolType Type; 61 | char pParam[URLSize][URLSize]; 62 | char pParVal[URLSize][URLSize]; 63 | int nPar; 64 | } URL_Param; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /webserver/lwipopts.h: -------------------------------------------------------------------------------- 1 | #ifndef __LWIPOPTS_H__ 2 | #define __LWIPOPTS_H__ 3 | 4 | #include "mem_manager.h" 5 | #include "eagle_soc.h" 6 | 7 | // Don't change: 8 | #define NO_SYS 1 9 | #define NO_SYS_NO_TIMERS 0 10 | #define LWIP_NETIF_TX_SINGLE_PBUF 1 11 | #define LWIP_ESP 1 12 | #define PBUF_RSV_FOR_WLAN 1 13 | #define ICACHE_FLASH 1 14 | #define EBUF_LWIP 1 15 | 16 | // Leave unchanged unless you really know what you're doing: 17 | #define MEM_ALIGNMENT 4 18 | #define TCP_MSS 1460 19 | #define TCP_SND_BUF (2*TCP_MSS) 20 | #define MEMP_MEM_MALLOC 1 21 | #define MEM_LIBC_MALLOC 1 22 | 23 | #define MEMP_NUM_TCP_PCB (*((volatile uint32*)0x600011FC)) 24 | #define LWIP_RAND() rand() 25 | 26 | #if MEM_LIBC_MALLOC 27 | #define mem_free vPortFree 28 | #define mem_malloc pvPortMalloc 29 | #define mem_calloc pvPortCalloc 30 | #endif 31 | 32 | #define MEMCPY(dst,src,len) os_memcpy(dst,src,len) 33 | #define SMEMCPY(dst,src,len) os_memcpy(dst,src,len) 34 | 35 | static inline uint32_t sys_now(void) 36 | { 37 | return NOW()/(TIMER_CLK_FREQ/1000); 38 | } 39 | 40 | // For espconn: 41 | //#define os_malloc(s) pvPortMalloc((s)) 42 | //#define os_realloc(p, s) pvPortRealloc((p), (s)) 43 | //#define os_zalloc(s) pvPortZalloc((s)) 44 | //#define os_free(p) vPortFree((p)) 45 | 46 | // Required: 47 | #define LWIP_DHCP 1 48 | #define LWIP_DNS 1 49 | 50 | // Optional: 51 | #define LWIP_IGMP 1 52 | #define LWIP_NETIF_LOOPBACK 0 53 | #define LWIP_HAVE_LOOPIF 0 54 | 55 | // Tweakable: 56 | #define ESP_TIMEWAIT_THRESHOLD 10000 57 | 58 | #define TCP_TMR_INTERVAL 125 59 | #define TCP_KEEPIDLE_DEFAULT 3000 60 | #define TCP_KEEPINTVL_DEFAULT 1000 61 | #define TCP_KEEPCNT_DEFAULT 3 62 | 63 | #define LWIP_NETCONN 0 64 | #define LWIP_SOCKET 0 65 | #define MEMP_NUM_SYS_TIMEOUT 8 66 | 67 | #define TCP_LOCAL_PORT_RANGE_START 0x1000 68 | #define TCP_LOCAL_PORT_RANGE_END 0x7fff 69 | #define UDP_LOCAL_PORT_RANGE_START 0x1000 70 | #define UDP_LOCAL_PORT_RANGE_END 0x7fff 71 | 72 | #define ARP_QUEUEING 1 73 | #define ETHARP_TRUST_IP_MAC 1 74 | #define IP_FRAG 0 75 | #define IP_REASSEMBLY 0 76 | #define IP_FRAG_USES_STATIC_BUF 1 77 | #define TCP_QUEUE_OOSEQ 0 78 | #define LWIP_TCP_KEEPALIVE 1 79 | #define LWIP_STATS 0 80 | 81 | #ifdef LWIP_OUR_IF 82 | #define LWIP_NETIF_HOSTNAME 1 // our eagle_lwip_if.o required 83 | #define LWIP_NETIF_HOSTNAME_PREFIX "esp8266-" 84 | #endif 85 | 86 | // #define LWIP_DEBUG 87 | // #define IP_DEBUG LWIP_DBG_ON 88 | 89 | #endif /* __LWIP_OPT_H__ */ 90 | -------------------------------------------------------------------------------- /webserver/mem_manager.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/internetofhomethings/ESP8266-Triple-Server/dbd425081586f24c5374c0d6ecdf71ffe2f6cae7/webserver/mem_manager.h -------------------------------------------------------------------------------- /webserver/user_webserver.h: -------------------------------------------------------------------------------- 1 | #ifndef __USER_WEBSERVER_H__ 2 | #define __USER_WEBSERVER_H__ 3 | 4 | #define SERVER_PORT 9703 5 | #define SERVER_SSL_PORT 443 6 | 7 | #define URLSize 10 8 | #define DATASize 10 9 | 10 | typedef enum Result_Resp { 11 | RespFail = 0, 12 | RespSuc, 13 | } Result_Resp; 14 | 15 | typedef enum ProtocolType { 16 | GET = 0, 17 | POST, 18 | GET_FAVICON 19 | } ProtocolType; 20 | 21 | typedef enum _ParmType { 22 | SWITCH_STATUS = 0, 23 | INFOMATION, 24 | WIFI, 25 | SCAN, 26 | REBOOT, 27 | DEEP_SLEEP, 28 | LIGHT_STATUS, 29 | CONNECT_STATUS, 30 | USER_BIN, 31 | GET_SENSORS 32 | } ParmType; 33 | 34 | typedef struct DATA_Sensors { 35 | char tDht11[DATASize]; 36 | char hDht11[DATASize]; 37 | char tBmp085[DATASize]; 38 | char pBmp085[DATASize]; 39 | char aBmp085[DATASize]; 40 | char t1Ds18b20[DATASize]; 41 | char t2Ds18b20[DATASize]; 42 | } DATA_Sensors; 43 | 44 | typedef struct DATA_System { 45 | char freeheap[DATASize]; 46 | char systime[DATASize]; 47 | char loopcnt[DATASize]; 48 | char wifimode[DATASize]; 49 | char wifistatus[DATASize]; 50 | char wifireconnects[DATASize]; 51 | } DATA_System; 52 | 53 | typedef struct URL_Frame { 54 | enum ProtocolType Type; 55 | char pSelect[URLSize]; 56 | char pCommand[URLSize]; 57 | char pFilename[URLSize]; 58 | } URL_Frame; 59 | 60 | typedef struct URL_Param { 61 | enum ProtocolType Type; 62 | char pParam[URLSize][URLSize]; 63 | char pParVal[URLSize][URLSize]; 64 | int nPar; 65 | } URL_Param; 66 | 67 | typedef struct _rst_parm { 68 | ParmType parmtype; 69 | struct espconn *pespconn; 70 | } rst_parm; 71 | 72 | void user_webserver_init(uint32 port); 73 | 74 | #endif 75 | --------------------------------------------------------------------------------