From 10f3964be1d3c0b12cabc0bf683687fa4b73b3df Mon Sep 17 00:00:00 2001 From: adamdunkels Date: Mon, 7 Jul 2008 23:42:32 +0000 Subject: [PATCH] Added an AJAX-style web server app that continously updates a web page with data from the Tmote Sky on-board sensors --- examples/sky-ip/Makefile | 6 +- examples/sky-ip/ajax-cgi.c | 230 ++++++++++++++++ examples/sky-ip/httpd-fs.c | 128 +++++++++ examples/sky-ip/httpd-fs/404.html | 8 + examples/sky-ip/httpd-fs/footer.html | 3 + examples/sky-ip/httpd-fs/header.html | 12 + examples/sky-ip/httpd-fs/index.html | 15 ++ examples/sky-ip/httpd-fs/neighbors.shtml | 10 + examples/sky-ip/httpd-fs/sensors.shtml | 78 ++++++ examples/sky-ip/httpd-fsdata.c | 330 +++++++++++++++++++++++ 10 files changed, 818 insertions(+), 2 deletions(-) create mode 100644 examples/sky-ip/ajax-cgi.c create mode 100644 examples/sky-ip/httpd-fs.c create mode 100644 examples/sky-ip/httpd-fs/404.html create mode 100644 examples/sky-ip/httpd-fs/footer.html create mode 100644 examples/sky-ip/httpd-fs/header.html create mode 100644 examples/sky-ip/httpd-fs/index.html create mode 100644 examples/sky-ip/httpd-fs/neighbors.shtml create mode 100644 examples/sky-ip/httpd-fs/sensors.shtml create mode 100644 examples/sky-ip/httpd-fsdata.c diff --git a/examples/sky-ip/Makefile b/examples/sky-ip/Makefile index bd906e360..25e30d9ee 100644 --- a/examples/sky-ip/Makefile +++ b/examples/sky-ip/Makefile @@ -1,8 +1,8 @@ -CONTIKI_PROJECT = telnet-webserver +CONTIKI_PROJECT = sky-webserver all: $(CONTIKI_PROJECT) APPS = telnetd webserver -CFLAGS = -DWITH_UIP=1 #-DWITH_NULLMAC=1 +CFLAGS = -DWITH_UIP=1 -I. #-DWITH_NULLMAC=1 # The webserver application normally contains a built-in file system and support # for server-side includes. @@ -19,6 +19,8 @@ endif CONTIKI = ../.. include $(CONTIKI)/Makefile.include +sky-webserver.$(TARGET): $(OBJECTDIR)/ajax-cgi.o + # Intentionally httpd.c and httpd-cfs.c implement the same interface. When # switching from one webserver alternative to the other with an existent # Contiki library then both files end up in the library making the linker diff --git a/examples/sky-ip/ajax-cgi.c b/examples/sky-ip/ajax-cgi.c new file mode 100644 index 000000000..9b1fcaecc --- /dev/null +++ b/examples/sky-ip/ajax-cgi.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2001, Adam Dunkels. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the uIP TCP/IP stack. + * + * $Id: ajax-cgi.c,v 1.1 2008/07/07 23:42:32 adamdunkels Exp $ + * + */ + +/* + * This file includes functions that are called by the web server + * scripts. The functions takes no argument, and the return value is + * interpreted as follows. A zero means that the function did not + * complete and should be invoked for the next packet as well. A + * non-zero value indicates that the function has completed and that + * the web server should move along to the next script line. + * + */ + +#include +#include + +#include "contiki-net.h" +#include "httpd.h" +#include "httpd-cgi.h" +#include "httpd-fs.h" + +#include "lib/petsciiconv.h" + +static struct httpd_cgi_call *calls = NULL; + +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(nullfunction(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +httpd_cgifunction +httpd_cgi(char *name) +{ + struct httpd_cgi_call *f; + + /* Find the matching name in the table, return the function. */ + for(f = calls; f != NULL; f = f->next) { + if(strncmp(f->name, name, strlen(f->name)) == 0) { + return f->function; + } + } + return nullfunction; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(nodeidcall(struct httpd_state *s, char *ptr)) +{ + static char buf[10]; + PSOCK_BEGIN(&s->sout); + snprintf(buf, sizeof(buf), "%d.%d", + rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); + PSOCK_SEND_STR(&s->sout, buf); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +void +httpd_cgi_add(struct httpd_cgi_call *c) +{ + struct httpd_cgi_call *l; + + c->next = NULL; + if(calls == NULL) { + calls = c; + } else { + for(l = calls; l->next != NULL; l = l->next); + l->next = c; + } +} +/*---------------------------------------------------------------------------*/ +#include "dev/sht11.h" +#include "dev/light.h" + +static +PT_THREAD(sensorscall(struct httpd_state *s, char *ptr)) +{ + static struct timer t; + static int i; + static char buf[100]; + static unsigned long last_cpu, last_lpm, last_listen, last_transmit; + + PSOCK_BEGIN(&s->sout); + + timer_set(&t, CLOCK_SECOND); + i = 0; + while(1) { + timer_restart(&t); + PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t)); + + snprintf(buf, sizeof(buf), + "", + sht11_temp(), + sht11_humidity(), + sensors_light1(), + sensors_light2()); + PSOCK_SEND_STR(&s->sout, buf); + + + timer_restart(&t); + PSOCK_WAIT_UNTIL(&s->sout, timer_expired(&t)); + snprintf(buf, sizeof(buf), + "", + energest_type_time(ENERGEST_TYPE_CPU) - last_cpu, + energest_type_time(ENERGEST_TYPE_LPM) - last_lpm, + energest_type_time(ENERGEST_TYPE_TRANSMIT) - last_transmit, + energest_type_time(ENERGEST_TYPE_LISTEN) - last_listen, + i++); + last_cpu = energest_type_time(ENERGEST_TYPE_CPU); + last_lpm = energest_type_time(ENERGEST_TYPE_LPM); + last_transmit = energest_type_time(ENERGEST_TYPE_TRANSMIT); + last_listen = energest_type_time(ENERGEST_TYPE_LISTEN); + PSOCK_SEND_STR(&s->sout, buf); + +} + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +static unsigned short +make_neighbor(void *arg) +{ + struct httpd_state *s = (struct httpd_state *)arg; + struct neighbor *n = neighbor_get(s->u.count); + + if(n == NULL) { + return 0; + } + + return snprintf((char *)uip_appdata, uip_mss(), + "
  • %d.%d\r\n", + + n->addr.u8[0], n->addr.u8[1], + n->addr.u8[0], n->addr.u8[1]); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(neighborscall(struct httpd_state *s, char *ptr)) +{ + PSOCK_BEGIN(&s->sout); + + printf("neighbor_num %d\n", neighbor_num()); + + for(s->u.count = 0; s->u.count < neighbor_num(); s->u.count++) { + printf("count %d\n", s->u.count); + if(neighbor_get(s->u.count) != NULL) { + printf("!= NULL\n"); + PSOCK_GENERATOR_SEND(&s->sout, make_neighbor, s); + } + } + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ + +static void +adv_received(struct neighbor_discovery_conn *c, rimeaddr_t *from, + uint16_t rtmetric) +{ + struct neighbor *n; + + printf("adv_received %d.%d\n", from->u8[0], from->u8[1]); + + n = neighbor_find(from); + + if(n == NULL) { + neighbor_add(from, rtmetric, 1); + } else { + neighbor_update(n, rtmetric); + } +} + + +static const struct neighbor_discovery_callbacks neighbor_discovery_callbacks = + { adv_received, NULL}; + + +HTTPD_CGI_CALL(sensors, "sensors", sensorscall); +HTTPD_CGI_CALL(nodeid, "nodeid", nodeidcall); +HTTPD_CGI_CALL(neighbors, "neighbors", neighborscall); + +static struct neighbor_discovery_conn conn; + +void +httpd_cgi_init(void) +{ + + httpd_cgi_add(&sensors); + httpd_cgi_add(&nodeid); + httpd_cgi_add(&neighbors); + + neighbor_discovery_open(&conn, 31, + CLOCK_SECOND * 2, + CLOCK_SECOND * 10, + CLOCK_SECOND * 60, + &neighbor_discovery_callbacks); + neighbor_discovery_start(&conn, 0); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/sky-ip/httpd-fs.c b/examples/sky-ip/httpd-fs.c new file mode 100644 index 000000000..6efb8c938 --- /dev/null +++ b/examples/sky-ip/httpd-fs.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: httpd-fs.c,v 1.1 2008/07/07 23:42:32 adamdunkels Exp $ + */ + +#include "contiki-net.h" +#include "httpd.h" +#include "httpd-fs.h" +#include "httpd-fsdata.h" + +#include "httpd-fsdata.c" + +#if HTTPD_FS_STATISTICS +static u16_t count[HTTPD_FS_NUMFILES]; +#endif /* HTTPD_FS_STATISTICS */ + +/*-----------------------------------------------------------------------------------*/ +static u8_t +httpd_fs_strcmp(const char *str1, const char *str2) +{ + u8_t i; + i = 0; + +loop: + if(str2[i] == 0 || + str1[i] == '\r' || + str1[i] == '\n') { + return 0; + } + + if(str1[i] != str2[i]) { + return 1; + } + + ++i; + goto loop; +} +/*-----------------------------------------------------------------------------------*/ +int +httpd_fs_open(const char *name, struct httpd_fs_file *file) +{ +#if HTTPD_FS_STATISTICS + u16_t i = 0; +#endif /* HTTPD_FS_STATISTICS */ + struct httpd_fsdata_file_noconst *f; + + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + file->data = f->data; + file->len = f->len; +#if HTTPD_FS_STATISTICS + ++count[i]; +#endif /* HTTPD_FS_STATISTICS */ + return 1; + } +#if HTTPD_FS_STATISTICS + ++i; +#endif /* HTTPD_FS_STATISTICS */ + + } + return 0; +} +/*-----------------------------------------------------------------------------------*/ +void +httpd_fs_init(void) +{ +#if HTTPD_FS_STATISTICS + u16_t i; + for(i = 0; i < HTTPD_FS_NUMFILES; i++) { + count[i] = 0; + } +#endif /* HTTPD_FS_STATISTICS */ +} +/*-----------------------------------------------------------------------------------*/ +#if HTTPD_FS_STATISTICS +u16_t +httpd_fs_count(char *name) +{ + struct httpd_fsdata_file_noconst *f; + u16_t i; + + i = 0; + for(f = (struct httpd_fsdata_file_noconst *)HTTPD_FS_ROOT; + f != NULL; + f = (struct httpd_fsdata_file_noconst *)f->next) { + + if(httpd_fs_strcmp(name, f->name) == 0) { + return count[i]; + } + ++i; + } + return 0; +} +#endif /* HTTPD_FS_STATISTICS */ +/*-----------------------------------------------------------------------------------*/ diff --git a/examples/sky-ip/httpd-fs/404.html b/examples/sky-ip/httpd-fs/404.html new file mode 100644 index 000000000..a17711d02 --- /dev/null +++ b/examples/sky-ip/httpd-fs/404.html @@ -0,0 +1,8 @@ + + +
    +

    404 - file not found

    +

    Go here instead.

    +
    + + \ No newline at end of file diff --git a/examples/sky-ip/httpd-fs/footer.html b/examples/sky-ip/httpd-fs/footer.html new file mode 100644 index 000000000..81d8c883c --- /dev/null +++ b/examples/sky-ip/httpd-fs/footer.html @@ -0,0 +1,3 @@ + + + diff --git a/examples/sky-ip/httpd-fs/header.html b/examples/sky-ip/httpd-fs/header.html new file mode 100644 index 000000000..a6c9f0dab --- /dev/null +++ b/examples/sky-ip/httpd-fs/header.html @@ -0,0 +1,12 @@ + + + +Contiki + + +
    +

    Contiki 

    +Front page
    +Neighbors
    +Sensors
    +
    diff --git a/examples/sky-ip/httpd-fs/index.html b/examples/sky-ip/httpd-fs/index.html new file mode 100644 index 000000000..27e09443d --- /dev/null +++ b/examples/sky-ip/httpd-fs/index.html @@ -0,0 +1,15 @@ + + + +Contiki + + +
    +

    Contiki 

    +Front page
    +Neighbors
    +Sensors
    +
    +
    + + diff --git a/examples/sky-ip/httpd-fs/neighbors.shtml b/examples/sky-ip/httpd-fs/neighbors.shtml new file mode 100644 index 000000000..0f10206b0 --- /dev/null +++ b/examples/sky-ip/httpd-fs/neighbors.shtml @@ -0,0 +1,10 @@ +%!: /header.html +

    Node +%! nodeid +

    +

    Neighbors

    +
      +%! neighbors +
    +%!: /footer.html + diff --git a/examples/sky-ip/httpd-fs/sensors.shtml b/examples/sky-ip/httpd-fs/sensors.shtml new file mode 100644 index 000000000..428ac6a43 --- /dev/null +++ b/examples/sky-ip/httpd-fs/sensors.shtml @@ -0,0 +1,78 @@ +%!: /header.html + +

    Node +%! nodeid +

    +

    Environment

    +
    +
    +

    Light

    +
    +
    +

    Power

    +
    +
    +
    +
    +
    +

    +
    0
    +%!: /footer.html +%! sensors + diff --git a/examples/sky-ip/httpd-fsdata.c b/examples/sky-ip/httpd-fsdata.c new file mode 100644 index 000000000..77d17db5e --- /dev/null +++ b/examples/sky-ip/httpd-fsdata.c @@ -0,0 +1,330 @@ +static const unsigned char data_404_html[] = { + /* /404.html */ + 0x2f, 0x34, 0x30, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0x20, 0x20, 0x3c, + 0x62, 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, + 0x6f, 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, + 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x63, 0x65, 0x6e, + 0x74, 0x65, 0x72, 0x3e, 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x3c, 0x68, 0x31, 0x3e, 0x34, 0x30, 0x34, 0x20, 0x2d, + 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x3c, 0x2f, 0x68, 0x31, 0x3e, + 0xa, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x68, 0x33, + 0x3e, 0x47, 0x6f, 0x20, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x68, 0x65, 0x72, 0x65, + 0x3c, 0x2f, 0x61, 0x3e, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, + 0x61, 0x64, 0x2e, 0x3c, 0x2f, 0x68, 0x33, 0x3e, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x63, 0x65, 0x6e, 0x74, 0x65, + 0x72, 0x3e, 0xa, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, + 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, +0}; + +static const unsigned char data_footer_html[] = { + /* /footer.html */ + 0x2f, 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x3c, + 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0xa, 0x3c, 0x2f, 0x68, + 0x74, 0x6d, 0x6c, 0x3e, 0xa, 0}; + +static const unsigned char data_header_html[] = { + /* /header.html */ + 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x3e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6b, + 0x69, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, + 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x62, + 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x3d, 0x30, 0x20, 0x63, 0x65, 0x6c, + 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x34, + 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, + 0x6e, 0x67, 0x3d, 0x34, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, + 0x74, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, + 0x22, 0x74, 0x6f, 0x70, 0x22, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, + 0xa, 0x3c, 0x68, 0x31, 0x3e, 0x43, 0x6f, 0x6e, 0x74, 0x69, + 0x6b, 0x69, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, + 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, 0x72, 0x6f, 0x6e, + 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, + 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, + 0x6c, 0x22, 0x3e, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, + 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x76, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x22, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6c, 0x65, + 0x66, 0x74, 0x22, 0x3e, 0xa, 0}; + +static const unsigned char data_index_html[] = { + /* /index.html */ + 0x2f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x3c, 0x21, 0x44, 0x4f, 0x43, 0x54, 0x59, 0x50, 0x45, 0x20, + 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x50, 0x55, 0x42, 0x4c, 0x49, + 0x43, 0x20, 0x22, 0x2d, 0x2f, 0x2f, 0x57, 0x33, 0x43, 0x2f, + 0x2f, 0x44, 0x54, 0x44, 0x20, 0x48, 0x54, 0x4d, 0x4c, 0x20, + 0x34, 0x2e, 0x30, 0x31, 0x20, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x2f, 0x45, + 0x4e, 0x22, 0x20, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, + 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x33, 0x2e, 0x6f, 0x72, + 0x67, 0x2f, 0x54, 0x52, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x34, + 0x2f, 0x6c, 0x6f, 0x6f, 0x73, 0x65, 0x2e, 0x64, 0x74, 0x64, + 0x22, 0x3e, 0xa, 0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, + 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x3e, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6b, + 0x69, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0xa, + 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0xa, 0x3c, 0x62, + 0x6f, 0x64, 0x79, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3d, 0x22, 0x77, 0x68, 0x69, 0x74, 0x65, 0x22, 0x3e, + 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x62, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x3d, 0x30, 0x20, 0x63, 0x65, 0x6c, + 0x6c, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x34, + 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, + 0x6e, 0x67, 0x3d, 0x34, 0x3e, 0x3c, 0x74, 0x72, 0x3e, 0x3c, + 0x74, 0x64, 0x20, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, + 0x22, 0x74, 0x6f, 0x70, 0x22, 0x20, 0x61, 0x6c, 0x69, 0x67, + 0x6e, 0x3d, 0x22, 0x72, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, + 0xa, 0x3c, 0x68, 0x31, 0x3e, 0x43, 0x6f, 0x6e, 0x74, 0x69, + 0x6b, 0x69, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, + 0x68, 0x31, 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, 0x65, + 0x66, 0x3d, 0x22, 0x2f, 0x22, 0x3e, 0x46, 0x72, 0x6f, 0x6e, + 0x74, 0x20, 0x70, 0x61, 0x67, 0x65, 0x3c, 0x2f, 0x61, 0x3e, + 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, 0x61, 0x20, 0x68, 0x72, + 0x65, 0x66, 0x3d, 0x22, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, + 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0x22, + 0x3e, 0x4e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, + 0x61, 0x20, 0x68, 0x72, 0x65, 0x66, 0x3d, 0x22, 0x73, 0x65, + 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, + 0x6c, 0x22, 0x3e, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, + 0x3c, 0x2f, 0x61, 0x3e, 0x3c, 0x62, 0x72, 0x3e, 0xa, 0x3c, + 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x76, 0x61, + 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x22, + 0x20, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x3d, 0x22, 0x6c, 0x65, + 0x66, 0x74, 0x22, 0x3e, 0xa, 0x3c, 0x2f, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x3e, 0xa, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, + 0x3e, 0xa, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0xa, +0}; + +static const unsigned char data_neighbors_shtml[] = { + /* /neighbors.shtml */ + 0x2f, 0x6e, 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x68, 0x31, + 0x3e, 0x4e, 0x6f, 0x64, 0x65, 0xa, 0x25, 0x21, 0x20, 0x6e, + 0x6f, 0x64, 0x65, 0x69, 0x64, 0xa, 0x3c, 0x2f, 0x68, 0x31, + 0x3e, 0xa, 0x3c, 0x68, 0x32, 0x3e, 0x4e, 0x65, 0x69, 0x67, + 0x68, 0x62, 0x6f, 0x72, 0x73, 0x3c, 0x2f, 0x68, 0x32, 0x3e, + 0xa, 0x3c, 0x75, 0x6c, 0x3e, 0xa, 0x25, 0x21, 0x20, 0x6e, + 0x65, 0x69, 0x67, 0x68, 0x62, 0x6f, 0x72, 0x73, 0xa, 0x3c, + 0x2f, 0x75, 0x6c, 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, + 0x66, 0x6f, 0x6f, 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, + 0x6c, 0xa, 0xa, 0}; + +static const unsigned char data_sensors_shtml[] = { + /* /sensors.shtml */ + 0x2f, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0x2e, 0x73, 0x68, 0x74, 0x6d, 0x6c, 0, + 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x3c, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, + 0x22, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x6a, 0x61, 0x76, 0x61, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x3e, 0xa, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x65, 0x28, + 0x65, 0x6c, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, 0x64, 0x20, + 0x3d, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x3b, 0xa, 0x20, 0x20, 0x69, 0x66, 0x28, 0x64, 0x2e, 0x67, + 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, + 0x79, 0x49, 0x64, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, 0x20, + 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x2e, + 0x67, 0x65, 0x74, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x42, 0x79, 0x49, 0x64, 0x28, 0x65, 0x6c, 0x29, 0x3b, 0xa, + 0x20, 0x20, 0x7d, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x69, + 0x66, 0x20, 0x28, 0x64, 0x2e, 0x61, 0x6c, 0x6c, 0x29, 0x20, + 0x7b, 0xa, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, + 0x72, 0x6e, 0x20, 0x64, 0x2e, 0x61, 0x6c, 0x6c, 0x5b, 0x65, + 0x6c, 0x5d, 0x3b, 0xa, 0x20, 0x20, 0x7d, 0xa, 0x7d, 0xa, + 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, + 0x28, 0x65, 0x6c, 0x2c, 0x6e, 0x2c, 0x6d, 0x61, 0x78, 0x2c, + 0x74, 0x65, 0x78, 0x74, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, + 0x65, 0x28, 0x65, 0x6c, 0x29, 0x2e, 0x69, 0x6e, 0x6e, 0x65, + 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, 0x27, 0x3c, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x64, 0x74, + 0x68, 0x3d, 0x35, 0x30, 0x34, 0x20, 0x62, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x3d, 0x30, 0x20, 0x63, 0x65, 0x6c, 0x6c, 0x70, + 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x31, 0x20, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, + 0x3d, 0x30, 0x3e, 0x27, 0x2b, 0xa, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x27, 0x3c, 0x74, 0x72, + 0x3e, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, + 0x3d, 0x32, 0x30, 0x30, 0x3e, 0x27, 0x20, 0x2b, 0xa, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, + 0x65, 0x78, 0x74, 0x20, 0x2b, 0x20, 0x27, 0x3c, 0x2f, 0x74, + 0x64, 0x3e, 0x27, 0x20, 0x2b, 0xa, 0x9, 0x9, 0x20, 0x20, + 0x20, 0x20, 0x27, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, + 0x74, 0x68, 0x3d, 0x27, 0x20, 0x2b, 0x20, 0x28, 0x33, 0x30, + 0x30, 0x2a, 0x6e, 0x2f, 0x6d, 0x61, 0x78, 0x29, 0x20, 0x2b, + 0x20, 0x27, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, 0x72, + 0x3d, 0x22, 0x67, 0x72, 0x61, 0x79, 0x22, 0x3e, 0x26, 0x6e, + 0x62, 0x73, 0x70, 0x3b, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x27, + 0x20, 0x2b, 0xa, 0x9, 0x9, 0x20, 0x20, 0x20, 0x20, 0x27, + 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, + 0x27, 0x20, 0x2b, 0x20, 0x28, 0x33, 0x30, 0x30, 0x2d, 0x33, + 0x30, 0x30, 0x2a, 0x6e, 0x2f, 0x6d, 0x61, 0x78, 0x29, 0x20, + 0x2b, 0x20, 0x27, 0x20, 0x62, 0x67, 0x63, 0x6f, 0x6c, 0x6f, + 0x72, 0x3d, 0x22, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x67, 0x72, + 0x61, 0x79, 0x22, 0x3e, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, + 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x27, 0x20, 0x2b, 0xa, 0x9, + 0x9, 0x20, 0x20, 0x20, 0x20, 0x27, 0x3c, 0x2f, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x3e, 0x27, 0x3b, 0xa, 0x7d, 0xa, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x63, + 0x28, 0x6e, 0x2c, 0x64, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, + 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x2e, 0x74, + 0x6f, 0x46, 0x69, 0x78, 0x65, 0x64, 0x28, 0x64, 0x29, 0x3b, + 0xa, 0x7d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x28, 0x6d, 0x29, 0x20, 0x7b, 0xa, 0x20, + 0x20, 0x6e, 0x20, 0x3d, 0x20, 0x64, 0x63, 0x28, 0x2d, 0x33, + 0x39, 0x2e, 0x36, 0x2b, 0x30, 0x2e, 0x30, 0x31, 0x2a, 0x6d, + 0x2c, 0x20, 0x31, 0x29, 0x3b, 0xa, 0x20, 0x20, 0x73, 0x28, + 0x27, 0x74, 0x65, 0x6d, 0x70, 0x27, 0x2c, 0x6e, 0x2c, 0x34, + 0x30, 0x2c, 0x27, 0x54, 0x65, 0x6d, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x20, 0x27, 0x2b, 0x6e, 0x2b, 0x27, + 0x20, 0x26, 0x64, 0x65, 0x67, 0x3b, 0x43, 0x27, 0x29, 0x3b, + 0xa, 0x7d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x68, 0x28, 0x6d, 0x29, 0x20, 0x7b, 0xa, 0x20, + 0x20, 0x6e, 0x20, 0x3d, 0x20, 0x64, 0x63, 0x28, 0x2d, 0x34, + 0x2b, 0x30, 0x2e, 0x30, 0x34, 0x30, 0x35, 0x2a, 0x6d, 0x20, + 0x2d, 0x20, 0x32, 0x2e, 0x38, 0x65, 0x2d, 0x36, 0x2a, 0x28, + 0x6d, 0x2a, 0x6d, 0x29, 0x2c, 0x20, 0x32, 0x29, 0x3b, 0xa, + 0x20, 0x20, 0x73, 0x28, 0x27, 0x68, 0x75, 0x6d, 0x27, 0x2c, + 0x6e, 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x27, 0x48, 0x75, 0x6d, + 0x69, 0x64, 0x69, 0x74, 0x79, 0x20, 0x27, 0x2b, 0x6e, 0x2b, + 0x27, 0x25, 0x27, 0x29, 0x3b, 0xa, 0x7d, 0xa, 0x66, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x31, 0x28, + 0x6d, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, 0x6e, 0x20, 0x3d, + 0x20, 0x64, 0x63, 0x28, 0x2e, 0x37, 0x36, 0x32, 0x39, 0x33, + 0x39, 0x34, 0x33, 0x37, 0x35, 0x2a, 0x6d, 0x2c, 0x20, 0x30, + 0x29, 0x3b, 0xa, 0x20, 0x20, 0x73, 0x28, 0x27, 0x6c, 0x31, + 0x27, 0x2c, 0x6e, 0x2c, 0x32, 0x30, 0x30, 0x2c, 0x27, 0x4c, + 0x69, 0x67, 0x68, 0x74, 0x20, 0x31, 0x20, 0x27, 0x2b, 0x6e, + 0x29, 0x3b, 0xa, 0x7d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x32, 0x28, 0x6d, 0x29, 0x20, + 0x7b, 0xa, 0x20, 0x20, 0x6e, 0x20, 0x3d, 0x20, 0x64, 0x63, + 0x28, 0x2e, 0x34, 0x36, 0x39, 0x33, 0x36, 0x30, 0x33, 0x2a, + 0x6d, 0x2c, 0x20, 0x30, 0x29, 0x3b, 0xa, 0x20, 0x20, 0x73, + 0x28, 0x27, 0x6c, 0x32, 0x27, 0x2c, 0x6e, 0x2c, 0x32, 0x30, + 0x30, 0x2c, 0x27, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x20, 0x32, + 0x20, 0x27, 0x2b, 0x6e, 0x29, 0x3b, 0xa, 0x7d, 0xa, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x73, + 0x28, 0x6d, 0x29, 0x20, 0x7b, 0xa, 0x20, 0x20, 0x6e, 0x20, + 0x3d, 0x20, 0x6d, 0x20, 0x2b, 0x20, 0x34, 0x35, 0x3b, 0xa, + 0x20, 0x20, 0x73, 0x28, 0x27, 0x72, 0x73, 0x27, 0x2c, 0x6e, + 0x2c, 0x31, 0x30, 0x30, 0x2c, 0x27, 0x52, 0x53, 0x53, 0x49, + 0x20, 0x27, 0x2b, 0x6e, 0x29, 0x3b, 0xa, 0x7d, 0xa, 0x66, + 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x70, 0x28, + 0x63, 0x2c, 0x6c, 0x2c, 0x74, 0x2c, 0x72, 0x29, 0x20, 0x7b, + 0xa, 0x20, 0x20, 0x74, 0x6d, 0x3d, 0x63, 0x2b, 0x6c, 0x3b, + 0xa, 0x20, 0x20, 0x63, 0x70, 0x3d, 0x63, 0x2a, 0x31, 0x2e, + 0x38, 0x2f, 0x74, 0x6d, 0x3b, 0xa, 0x20, 0x20, 0x6c, 0x70, + 0x3d, 0x6c, 0x2a, 0x30, 0x2e, 0x30, 0x35, 0x34, 0x35, 0x2f, + 0x74, 0x6d, 0x3b, 0xa, 0x20, 0x20, 0x6c, 0x74, 0x3d, 0x74, + 0x2a, 0x31, 0x37, 0x2e, 0x37, 0x2f, 0x74, 0x6d, 0x3b, 0xa, + 0x20, 0x20, 0x6c, 0x72, 0x3d, 0x72, 0x2a, 0x32, 0x30, 0x2f, + 0x74, 0x6d, 0x3b, 0xa, 0x20, 0x20, 0x6e, 0x3d, 0x63, 0x70, + 0x2b, 0x6c, 0x70, 0x2b, 0x6c, 0x74, 0x2b, 0x6c, 0x72, 0x3b, + 0xa, 0x20, 0x20, 0x73, 0x28, 0x27, 0x70, 0x27, 0x2c, 0x6e, + 0x2c, 0x33, 0x30, 0x2c, 0x27, 0x50, 0x6f, 0x77, 0x65, 0x72, + 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x20, 0x27, 0x2b, 0x64, 0x63, 0x28, 0x6e, 0x2c, + 0x32, 0x29, 0x2b, 0x27, 0x20, 0x6d, 0x57, 0x27, 0x29, 0x3b, + 0xa, 0x20, 0x20, 0x73, 0x28, 0x27, 0x70, 0x63, 0x27, 0x2c, + 0x63, 0x70, 0x2c, 0x33, 0x30, 0x2c, 0x27, 0x43, 0x50, 0x55, + 0x20, 0x70, 0x6f, 0x77, 0x65, 0x72, 0x20, 0x27, 0x2b, 0x64, + 0x63, 0x28, 0x63, 0x70, 0x2c, 0x32, 0x29, 0x2b, 0x27, 0x20, + 0x6d, 0x57, 0x27, 0x29, 0x3b, 0xa, 0x20, 0x20, 0x73, 0x28, + 0x27, 0x70, 0x6c, 0x27, 0x2c, 0x6c, 0x70, 0x2c, 0x33, 0x30, + 0x2c, 0x27, 0x4c, 0x50, 0x4d, 0x20, 0x70, 0x6f, 0x77, 0x65, + 0x72, 0x20, 0x27, 0x2b, 0x64, 0x63, 0x28, 0x6c, 0x70, 0x2c, + 0x32, 0x29, 0x2b, 0x27, 0x20, 0x6d, 0x57, 0x27, 0x29, 0x3b, + 0xa, 0x20, 0x20, 0x73, 0x28, 0x27, 0x70, 0x72, 0x27, 0x2c, + 0x6c, 0x72, 0x2c, 0x33, 0x30, 0x2c, 0x27, 0x52, 0x61, 0x64, + 0x69, 0x6f, 0x20, 0x52, 0x58, 0x20, 0x70, 0x6f, 0x77, 0x65, + 0x72, 0x20, 0x27, 0x2b, 0x64, 0x63, 0x28, 0x6c, 0x72, 0x2c, + 0x32, 0x29, 0x2b, 0x27, 0x20, 0x6d, 0x57, 0x27, 0x29, 0x3b, + 0xa, 0x20, 0x20, 0x73, 0x28, 0x27, 0x70, 0x74, 0x27, 0x2c, + 0x6c, 0x74, 0x2c, 0x33, 0x30, 0x2c, 0x27, 0x52, 0x61, 0x64, + 0x69, 0x6f, 0x20, 0x54, 0x58, 0x20, 0x70, 0x6f, 0x77, 0x65, + 0x72, 0x20, 0x27, 0x2b, 0x64, 0x63, 0x28, 0x6c, 0x74, 0x2c, + 0x32, 0x29, 0x2b, 0x27, 0x20, 0x6d, 0x57, 0x27, 0x29, 0x3b, + 0xa, 0x7d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x69, 0x28, 0x6e, 0x29, 0x20, 0x7b, 0xa, 0x20, + 0x20, 0x65, 0x28, 0x27, 0x69, 0x27, 0x29, 0x2e, 0x69, 0x6e, + 0x6e, 0x65, 0x72, 0x48, 0x54, 0x4d, 0x4c, 0x20, 0x3d, 0x20, + 0x6e, 0x3b, 0xa, 0x7d, 0xa, 0x3c, 0x2f, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x3e, 0xa, 0x3c, 0x68, 0x31, 0x3e, 0x4e, + 0x6f, 0x64, 0x65, 0xa, 0x25, 0x21, 0x20, 0x6e, 0x6f, 0x64, + 0x65, 0x69, 0x64, 0xa, 0x3c, 0x2f, 0x68, 0x31, 0x3e, 0xa, + 0x3c, 0x68, 0x32, 0x3e, 0x45, 0x6e, 0x76, 0x69, 0x72, 0x6f, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x3c, 0x2f, 0x68, 0x32, 0x3e, + 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, + 0x74, 0x65, 0x6d, 0x70, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, + 0x3d, 0x22, 0x68, 0x75, 0x6d, 0x22, 0x3e, 0x3c, 0x2f, 0x64, + 0x69, 0x76, 0x3e, 0xa, 0x3c, 0x68, 0x32, 0x3e, 0x4c, 0x69, + 0x67, 0x68, 0x74, 0x3c, 0x2f, 0x68, 0x32, 0x3e, 0xa, 0x3c, + 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x31, + 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, + 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x32, + 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, 0x76, 0x3e, 0xa, 0x3c, + 0x68, 0x32, 0x3e, 0x50, 0x6f, 0x77, 0x65, 0x72, 0x3c, 0x2f, + 0x68, 0x32, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, + 0x64, 0x3d, 0x22, 0x70, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, + 0x3d, 0x22, 0x70, 0x63, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, + 0x3d, 0x22, 0x70, 0x6c, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, + 0x3d, 0x22, 0x70, 0x72, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, + 0x3d, 0x22, 0x70, 0x74, 0x22, 0x3e, 0x3c, 0x2f, 0x64, 0x69, + 0x76, 0x3e, 0xa, 0x3c, 0x62, 0x72, 0x3e, 0x3c, 0x62, 0x72, + 0x3e, 0xa, 0x3c, 0x64, 0x69, 0x76, 0x20, 0x69, 0x64, 0x3d, + 0x22, 0x69, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x64, 0x69, 0x76, + 0x3e, 0xa, 0x25, 0x21, 0x3a, 0x20, 0x2f, 0x66, 0x6f, 0x6f, + 0x74, 0x65, 0x72, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0xa, 0x25, + 0x21, 0x20, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x73, 0xa, + 0xa, 0}; + +const struct httpd_fsdata_file file_404_html[] = {{NULL, data_404_html, data_404_html + 10, sizeof(data_404_html) - 10}}; + +const struct httpd_fsdata_file file_footer_html[] = {{file_404_html, data_footer_html, data_footer_html + 13, sizeof(data_footer_html) - 13}}; + +const struct httpd_fsdata_file file_header_html[] = {{file_footer_html, data_header_html, data_header_html + 13, sizeof(data_header_html) - 13}}; + +const struct httpd_fsdata_file file_index_html[] = {{file_header_html, data_index_html, data_index_html + 12, sizeof(data_index_html) - 12}}; + +const struct httpd_fsdata_file file_neighbors_shtml[] = {{file_index_html, data_neighbors_shtml, data_neighbors_shtml + 17, sizeof(data_neighbors_shtml) - 17}}; + +const struct httpd_fsdata_file file_sensors_shtml[] = {{file_neighbors_shtml, data_sensors_shtml, data_sensors_shtml + 15, sizeof(data_sensors_shtml) - 15}}; + +#define HTTPD_FS_ROOT file_sensors_shtml + +#define HTTPD_FS_NUMFILES 6