├── .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 += "