Parcourir la source

EUS bug fixes (#1605)

- Bug fixes and improvements
- FIX: Ensure that station is enabled before doing network scan (this seems to be the cause of #1578)
- FIX: Check if state == NULL on enduser_setup.stop()
- IMPROVEMENT: Look for both enduser_setup.html.gz and enduser_setup.html as valid filenames, for semantic reasons
- IMPROVEMENT: Show a generic status message on HTML page if failure occurred before user even submitted data (i.e., would have come from previously stored config when the STA was started by EUS)
Jason Follas il y a 7 ans
Parent
commit
a48e88d4a3

+ 116 - 58
app/modules/enduser_setup.c

@@ -49,6 +49,13 @@
 #include "vfs.h"
 #include "task/task.h"
 
+/* Set this to 1 to generate debug messages. Uses debug callback provided by Lua. Example: enduser_setup.start(successFn, print, print) */ 
+#define ENDUSER_SETUP_DEBUG_ENABLE 0
+
+/* Set this to 1 to output the contents of HTTP requests when debugging. Useful if you need it, but can get pretty noisy */
+#define ENDUSER_SETUP_DEBUG_SHOW_HTTP_REQUEST 0
+
+
 #define MIN(x, y)  (((x) < (y)) ? (x) : (y))
 #define LITLEN(strliteral) (sizeof (strliteral) -1)
 #define STRINGIFY(x) #x
@@ -63,6 +70,7 @@
 #define ENDUSER_SETUP_ERR_UNKOWN_ERROR           3
 #define ENDUSER_SETUP_ERR_SOCKET_ALREADY_OPEN    4
 #define ENDUSER_SETUP_ERR_MAX_NUMBER             5
+#define ENDUSER_SETUP_ERR_ALREADY_INITIALIZED    6
 
 /**
  * DNS Response Packet:
@@ -80,6 +88,7 @@ static const char dns_body[]   = { 0x00, 0x01, 0x00, 0x01,
 /*        DNS Answer Part          |LBL OFFS|  |  TYPE  |  |  CLASS |  |         TTL        |  | RD LEN | */
                                    0xC0, 0x0C, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x78, 0x00, 0x04 };
 
+static const char http_html_gz_filename[] = "enduser_setup.html.gz";
 static const char http_html_filename[] = "enduser_setup.html";
 static const char http_header_200[] = "HTTP/1.1 200 OK\r\nCache-control:no-cache\r\nConnection:close\r\nContent-Type:text/html\r\n"; /* Note single \r\n here! */
 static const char http_header_204[] = "HTTP/1.1 204 No Content\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
@@ -92,7 +101,7 @@ static const char http_header_500[] = "HTTP/1.1 500 Internal Error\r\nContent-Le
 static const char http_header_content_len_fmt[] = "Content-length:%5d\r\n\r\n";
 static const char http_html_gzip_contentencoding[] = "Content-Encoding: gzip\r\n";
 
-// Externally defined: static const char http_html_backup[] = ...
+/* Externally defined: static const char http_html_backup[] = ... */
 #include "eus/http_html_backup.def"
 
 typedef struct scan_listener
@@ -136,7 +145,6 @@ static void enduser_setup_check_station(void *p);
 static void enduser_setup_debug(int line, const char *str);
 
 
-#define ENDUSER_SETUP_DEBUG_ENABLE 0
 #if ENDUSER_SETUP_DEBUG_ENABLE
 #define ENDUSER_SETUP_DEBUG(str) enduser_setup_debug(__LINE__, str)
 #else
@@ -250,7 +258,7 @@ static void enduser_setup_check_station(void *p)
   
   if (has_ip == 0)
   {
-    // No IP Address yet, so check the reported status 
+    /* No IP Address yet, so check the reported status */ 
     uint8_t curr_status = wifi_station_get_connect_status();
     char buf[20];
     c_sprintf(buf, "status=%d,chan=%d", curr_status, currChan);
@@ -260,9 +268,10 @@ static void enduser_setup_check_station(void *p)
     {
       state->connecting = 0;
      
-      // If the status is an error status and the channel changed, then cache the 
-      // status to state since the Station won't be able to report the same status
-      // after switching the channel back to the SoftAP's
+      /* If the status is an error status and the channel changed, then cache the 
+       * status to state since the Station won't be able to report the same status
+       * after switching the channel back to the SoftAP's
+       */
       if (currChan != state->softAPchannel) {
         state->lastStationStatus = curr_status;
       
@@ -277,7 +286,7 @@ static void enduser_setup_check_station(void *p)
   }
 
   state->success = 1;
-  state->lastStationStatus = 5; // We have an IP Address, so the status is 5 (as of SDK 1.5.1)
+  state->lastStationStatus = 5; /*  We have an IP Address, so the status is 5 (as of SDK 1.5.1) */
   state->connecting = 0;
   
 #if ENDUSER_SETUP_DEBUG_ENABLE  
@@ -411,13 +420,35 @@ static int enduser_setup_http_load_payload(void)
   int err = VFS_RES_ERR;
   int err2 = VFS_RES_ERR;
   int file_len = 0;
-  int f = vfs_open(http_html_filename, "r");
-  if (f) {
+
+  /* Try to open enduser_setup.html.gz from SPIFFS first */
+  int f = vfs_open(http_html_gz_filename, "r");
+
+  if (f) 
+  {
       err = vfs_lseek(f, 0, VFS_SEEK_END);
       file_len = (int) vfs_tell(f);
       err2 = vfs_lseek(f, 0, VFS_SEEK_SET);
   }
 
+  if (!f || err == VFS_RES_ERR || err2 == VFS_RES_ERR)
+  {
+    if (f) 
+    {
+      vfs_close(f);
+    }
+
+    /* If that didn't work, try to open enduser_setup.html from SPIFFS */
+    f = vfs_open(http_html_filename, "r");
+
+    if (f) 
+    {
+        err = vfs_lseek(f, 0, VFS_SEEK_END);
+        file_len = (int) vfs_tell(f);
+        err2 = vfs_lseek(f, 0, VFS_SEEK_SET);
+    }
+  }
+
   char cl_hdr[30];
   size_t ce_len = 0;
   
@@ -426,20 +457,23 @@ static int enduser_setup_http_load_payload(void)
 
   if (!f || err == VFS_RES_ERR || err2 == VFS_RES_ERR)
   {
-    ENDUSER_SETUP_DEBUG("enduser_setup_http_load_payload unable to load file enduser_setup.html, loading backup HTML.");
+    ENDUSER_SETUP_DEBUG("Unable to load file enduser_setup.html, loading backup HTML...");
 
     c_sprintf(cl_hdr, http_header_content_len_fmt, sizeof(http_html_backup));
     cl_len = c_strlen(cl_hdr);
-    
+    int html_len = LITLEN(http_html_backup);
+
     if (http_html_backup[0] == 0x1f && http_html_backup[1] == 0x8b)
     {
         ce_len = c_strlen(http_html_gzip_contentencoding);
+        html_len = http_html_backup_len; /* Defined in eus/http_html_backup.def by xxd -i */
         ENDUSER_SETUP_DEBUG("Content is gzipped");
     }   
    
-    int payload_len = LITLEN(http_header_200) + cl_len + ce_len + LITLEN(http_html_backup); 
+    int payload_len = LITLEN(http_header_200) + cl_len + ce_len + html_len; 
     state->http_payload_len = payload_len;
     state->http_payload_data = (char *) c_malloc(payload_len);
+
     if (state->http_payload_data == NULL)
     {
       return 2;
@@ -448,8 +482,12 @@ static int enduser_setup_http_load_payload(void)
     int offset = 0;
     c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200));
     offset += LITLEN(http_header_200);
+
     if (ce_len > 0)
+    {
         offset += c_sprintf(state->http_payload_data + offset, http_html_gzip_contentencoding, ce_len);
+    }
+    
     c_memcpy(&(state->http_payload_data[offset]), &(cl_hdr), cl_len);
     offset += cl_len;
     c_memcpy(&(state->http_payload_data[offset]), &(http_html_backup), sizeof(http_html_backup));
@@ -469,6 +507,7 @@ static int enduser_setup_http_load_payload(void)
   int payload_len = LITLEN(http_header_200) + cl_len + ce_len + file_len;
   state->http_payload_len = payload_len;
   state->http_payload_data = (char *) c_malloc(payload_len);
+
   if (state->http_payload_data == NULL)
   {
     return 2;
@@ -480,8 +519,12 @@ static int enduser_setup_http_load_payload(void)
 
   c_memcpy(&(state->http_payload_data[offset]), &(http_header_200), LITLEN(http_header_200));
   offset += LITLEN(http_header_200);
+
   if (ce_len > 0)
+  {
     offset += c_sprintf(state->http_payload_data + offset, http_html_gzip_contentencoding, ce_len);  
+  }
+  
   c_memcpy(&(state->http_payload_data[offset]), &(cl_hdr), cl_len);
   offset += cl_len;
   vfs_read(f, &(state->http_payload_data[offset]), file_len);
@@ -793,7 +836,7 @@ static void enduser_setup_serve_status(struct tcp_pcb *conn)
         memset(status_buf, 0, status_len);
         status_len = c_sprintf(status_buf, s, config.ssid, ip_addr);
 
-        int buf_len = sizeof(fmt) + status_len + 10; //10 = (9+1), 1 byte is '\0' and 9 are reserved for length field
+        int buf_len = sizeof(fmt) + status_len + 10; /* 10 = (9+1), 1 byte is '\0' and 9 are reserved for length field */
         char buf[buf_len];
         memset(buf, 0, buf_len);
         int output_len = c_sprintf(buf, fmt, status_len, status_buf);
@@ -807,7 +850,7 @@ static void enduser_setup_serve_status(struct tcp_pcb *conn)
       {
         const char *s = states[curr_state];
         int status_len = c_strlen(s);
-        int buf_len = sizeof(fmt) + status_len + 10; //10 = (9+1), 1 byte is '\0' and 9 are reserved for length field
+        int buf_len = sizeof(fmt) + status_len + 10; /* 10 = (9+1), 1 byte is '\0' and 9 are reserved for length field */
         char buf[buf_len];
         memset(buf, 0, buf_len);
         int output_len = c_sprintf(buf, fmt, status_len, s);
@@ -827,7 +870,7 @@ static void enduser_setup_serve_status_as_json (struct tcp_pcb *http_client)
 {
   ENDUSER_SETUP_DEBUG("enduser_setup_serve_status_as_json");
   
-  // If the station is currently shut down because of wi-fi channel issue, use the cached status
+  /* If the station is currently shut down because of wi-fi channel issue, use the cached status */
   uint8_t curr_status = state->lastStationStatus > 0 ? state->lastStationStatus : wifi_station_get_connect_status ();  
 
   char json_payload[64];
@@ -999,7 +1042,7 @@ static void on_scan_done (void *arg, STATUS status)
     const size_t hdr_sz = sizeof (header_fmt) +1 -1; /* +expand %4d, -\0 */
 
     /* To be able to safely escape a pathological SSID, we need 2*32 bytes */
-    const size_t max_entry_sz = 27 + 2*32 + 6; // {"ssid":"","rssi":,"chan":}
+    const size_t max_entry_sz = 27 + 2*32 + 6; /* {"ssid":"","rssi":,"chan":} */
     const size_t alloc_sz = hdr_sz + num_nets * max_entry_sz + 3;
     char *http = os_zalloc (alloc_sz);
     if (!http)
@@ -1089,8 +1132,10 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
 
   err_t ret = ERR_OK;
 
+#if ENDUSER_SETUP_DEBUG_SHOW_HTTP_REQUEST
   ENDUSER_SETUP_DEBUG(data);
-  
+#endif
+
   if (c_strncmp(data, "GET ", 4) == 0)
   {
     if (c_strncmp(data + 4, "/ ", 2) == 0)
@@ -1106,7 +1151,7 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
     }
     else if (c_strncmp(data + 4, "/aplist", 7) == 0)
     {
-      // Don't do an AP Scan while station is trying to connect to Wi-Fi
+      /* Don't do an AP Scan while station is trying to connect to Wi-Fi */
       if (state->connecting == 0) 
       {
         scan_listener_t *l = os_malloc (sizeof (scan_listener_t));
@@ -1137,7 +1182,7 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
       }
       else
       {
-        // Return No Content status to the caller
+        /* Return No Content status to the caller */
         enduser_setup_http_serve_header(http_client, http_header_204, LITLEN(http_header_204));     
       }
     }
@@ -1329,7 +1374,7 @@ static void on_initial_scan_done (void *arg, STATUS status)
 {
   ENDUSER_SETUP_DEBUG("on_initial_scan_done");
 
-  if (!state)
+  if (state == NULL)
   {
     return;
   }
@@ -1338,6 +1383,14 @@ static void on_initial_scan_done (void *arg, STATUS status)
   
   if (status == OK)
   {
+    /* Find the strongest signal and use the same wi-fi channel for the SoftAP. This is based on an assumption that end-user 
+     * will likely be choosing that AP to connect to. Since ESP only has one radio, STA and AP must share same channel. This  
+     * algorithm tries to minimize the SoftAP unavailability when the STA is connecting to verify. If the STA must switch to  
+     * another wi-fi channel, then the SoftAP will follow it, but the end-user's device will not know that the SoftAP is no  
+     * longer there until it times out. To mitigate, we try to prevent the need to switch channels, and if a switch does occur,
+     * be quick about returning to this channel so that status info can be delivered to the end-user's device before shutting 
+     * down EUS. 
+     */
     for (struct bss_info *wn = arg; wn; wn = wn->next.stqe_next)
     {
       if (wn->rssi > rssi)
@@ -1359,8 +1412,8 @@ static void enduser_setup_dns_recv_callback(void *arg, char *recv_data, unsigned
   struct espconn *callback_espconn = arg;
   struct ip_info ip_info;
 
-  uint32_t qname_len = c_strlen(&(recv_data[12])) + 1; // \0=1byte
-  uint32_t dns_reply_static_len = (uint32_t) sizeof(dns_header) + (uint32_t) sizeof(dns_body) + 2 + 4; // dns_id=2bytes, ip=4bytes
+  uint32_t qname_len = c_strlen(&(recv_data[12])) + 1; /* \0=1byte */
+  uint32_t dns_reply_static_len = (uint32_t) sizeof(dns_header) + (uint32_t) sizeof(dns_body) + 2 + 4; /* dns_id=2bytes, ip=4bytes */
   uint32_t dns_reply_len = dns_reply_static_len + qname_len;
 
 #if ENDUSER_SETUP_DEBUG_ENABLE
@@ -1418,7 +1471,7 @@ static void enduser_setup_dns_recv_callback(void *arg, char *recv_data, unsigned
   insert_byte += (uint32_t) sizeof(dns_body);
   c_memcpy(&(dns_reply[insert_byte]), &(ip_info.ip), 4);
 
-  // SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port
+  /* SDK 1.4.0 changed behaviour, for UDP server need to look up remote ip/port */
   remot_info *pr = 0;
   if (espconn_get_connection_info(callback_espconn, &pr, 0) != ESPCONN_OK)
   {
@@ -1490,7 +1543,7 @@ static int enduser_setup_dns_start(void)
 
   if (state->espconn_dns_udp != NULL)
   {
-    ENDUSER_SETUP_ERROR("dns_start failed. Appears to already be started (espconn_dns_udp != NULL).", ENDUSER_SETUP_ERR_UNKOWN_ERROR, ENDUSER_SETUP_ERR_FATAL);
+    ENDUSER_SETUP_ERROR("dns_start failed. Appears to already be started (espconn_dns_udp != NULL).", ENDUSER_SETUP_ERR_ALREADY_INITIALIZED, ENDUSER_SETUP_ERR_FATAL);
   }
   state->espconn_dns_udp = (struct espconn *) c_malloc(sizeof(struct espconn));
   if (state->espconn_dns_udp == NULL)
@@ -1549,65 +1602,69 @@ static void enduser_setup_dns_stop(void)
 
 static int enduser_setup_init(lua_State *L)
 {
-  // Note: Normal to not see this debug message on first invocation because debug callback is set below
+  /* Note: Normal to not see this debug message on first invocation because debug callback is set below */
   ENDUSER_SETUP_DEBUG("enduser_setup_init");
 
+  /* Defer errors until the bottom, so that callbacks can be set, if applicable, to handle debug and error messages */
+  int ret = 0;
+
   if (state != NULL)
   {
-    ENDUSER_SETUP_ERROR("init failed. Appears to already be started.", ENDUSER_SETUP_ERR_UNKOWN_ERROR, ENDUSER_SETUP_ERR_FATAL);
-    return ENDUSER_SETUP_ERR_UNKOWN_ERROR;
+    ret = ENDUSER_SETUP_ERR_ALREADY_INITIALIZED;
   }
-
-  state = (enduser_setup_state_t *) os_zalloc(sizeof(enduser_setup_state_t));
-  if (state == NULL)
+  else
   {
-    ENDUSER_SETUP_ERROR("init failed. Unable to allocate memory.", ENDUSER_SETUP_ERR_OUT_OF_MEMORY, ENDUSER_SETUP_ERR_FATAL);
-    return ENDUSER_SETUP_ERR_OUT_OF_MEMORY;
-  }
-  c_memset(state, 0, sizeof(enduser_setup_state_t));
+    state = (enduser_setup_state_t *) os_zalloc(sizeof(enduser_setup_state_t));
 
-  state->lua_connected_cb_ref = LUA_NOREF;
-  state->lua_err_cb_ref = LUA_NOREF;
-  state->lua_dbg_cb_ref = LUA_NOREF;
+    if (state == NULL)
+    {
+      ret = ENDUSER_SETUP_ERR_OUT_OF_MEMORY;
+    }
+    else
+    {
+      c_memset(state, 0, sizeof(enduser_setup_state_t));    
+
+      state->lua_connected_cb_ref = LUA_NOREF;
+      state->lua_err_cb_ref = LUA_NOREF;
+      state->lua_dbg_cb_ref = LUA_NOREF;    
+
+      state->softAPchannel = 1;
+      state->success = 0;
+      state->callbackDone = 0;
+      state->lastStationStatus = 0;
+      state->connecting = 0;    
+    }
+  }
 
   if (!lua_isnoneornil(L, 1))
   {
     lua_pushvalue(L, 1);
     state->lua_connected_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
   }
-  else
-  {
-    state->lua_connected_cb_ref = LUA_NOREF;
-  }
 
   if (!lua_isnoneornil(L, 2))
   {
     lua_pushvalue (L, 2);
     state->lua_err_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
   }
-  else
-  {
-    state->lua_err_cb_ref = LUA_NOREF;
-  }
 
   if (!lua_isnoneornil(L, 3))
   {
     lua_pushvalue (L, 3);
     state->lua_dbg_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
-    ENDUSER_SETUP_DEBUG("enduser_setup_init: Debug callback has been defined");    
+    ENDUSER_SETUP_DEBUG("enduser_setup_init: Debug callback has been set");    
   }
-  else
+
+  if (ret == ENDUSER_SETUP_ERR_ALREADY_INITIALIZED) 
+  {
+    ENDUSER_SETUP_ERROR("init failed. Appears to already be started. EUS will shut down now.", ENDUSER_SETUP_ERR_ALREADY_INITIALIZED, ENDUSER_SETUP_ERR_FATAL);
+  }
+  else if (ret == ENDUSER_SETUP_ERR_OUT_OF_MEMORY) 
   {
-    state->lua_dbg_cb_ref = LUA_NOREF;
+    ENDUSER_SETUP_ERROR("init failed. Unable to allocate memory.", ENDUSER_SETUP_ERR_OUT_OF_MEMORY, ENDUSER_SETUP_ERR_FATAL);
   }
 
-  state->softAPchannel = 1;
-  state->success = 0;
-  state->callbackDone = 0;
-  state->lastStationStatus = 0;
-  state->connecting = 0;
-  
-  return 0;
+  return ret;
 }
 
 
@@ -1624,7 +1681,7 @@ static int enduser_setup_manual(lua_State *L)
 
 static int enduser_setup_start(lua_State *L)
 {
-  // Note: The debug callback is set in enduser_setup_init. It's normal to not see this debug message on first invocation.
+  /* Note: The debug callback is set in enduser_setup_init. It's normal to not see this debug message on first invocation. */
   ENDUSER_SETUP_DEBUG("enduser_setup_start");
 
   if (!do_station_cfg_handle)
@@ -1639,7 +1696,8 @@ static int enduser_setup_start(lua_State *L)
 
   if (!manual)
   {
-    ENDUSER_SETUP_DEBUG("Performing AP Scan to identify likely AP's channel");    
+    ENDUSER_SETUP_DEBUG("Performing AP Scan to identify likely AP's channel. Enabling Station if it wasn't already.");    
+    wifi_set_opmode(STATION_MODE | wifi_get_opmode());
     wifi_station_scan(NULL, on_initial_scan_done);
   }
   else
@@ -1683,7 +1741,7 @@ static int enduser_setup_stop(lua_State* L)
   {
     enduser_setup_ap_stop();
   }
-  if (state->success && !state->callbackDone)
+  if (state != NULL && state->success && !state->callbackDone)
   {
     wifi_set_opmode(STATION_MODE | wifi_get_opmode());
     wifi_station_connect();

+ 134 - 127
app/modules/eus/enduser_setup.html

@@ -142,7 +142,7 @@
 		}
 		
 		#i {
-			text-align: justify;
+			text-align: center;
 		}
 	</style>
 </head>
@@ -165,7 +165,7 @@
 			<div id=f2>
 				<h1>Success!</h1>
 				<div id=i>
-					<h3>Your device has successfully connected to the Wi-Fi network.</h3>
+					<h3>Your device has successfully connected to the Wi-Fi network.<br /><br/>You may now close this web page.</h3>
 				</div>
 			</div>
 			<div id=f3>
@@ -176,139 +176,146 @@
 		<h4 id='st'>Updating Status...</h4>
 	</div>
 	<script>
-        var $ = function (selector) { return document.querySelector(selector); };
-        var ab = $('#networks'), ap = $('#aplist');
-        var stopAll = false, ra, rs;
+		var $ = function (selector) { return document.querySelector(selector); };
+		var ab = $('#networks'), ap = $('#aplist');
+		var stopAll = false, ra, rs, submitted = false;
+
+		function show(f, y) {
+			if (y == null) y = f;
+			$(f).style.display = y == f ? 'block' : 'none';
+		}
+		function hide(f) {
+			$(f).style.display = 'none';
+		}
+		function to(cb, x) {
+			return setTimeout(cb, 1000 * x);
+		}
+		function refr() {
+			if (!stopAll)
+				fetch('/status.json?n=' + Math.random(), 'GET', newSt, 2);
+		}
+		function cur(f) {
+			show('#f1', f);
+			show('#f2', f);
+			show('#f3', f);
+		}
+		function newSt(s, d) {
+			clearTimeout(rs);
+			rs = to(refr, 3);
 
-        function show(f, y) {
-            if (y == null) y = f;
-            $(f).style.display = y == f ? 'block' : 'none';
-        }
-        function hide(f) {
-            $(f).style.display = 'none';
-        }
-        function to(cb, x) {
-            return setTimeout(cb, 1000 * x);
-        }
-        function refr() {
-            if (!stopAll)
-                fetch('/status.json?n=' + Math.random(), 'GET', newSt, 2);
-        }
-        function cur(f) {
-            show('#f1', f);
-            show('#f2', f);
-            show('#f3', f);
-        }
-        function newSt(s, d) {
-            clearTimeout(rs);
-            rs = to(refr, 3);
+			if (s != 200) {
+				$('#st').innerText = 'Awaiting Status (' + s + ')';
+			} else {
+				if (typeof d === 'string') {
+					d = JSON.parse(d);
+				}
 
-            if (s != 200) {
-                $('#st').innerText = 'Awaiting Status (' + s + ')';
-            } else {
-                if (typeof d === 'string') {
-                    d = JSON.parse(d);
-                }
+				$('#deviceId').innerText = "Device: " + d.deviceid;
 
-                $('#deviceId').innerText = d.deviceid;
+				var c = d.pairing;
 
-                var c = d.pairing;
+				var st = [
+					'Idle',
+					'Connecting...',
+					'Failed - wrong password',
+					'Failed - network not found',
+					'Failed',
+					'Wi-Fi successfully connected!'
+				][d.status];
 
-                var s = [
-                    'Idle',
-                    'Connecting...',
-                    'Failed - wrong password',
-                    'Failed - network not found',
-                    'Failed',
-                    'Wi-Fi successfully connected!'
-                ][d.status];
+				if (st == null)
+					st = "";
 
-                $('#st').innerText = s;
+				if (!submitted && d.status > 1 && d.status < 5)
+					st = "Need a valid Network and Password";
 
-                if (d.status === 5) {
-                    cur('#f2');
-                    stopAll = true;
-                    clearTimeout(ra);
-                } else if (d.status > 1) {
-                    cur('#f1');
-                }
-            }
-        }
-        function submit() {
-            var url = '/setwifi?wifi_ssid=' + encodeURIComponent($('#ssid').value) + '&wifi_password=' + encodeURIComponent($('#wifi_password').value);
-            clearTimeout(rs);
-            fetch(url, 'GET', newSt, 2);
-            cur('#f3');
-        }
-        function fetch(url, method, callback, time_out) {
-            var xhr = new XMLHttpRequest();
-            xhr.onloadend = function () {
-                callback(xhr.status, xhr.responseText);
-            }
-            xhr.ontimeout = function () {
-                callback(-1, null);
-            }
-            xhr.open(method, url, true);
-            xhr.setRequestHeader('Accept', 'application/json');
-            xhr.timeout = (time_out || 10) * 1000;
-            xhr.send();
-        }
-        function gotAp(s, json) {
-            var list;
-            if (s === 200 && json != null) {
-                if (typeof json === 'string' && json.length > 0) {
-                    list = JSON.parse(json);
-                } else if (typeof json === 'object') {
-                    list = json;
-                }
+				$('#st').innerText = st;
 
-                list.sort(function (a, b) {
-                    return b.rssi - a.rssi;
-                });
-                var ops = '<option>Select a Network...</option>';
-                for (var i = 0; i < list.length; ++i) {
-                    ops += '<option>' + list[i].ssid + '</option>';
-                }
-                ap.innerHTML = ops;
-                ab.disabled = false;
-                togAp(null, true);
-                ab.onclick = togAp;
-            } else {
-                ab.innerText = 'No networks found (' + s + ')';
-                ra = to(refrAp, 5);
-            }
-        }
-        function togAp(ev, force) {
-            if (!force || ap.style.display == 'block') {
-                hide('#dropdown');
-                show('#ssid');
-                ab.innerText = 'Scan for Networks';
-                ab.onclick = refrAp;
-            } else {
-                show('#dropdown');
-                hide('#ssid');
-                ab.innerText = 'Manual Entry';
-            }
-        }
-        function refrAp() {
-            ab.innerText = 'Searching for networks...';
-            ab.disabled = true;
-            ap.innerHTML = '<option disabled>Scanning...</option>';
-            if (!stopAll)
-                fetch('/aplist?n=' + Math.random(), 'GET', gotAp, 10);
-        }
-        window.onload = function() {
-          ab.innerText = 'Scan for Networks';
-          ab.onclick = refrAp;
-          $('#aplist').onchange = function () {
-              $('#ssid').value = $('#aplist').value;
-          };
-          $('#submit').onclick = submit;
-          $('#bk2').onclick = function () {
-              cur('#f1')
-          }
-          rs = to(refr, 0.5);
-        }
+				if (d.status === 5) {
+					cur('#f2');
+					stopAll = true;
+					clearTimeout(ra);
+				} else if (d.status > 1) {
+					cur('#f1');
+				}
+			}
+		}
+		function submit() {
+			submitted = true;
+			var url = '/setwifi?wifi_ssid=' + encodeURIComponent($('#ssid').value) + '&wifi_password=' + encodeURIComponent($('#wifi_password').value);
+			clearTimeout(rs);
+			fetch(url, 'GET', newSt, 2);
+			cur('#f3');
+		}
+		function fetch(url, method, callback, time_out) {
+			var xhr = new XMLHttpRequest();
+			xhr.onloadend = function () {
+				callback(xhr.status, xhr.responseText);
+			}
+			xhr.ontimeout = function () {
+				callback(-1, null);
+			}
+			xhr.open(method, url, true);
+			xhr.setRequestHeader('Accept', 'application/json');
+			xhr.timeout = (time_out || 10) * 1000;
+			xhr.send();
+		}
+		function gotAp(s, json) {
+			var list;
+			if (s === 200 && json != null) {
+				if (typeof json === 'string' && json.length > 0) {
+					list = JSON.parse(json);
+				} else if (typeof json === 'object') {
+					list = json;
+				}
+
+				list.sort(function (a, b) {
+					return b.rssi - a.rssi;
+				});
+				var ops = '<option>Select a Network...</option>';
+				for (var i = 0; i < list.length; ++i) {
+					ops += '<option>' + list[i].ssid + '</option>';
+				}
+				ap.innerHTML = ops;
+				ab.disabled = false;
+				togAp(null, true);
+				ab.onclick = togAp;
+			} else {
+				ab.innerText = 'No networks found (' + s + ')';
+				ra = to(refrAp, 5);
+			}
+		}
+		function togAp(ev, force) {
+			if (!force || ap.style.display == 'block') {
+				hide('#dropdown');
+				show('#ssid');
+				ab.innerText = 'Scan for Networks';
+				ab.onclick = refrAp;
+			} else {
+				show('#dropdown');
+				hide('#ssid');
+				ab.innerText = 'Manual Entry';
+			}
+		}
+		function refrAp() {
+			ab.innerText = 'Searching for networks...';
+			ab.disabled = true;
+			ap.innerHTML = '<option disabled>Scanning...</option>';
+			if (!stopAll)
+				fetch('/aplist?n=' + Math.random(), 'GET', gotAp, 10);
+		}
+		window.onload = function() {
+		  ab.innerText = 'Scan for Networks';
+		  ab.onclick = refrAp;
+		  $('#aplist').onchange = function () {
+			  $('#ssid').value = $('#aplist').value;
+		  };
+		  $('#submit').onclick = submit;
+		  $('#bk2').onclick = function () {
+			  cur('#f1')
+		  }
+		  rs = to(refr, 0.5);
+		}
   </script>
 </body>
 

BIN
app/modules/eus/enduser_setup.html.gz


+ 202 - 200
app/modules/eus/http_html_backup.def

@@ -1,203 +1,205 @@
 static const char http_html_backup[] = {
   0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x95, 0x59,
-  0xfd, 0x72, 0xdb, 0x36, 0x12, 0xff, 0xbb, 0x37, 0x73, 0xef, 0xb0, 0x1e,
-  0xf7, 0x42, 0xb9, 0xa1, 0x64, 0x7d, 0xd8, 0x69, 0xc6, 0x12, 0xd5, 0xc9,
-  0xe5, 0x92, 0x26, 0x37, 0x49, 0xda, 0xa9, 0xdd, 0xe9, 0x75, 0x32, 0x99,
-  0x0e, 0x44, 0x82, 0x26, 0x62, 0x0a, 0xe0, 0x01, 0xa0, 0x65, 0x5d, 0xea,
-  0x77, 0x3f, 0x2c, 0x01, 0x5a, 0x86, 0x40, 0x87, 0xb5, 0x5a, 0x57, 0x04,
-  0xb0, 0xdf, 0xfb, 0xc3, 0xee, 0x52, 0x5d, 0x1c, 0xfc, 0xeb, 0xa7, 0x97,
-  0x17, 0xbf, 0xff, 0xfc, 0x0a, 0x0a, 0xbd, 0x2e, 0x97, 0x7f, 0xff, 0xdb,
-  0xc2, 0x7d, 0xe3, 0x13, 0x25, 0x99, 0x79, 0xfa, 0x66, 0xb1, 0xa6, 0x9a,
-  0x00, 0x27, 0x6b, 0x9a, 0x44, 0xd7, 0x8c, 0x6e, 0x2a, 0x21, 0x75, 0x04,
-  0xa9, 0xe0, 0x9a, 0x72, 0x9d, 0x44, 0x1b, 0x96, 0xe9, 0x22, 0xc9, 0xe8,
-  0x35, 0x4b, 0xe9, 0xb0, 0x59, 0xc4, 0xc0, 0x38, 0xd3, 0x8c, 0x94, 0x43,
-  0x95, 0x92, 0x92, 0x26, 0x93, 0xd1, 0x38, 0x6a, 0x04, 0x69, 0xa6, 0x4b,
-  0xba, 0xfc, 0x8d, 0xbd, 0x66, 0xf0, 0x4e, 0x5c, 0x32, 0xbe, 0x38, 0xb6,
-  0x3b, 0x78, 0xa6, 0xf4, 0xb6, 0xa4, 0xa0, 0xb7, 0x15, 0x4d, 0x34, 0xbd,
-  0xd1, 0xc7, 0xa9, 0x52, 0xb8, 0xff, 0xcd, 0x77, 0xf0, 0x05, 0xbf, 0xbe,
-  0x59, 0x13, 0x69, 0x38, 0xce, 0x60, 0x3c, 0x6f, 0x96, 0x15, 0xc9, 0x32,
-  0xc6, 0x2f, 0xdb, 0xf5, 0x2d, 0xfe, 0x07, 0xff, 0xd0, 0xfc, 0x18, 0x1f,
-  0x56, 0x22, 0xdb, 0x3a, 0xd6, 0x82, 0xb2, 0xcb, 0x42, 0x9f, 0xc1, 0x64,
-  0x3c, 0xfe, 0x87, 0xe5, 0xce, 0x8d, 0xf1, 0xc3, 0x9c, 0xac, 0x59, 0xb9,
-  0x3d, 0x03, 0x45, 0xb8, 0x1a, 0x2a, 0x2a, 0x59, 0x6e, 0x0f, 0x51, 0xfd,
-  0x90, 0x94, 0xec, 0xd2, 0x68, 0x4b, 0x29, 0xd7, 0x54, 0xda, 0xfd, 0x15,
-  0x49, 0xaf, 0x2e, 0xa5, 0xa8, 0x79, 0x76, 0x06, 0x87, 0x27, 0x27, 0x27,
-  0xd9, 0xc9, 0x89, 0xaf, 0xfb, 0xd0, 0xc5, 0xc4, 0xa9, 0xad, 0x84, 0x62,
-  0x9a, 0x09, 0x23, 0x85, 0xac, 0x94, 0x28, 0x6b, 0x4d, 0x9d, 0x7c, 0x51,
-  0xdd, 0xb9, 0x21, 0xad, 0x65, 0x6e, 0xb5, 0x12, 0x5a, 0x8b, 0xf5, 0xdd,
-  0xb2, 0xa4, 0xf9, 0xee, 0xac, 0x89, 0xec, 0x19, 0xcc, 0xa6, 0xe3, 0xea,
-  0x66, 0xee, 0xb9, 0x75, 0xf2, 0x1c, 0xb7, 0xbc, 0x20, 0x91, 0x5a, 0x0b,
-  0xdf, 0x36, 0xc6, 0xab, 0x5a, 0xdb, 0xc0, 0xd4, 0x46, 0x09, 0x6f, 0x1e,
-  0x15, 0x2d, 0x69, 0xda, 0x9a, 0x3b, 0xdc, 0xd0, 0xd5, 0x15, 0x33, 0x9e,
-  0x57, 0x15, 0x25, 0x92, 0xf0, 0x94, 0x9e, 0x01, 0x17, 0x9c, 0xb6, 0xa6,
-  0xc9, 0x8c, 0xca, 0xa1, 0x24, 0x19, 0xab, 0x55, 0x10, 0xf5, 0x9c, 0xd1,
-  0x32, 0x53, 0xd4, 0x89, 0x72, 0xc4, 0xf7, 0xdc, 0xba, 0x19, 0xaa, 0x82,
-  0x64, 0x62, 0x63, 0xb6, 0xcc, 0x3f, 0x93, 0xd3, 0xea, 0x06, 0x26, 0xe6,
-  0x4f, 0x5e, 0xae, 0xc8, 0x60, 0x1c, 0x83, 0xfd, 0x77, 0x74, 0x72, 0x74,
-  0x8f, 0x9e, 0xfd, 0xaf, 0x49, 0xaf, 0xd3, 0x6b, 0xb6, 0xf6, 0xf2, 0x8e,
-  0x71, 0x80, 0x19, 0x7a, 0x1e, 0x26, 0x27, 0xcf, 0x73, 0x17, 0x0f, 0xc6,
-  0x87, 0x36, 0x4c, 0x18, 0xb9, 0x20, 0x4c, 0x43, 0x63, 0x44, 0x18, 0xa6,
-  0x7d, 0x2f, 0xd0, 0x52, 0x93, 0x3f, 0x96, 0xc1, 0x61, 0x9a, 0xa6, 0xf7,
-  0x25, 0x0c, 0xdb, 0x84, 0x4d, 0x9c, 0x68, 0x97, 0x26, 0x07, 0xb5, 0x5e,
-  0x67, 0x52, 0x51, 0x0a, 0x69, 0xec, 0x9d, 0x4e, 0xa7, 0x3b, 0x5c, 0x1a,
-  0xe6, 0x67, 0x46, 0xe3, 0x5a, 0x70, 0xa1, 0x2a, 0x92, 0x52, 0xdf, 0x6f,
-  0x0c, 0x9e, 0x6f, 0xb3, 0x9f, 0xc5, 0x6e, 0x09, 0x7e, 0x84, 0x86, 0x4e,
-  0xaf, 0x36, 0x59, 0x36, 0x04, 0x92, 0x72, 0xdd, 0xa7, 0xc4, 0xa1, 0xc6,
-  0x29, 0xb1, 0xfc, 0x2e, 0xce, 0x41, 0xc2, 0x03, 0xb0, 0xcc, 0xaa, 0xd6,
-  0xdf, 0x5a, 0x2a, 0x64, 0xac, 0x04, 0xdb, 0x5d, 0xab, 0x8c, 0xa9, 0xaa,
-  0x24, 0x5b, 0x13, 0x9d, 0x52, 0xa4, 0x57, 0x41, 0x1c, 0x3a, 0x6f, 0x67,
-  0x46, 0x53, 0x21, 0x89, 0xbd, 0x5c, 0x0e, 0xa3, 0x9e, 0xf9, 0x88, 0x8d,
-  0xd3, 0x4e, 0x68, 0xcc, 0x26, 0xab, 0x93, 0xd3, 0xef, 0xc3, 0x5c, 0x75,
-  0x38, 0x7b, 0x96, 0x8b, 0xb4, 0x56, 0xf1, 0xbd, 0x8d, 0x42, 0x5c, 0x53,
-  0x09, 0x5f, 0x3a, 0x41, 0x3d, 0x86, 0xa9, 0x51, 0x8a, 0x21, 0x89, 0xed,
-  0x1a, 0xdd, 0xde, 0xe9, 0xf3, 0x6a, 0xd4, 0xec, 0x5e, 0xb2, 0x10, 0x1c,
-  0xd4, 0xfa, 0xea, 0x83, 0xe2, 0xd9, 0xb3, 0x67, 0x9d, 0x58, 0xb3, 0x30,
-  0xf6, 0xe4, 0x9d, 0x78, 0x79, 0x71, 0x30, 0xf5, 0x23, 0x12, 0x30, 0x8d,
-  0x6a, 0xcd, 0x4a, 0xa6, 0xb7, 0xad, 0x29, 0xa5, 0x20, 0x26, 0xe4, 0x4d,
-  0x3d, 0x72, 0x76, 0x94, 0x94, 0x48, 0xc4, 0xac, 0x2e, 0x5a, 0x3b, 0x6e,
-  0x86, 0x2e, 0x64, 0xdf, 0x9f, 0xda, 0x88, 0x79, 0x1e, 0xcc, 0xaa, 0x6e,
-  0x58, 0xb7, 0x1e, 0x58, 0x2b, 0x82, 0x02, 0xde, 0x14, 0x83, 0xee, 0x7b,
-  0xec, 0xfc, 0x08, 0x8d, 0x76, 0xa9, 0xf1, 0xb6, 0x1e, 0x9f, 0x9c, 0x50,
-  0xfe, 0x61, 0x26, 0x45, 0x65, 0xb8, 0x78, 0xdc, 0xac, 0xf2, 0xa9, 0xfb,
-  0x9e, 0xd9, 0xef, 0xd5, 0xd5, 0xd4, 0x29, 0x70, 0xa0, 0x75, 0xe8, 0xeb,
-  0x96, 0x11, 0xb4, 0x01, 0x49, 0x4b, 0xa2, 0xd9, 0x35, 0x7d, 0xa0, 0x52,
-  0xa0, 0xfd, 0x26, 0x0d, 0x1b, 0x57, 0xbe, 0xbd, 0x1a, 0x7f, 0xea, 0x2a,
-  0x55, 0x77, 0xe5, 0xf1, 0xf5, 0x93, 0xaa, 0x64, 0xaa, 0xa7, 0x09, 0x85,
-  0xda, 0xc3, 0x26, 0xa9, 0x45, 0x15, 0xb4, 0xa2, 0xa0, 0x4d, 0xf5, 0xd4,
-  0x49, 0xaf, 0xd1, 0x7a, 0x05, 0x29, 0xb8, 0xae, 0xa1, 0x1f, 0x52, 0x8a,
-  0xcd, 0x1e, 0xb2, 0x9f, 0x3f, 0x7f, 0x3e, 0xff, 0xaa, 0x5f, 0xae, 0xa1,
-  0x3e, 0xb7, 0xd2, 0x9c, 0x13, 0x93, 0x50, 0x38, 0x83, 0x2f, 0x41, 0xb3,
-  0xff, 0x5c, 0x2b, 0xcd, 0xf2, 0xed, 0x1d, 0xe5, 0xe2, 0xb8, 0x19, 0x4a,
-  0x70, 0x2a, 0x3a, 0x76, 0xc3, 0x90, 0x79, 0xc4, 0xc1, 0x62, 0x89, 0xa7,
-  0x19, 0xbb, 0x06, 0x96, 0x25, 0xae, 0xe9, 0x2f, 0x91, 0x6b, 0xe1, 0x1a,
-  0xa1, 0x5d, 0xb5, 0x24, 0x6e, 0x38, 0x7a, 0x9b, 0x2d, 0x17, 0xc7, 0x66,
-  0xc7, 0x3f, 0xcb, 0x27, 0xb8, 0xc6, 0x8d, 0x62, 0xb6, 0x7c, 0x29, 0x38,
-  0xc7, 0x5a, 0x6e, 0x19, 0x40, 0x0b, 0xd8, 0x8a, 0x5a, 0xc2, 0x6f, 0x6c,
-  0xf8, 0x9a, 0x19, 0x1b, 0x66, 0x2d, 0xa9, 0xad, 0x47, 0xc8, 0xce, 0xa9,
-  0xde, 0x08, 0x79, 0xa5, 0xec, 0xe4, 0xe4, 0xf6, 0xd3, 0x92, 0x28, 0x95,
-  0xb8, 0x8b, 0x61, 0x94, 0xda, 0x6d, 0xc7, 0xdc, 0x2a, 0x76, 0x30, 0xb5,
-  0xdb, 0xb8, 0x6f, 0x52, 0xd3, 0x88, 0x6c, 0xe2, 0xbe, 0x7c, 0x72, 0x78,
-  0x33, 0x3d, 0x5d, 0xa5, 0x73, 0x13, 0x84, 0x8a, 0xec, 0x88, 0x6c, 0xb3,
-  0x41, 0x32, 0x07, 0x33, 0x9c, 0x0b, 0xdd, 0xb3, 0xd1, 0x64, 0x8f, 0x1d,
-  0xb5, 0xf3, 0xd6, 0x3e, 0xdb, 0xce, 0x6a, 0xf8, 0x94, 0x62, 0xd9, 0x6e,
-  0xce, 0x6b, 0xb0, 0x9e, 0x0a, 0x29, 0x0d, 0x5b, 0x22, 0xf2, 0xdc, 0xae,
-  0x49, 0xc5, 0x34, 0x29, 0x4d, 0x59, 0x49, 0xf0, 0x7e, 0x41, 0x55, 0x92,
-  0x94, 0x16, 0xa2, 0xcc, 0xa8, 0x4c, 0xa2, 0x26, 0x18, 0xf0, 0xc1, 0xa8,
-  0x8d, 0xe0, 0x38, 0x90, 0xbe, 0x61, 0x39, 0xfb, 0xa3, 0x32, 0xee, 0x9b,
-  0xa8, 0x3c, 0x52, 0x8d, 0xa3, 0x59, 0x57, 0x25, 0xd5, 0x14, 0x89, 0x3c,
-  0xbd, 0x3f, 0xb7, 0x32, 0x8f, 0xc3, 0x24, 0xa8, 0x7a, 0xb5, 0x66, 0xfa,
-  0x7e, 0x0a, 0x96, 0xe7, 0xe4, 0x9a, 0xfa, 0x81, 0xef, 0xca, 0xfd, 0xf4,
-  0x2e, 0xf7, 0x93, 0xe5, 0x79, 0x9d, 0xa6, 0x54, 0xa9, 0x03, 0x93, 0xe7,
-  0xc9, 0x5e, 0xaa, 0x98, 0x5d, 0x5b, 0x8c, 0xfc, 0x8e, 0x88, 0x70, 0x00,
-  0x29, 0x88, 0x02, 0x65, 0xf9, 0xf2, 0xba, 0x2c, 0xb7, 0x90, 0x5a, 0x00,
-  0xd1, 0x0c, 0xb1, 0xa3, 0x0b, 0x0a, 0x36, 0x5a, 0x0e, 0x25, 0x23, 0xc4,
-  0x50, 0x98, 0x9c, 0x2e, 0xcb, 0xee, 0xc8, 0x8a, 0xe9, 0xf2, 0x42, 0x6e,
-  0xcd, 0x3d, 0x1d, 0x8d, 0x90, 0x7d, 0x1a, 0x7a, 0x8f, 0x55, 0x31, 0x44,
-  0x5f, 0xe4, 0xe0, 0x17, 0x2d, 0x7f, 0x14, 0xf0, 0x4f, 0x53, 0xd5, 0xd1,
-  0x22, 0x6b, 0xcd, 0x39, 0xd5, 0x75, 0xd5, 0x1d, 0x1c, 0x7c, 0xf2, 0xee,
-  0xd0, 0xa2, 0x38, 0x41, 0x1d, 0x91, 0xd2, 0xd1, 0xf2, 0xd7, 0x2a, 0x23,
-  0xda, 0x58, 0x02, 0xe7, 0x9a, 0xe8, 0x5a, 0x59, 0x83, 0x4e, 0x90, 0xec,
-  0x8e, 0x7d, 0xa1, 0x52, 0xc9, 0x2a, 0x64, 0x05, 0xf7, 0xb9, 0x26, 0x12,
-  0xbe, 0x85, 0x04, 0xf2, 0x9a, 0xa7, 0x58, 0x30, 0x60, 0x60, 0x31, 0x2a,
-  0xe4, 0x11, 0x7c, 0x01, 0x69, 0x4c, 0x91, 0x1c, 0x32, 0x91, 0xd6, 0x6b,
-  0xca, 0xf5, 0xe8, 0xbf, 0x35, 0x95, 0xdb, 0x73, 0x47, 0xb0, 0xa3, 0x9c,
-  0xc3, 0xed, 0xdc, 0x17, 0x49, 0x56, 0x46, 0xe6, 0xb7, 0x83, 0xe8, 0xb0,
-  0xbd, 0x80, 0xd1, 0x51, 0x0c, 0xa4, 0x72, 0x9b, 0xf6, 0x3e, 0x44, 0x47,
-  0x7b, 0x4c, 0x4a, 0x8b, 0xea, 0x45, 0x59, 0xa2, 0x35, 0xa4, 0x54, 0x34,
-  0x06, 0x49, 0xcc, 0x9f, 0x32, 0x54, 0x77, 0x74, 0x3b, 0x3b, 0x55, 0x21,
-  0x36, 0x83, 0x3c, 0x86, 0xad, 0xb1, 0xd3, 0x1d, 0xbb, 0x0f, 0xcb, 0x61,
-  0xb0, 0x85, 0x24, 0x01, 0x6e, 0x72, 0x7e, 0x04, 0x5b, 0x94, 0x37, 0xf7,
-  0x48, 0x8c, 0x11, 0xf9, 0xd1, 0xa8, 0xa9, 0x5e, 0x23, 0xdb, 0xaa, 0x90,
-  0xa8, 0xe1, 0xc9, 0xe1, 0x07, 0x88, 0x9a, 0x51, 0x2b, 0x82, 0x33, 0x88,
-  0x10, 0xf8, 0xd1, 0x3d, 0xe6, 0xdb, 0x0e, 0x4b, 0x0a, 0x96, 0xd1, 0x41,
-  0x8e, 0x66, 0xf4, 0xea, 0xf8, 0x6b, 0x02, 0xb5, 0x18, 0xa4, 0xab, 0x18,
-  0x6e, 0x02, 0x91, 0x2e, 0x1d, 0x8a, 0xea, 0x0b, 0xb6, 0xa6, 0xa2, 0xd6,
-  0x48, 0x87, 0x2d, 0x69, 0x0c, 0xdf, 0x19, 0xf2, 0x1e, 0xb1, 0x92, 0xe6,
-  0x72, 0xd0, 0x19, 0xad, 0x03, 0x17, 0xf9, 0x23, 0xef, 0xc8, 0x72, 0x53,
-  0x9d, 0x16, 0x83, 0xe8, 0x58, 0x59, 0x4c, 0x7d, 0x56, 0x82, 0xff, 0xc0,
-  0x93, 0x08, 0x9e, 0xc2, 0x7b, 0xa2, 0x8b, 0x91, 0x24, 0x3c, 0x13, 0xeb,
-  0x81, 0x49, 0x6e, 0xf4, 0xe3, 0xab, 0x8b, 0x28, 0x06, 0x4e, 0x37, 0xe7,
-  0x3a, 0x86, 0x69, 0x9f, 0x31, 0x69, 0x2d, 0xc3, 0x98, 0xd9, 0xa4, 0x46,
-  0x87, 0xf9, 0xc4, 0x48, 0xca, 0x9d, 0x88, 0xe0, 0x70, 0xfa, 0xb5, 0xc3,
-  0x19, 0x1e, 0xf6, 0x28, 0xb7, 0x46, 0x0e, 0x54, 0x0c, 0x59, 0x60, 0x41,
-  0x33, 0xd6, 0xb5, 0xd1, 0x95, 0x6a, 0x5f, 0x8d, 0x54, 0x90, 0x60, 0x7e,
-  0x30, 0x96, 0x31, 0xcc, 0xf0, 0x38, 0x0c, 0xa7, 0x82, 0x83, 0xc4, 0xcc,
-  0xa1, 0xe3, 0x40, 0x38, 0x7e, 0x10, 0xff, 0x88, 0xfd, 0x11, 0xe3, 0x9c,
-  0xca, 0x0b, 0x7a, 0xa3, 0x11, 0x16, 0x2f, 0x36, 0x84, 0xdd, 0xbb, 0xbb,
-  0x30, 0xc0, 0x08, 0x2b, 0xf3, 0x17, 0x1d, 0x45, 0x7b, 0x26, 0xdc, 0x02,
-  0x2d, 0x15, 0x0d, 0x44, 0x3b, 0xdd, 0x58, 0x69, 0x44, 0x0e, 0x99, 0xc1,
-  0xb2, 0x11, 0xab, 0xb4, 0x34, 0x42, 0xa3, 0xc0, 0x10, 0xf7, 0x41, 0x32,
-  0xf8, 0xf7, 0xf9, 0x4f, 0x1f, 0x46, 0x15, 0x91, 0x8a, 0x0e, 0xb2, 0x7d,
-  0x77, 0x5d, 0x00, 0xbb, 0xbd, 0x68, 0xdb, 0xf6, 0x9e, 0x2f, 0xd9, 0xc8,
-  0x1e, 0xb0, 0x2c, 0x08, 0x4e, 0x7b, 0xd1, 0xd3, 0x86, 0xac, 0x22, 0x0c,
-  0xad, 0x7b, 0x90, 0x0a, 0x43, 0xfd, 0xb1, 0xdb, 0xee, 0xe8, 0x6d, 0x56,
-  0xd2, 0x28, 0x7e, 0xe0, 0xd0, 0x8d, 0x09, 0xb6, 0x28, 0x3f, 0x48, 0xf5,
-  0x9a, 0xb0, 0x92, 0x66, 0x30, 0x84, 0x8d, 0x14, 0x26, 0xf0, 0x6d, 0x53,
-  0xec, 0xa7, 0x77, 0x25, 0x0d, 0xb8, 0xd0, 0x90, 0x8b, 0x9a, 0xf7, 0xb1,
-  0x3c, 0x78, 0x6c, 0xcb, 0x7d, 0x77, 0x83, 0x3a, 0x88, 0x42, 0xa6, 0x4f,
-  0x1f, 0xb3, 0x91, 0xbd, 0x87, 0x9f, 0xda, 0xa0, 0xf5, 0x43, 0x4b, 0x39,
-  0xd2, 0x10, 0x2a, 0xad, 0xb0, 0x06, 0x2a, 0xa7, 0x0f, 0x61, 0x04, 0x6f,
-  0xaa, 0xbd, 0x75, 0x01, 0x38, 0xdc, 0x67, 0x57, 0xb6, 0xb5, 0xac, 0x69,
-  0x40, 0xd4, 0x75, 0xaf, 0x48, 0x87, 0x2c, 0x07, 0x6c, 0xdf, 0xb4, 0x25,
-  0x4c, 0xfa, 0x0c, 0x9b, 0x44, 0x0f, 0xa0, 0xb6, 0x7b, 0xd9, 0x59, 0x10,
-  0xec, 0x84, 0x12, 0x16, 0x47, 0x84, 0x61, 0x2d, 0xd1, 0x35, 0x53, 0x01,
-  0xa9, 0xc6, 0xe9, 0xe9, 0x87, 0x66, 0x84, 0xc2, 0x29, 0xad, 0xa9, 0x82,
-  0x94, 0xa7, 0x22, 0xa3, 0xbf, 0xfe, 0xf2, 0xf6, 0xa5, 0x58, 0x57, 0x82,
-  0x53, 0xae, 0x07, 0x98, 0x06, 0x3c, 0x37, 0x89, 0xb8, 0x26, 0x65, 0x4d,
-  0x8f, 0xf0, 0x1a, 0x3f, 0xf1, 0x26, 0xaf, 0xaf, 0xb1, 0x7a, 0x84, 0x77,
-  0x32, 0xe6, 0xbd, 0x65, 0x2a, 0xac, 0xda, 0xc6, 0xf2, 0xee, 0xba, 0x1c,
-  0x06, 0x71, 0x16, 0xf5, 0xd5, 0xcc, 0x7b, 0x22, 0xd7, 0x54, 0x17, 0x22,
-  0x8b, 0x21, 0x25, 0x65, 0x89, 0x2f, 0xa4, 0x31, 0x68, 0x63, 0xc9, 0x1f,
-  0xc6, 0x94, 0xce, 0x00, 0xde, 0x14, 0x12, 0x12, 0x34, 0x00, 0xfe, 0xf3,
-  0xfe, 0xdd, 0x1b, 0xad, 0xab, 0x5f, 0xa8, 0x99, 0x23, 0x94, 0x1e, 0xec,
-  0xd9, 0x82, 0x84, 0x23, 0xc1, 0x4b, 0x41, 0x32, 0xca, 0x33, 0x6f, 0x26,
-  0xe9, 0xc4, 0x40, 0xab, 0x7e, 0x80, 0x7c, 0x16, 0x2f, 0x71, 0x23, 0x43,
-  0x52, 0x65, 0xe2, 0xa9, 0x28, 0xde, 0x80, 0x7d, 0x1d, 0xb7, 0x5d, 0x2a,
-  0xb5, 0x0d, 0xe4, 0x23, 0x54, 0x0e, 0x27, 0xb1, 0x1d, 0x2f, 0xfe, 0x82,
-  0xf8, 0x8a, 0xf2, 0x41, 0x1b, 0x32, 0x8c, 0x5f, 0x73, 0x4d, 0xba, 0x7c,
-  0x57, 0x54, 0xbb, 0xd0, 0xbc, 0xa1, 0x24, 0xa3, 0x26, 0x31, 0x2f, 0xd2,
-  0x94, 0x56, 0xda, 0xa4, 0x2f, 0x22, 0x55, 0x55, 0xb2, 0x94, 0xa0, 0x6d,
-  0xc7, 0xd8, 0x84, 0xa3, 0x2e, 0x01, 0x3b, 0x3f, 0x06, 0x6d, 0x46, 0xe0,
-  0xcf, 0x3f, 0x61, 0x62, 0x3a, 0xd1, 0x77, 0xcd, 0x98, 0xd0, 0xa9, 0x94,
-  0x67, 0x83, 0xbe, 0xe4, 0x5f, 0x0a, 0xfd, 0xa2, 0xc2, 0x86, 0x89, 0xaa,
-  0x3b, 0x93, 0x8c, 0x03, 0xdd, 0xbc, 0xab, 0x15, 0x26, 0x49, 0xd3, 0x0b,
-  0xe1, 0xc9, 0x93, 0x86, 0x19, 0x0e, 0xdc, 0x5c, 0xd6, 0xd3, 0xc0, 0x90,
-  0xd6, 0xeb, 0x61, 0xad, 0x80, 0x51, 0x49, 0xf9, 0xa5, 0x2e, 0x60, 0x09,
-  0xe3, 0x07, 0x2b, 0x03, 0x1a, 0xe3, 0x77, 0x36, 0xe4, 0xec, 0xa9, 0x39,
-  0x81, 0x62, 0xb1, 0xfa, 0x4c, 0x53, 0x1d, 0xf5, 0x69, 0x41, 0x86, 0x9e,
-  0xb6, 0xe9, 0xb1, 0x8c, 0x94, 0x90, 0x7a, 0xb0, 0x03, 0x1a, 0x89, 0x61,
-  0xe5, 0xeb, 0x08, 0x27, 0xbe, 0xd5, 0x48, 0x2a, 0xc5, 0x60, 0x08, 0xa4,
-  0x79, 0xe8, 0x52, 0x17, 0x78, 0xe7, 0x12, 0x23, 0x2a, 0x85, 0xe5, 0x6b,
-  0x21, 0x2a, 0x54, 0xb7, 0xb4, 0xc3, 0x3b, 0x10, 0xf8, 0x60, 0xbb, 0x58,
-  0xf3, 0x96, 0xe0, 0xce, 0xa2, 0x0e, 0x11, 0xb9, 0x90, 0x30, 0x40, 0x39,
-  0xcc, 0x48, 0x19, 0xcf, 0xcd, 0xd7, 0xc2, 0x7a, 0x61, 0xd3, 0x30, 0x87,
-  0xa7, 0x4f, 0xd9, 0x83, 0xd6, 0xa3, 0xee, 0xa7, 0xf7, 0x94, 0x63, 0xd5,
-  0x43, 0xe6, 0x8f, 0xec, 0xd3, 0x08, 0x2b, 0x24, 0x16, 0xc6, 0xaf, 0x6a,
-  0xbf, 0x0d, 0xb7, 0x48, 0x65, 0xdb, 0xdb, 0x9b, 0x8b, 0xf7, 0xef, 0x20,
-  0x41, 0x15, 0x1d, 0x7c, 0x64, 0x85, 0x33, 0x37, 0x59, 0x95, 0x34, 0x6b,
-  0xdf, 0x26, 0x3a, 0xa8, 0xb4, 0xb8, 0x34, 0xa8, 0x46, 0x34, 0x76, 0xdf,
-  0x49, 0x27, 0x49, 0xf0, 0xb4, 0x64, 0xe9, 0x15, 0x24, 0x96, 0xa1, 0x67,
-  0x1c, 0xf3, 0x58, 0xbd, 0x19, 0xef, 0x83, 0x68, 0x47, 0x07, 0x65, 0xe7,
-  0x86, 0xae, 0x29, 0xcf, 0x4b, 0x3e, 0xd9, 0x0d, 0x9b, 0x2f, 0xaa, 0xd8,
-  0xf4, 0xe8, 0xf9, 0x63, 0xba, 0x9a, 0xf3, 0x8f, 0x5e, 0xc7, 0x98, 0xc5,
-  0x94, 0x76, 0x8f, 0xfe, 0xcd, 0x11, 0x56, 0x09, 0x52, 0xed, 0xbf, 0xad,
-  0x24, 0xed, 0x9b, 0x50, 0x57, 0x82, 0xed, 0x6b, 0x4f, 0xd4, 0xfe, 0x9c,
-  0xe7, 0x17, 0x24, 0x7f, 0x2a, 0x77, 0xdd, 0x70, 0xde, 0x1f, 0xa2, 0xf3,
-  0x94, 0x70, 0x34, 0xb6, 0x45, 0xa7, 0x8a, 0xfa, 0x52, 0x82, 0xb1, 0xe9,
-  0xc9, 0x49, 0x60, 0x50, 0x60, 0x74, 0xe8, 0xd8, 0x63, 0x8c, 0x7e, 0x4f,
-  0x78, 0x4d, 0x4a, 0x78, 0xc5, 0xb5, 0xdc, 0x46, 0x8f, 0xca, 0x90, 0xb3,
-  0x3e, 0xec, 0x35, 0x41, 0x5c, 0x28, 0x91, 0x69, 0x61, 0xca, 0x20, 0x06,
-  0xe7, 0x0e, 0x45, 0xe6, 0xee, 0x3a, 0x7d, 0xdd, 0xc0, 0x0f, 0xe7, 0xb1,
-  0xe0, 0xfa, 0xb4, 0x57, 0x13, 0x5a, 0xae, 0x25, 0xa6, 0x80, 0x1b, 0x4d,
-  0x61, 0x61, 0x78, 0xf4, 0x3b, 0xa3, 0x7d, 0xcd, 0xff, 0xda, 0xeb, 0xa2,
-  0x6d, 0x2c, 0xf8, 0x0a, 0xfb, 0x40, 0x07, 0xda, 0x30, 0xc3, 0xb0, 0x71,
-  0x53, 0xc1, 0xbd, 0xfe, 0xec, 0x85, 0xec, 0xf1, 0x40, 0xea, 0x81, 0x90,
-  0xf7, 0x23, 0x05, 0x52, 0x16, 0x84, 0x5f, 0xd2, 0xbe, 0xf1, 0x60, 0x7f,
-  0xee, 0xf3, 0x7f, 0xec, 0x70, 0x9b, 0x9e, 0x9a, 0xdb, 0x40, 0xa9, 0x1d,
-  0x44, 0xad, 0x52, 0x67, 0x9e, 0xdd, 0x0a, 0x28, 0x57, 0x57, 0x53, 0x8f,
-  0xac, 0xd3, 0xb4, 0x70, 0x54, 0xf6, 0xd4, 0xe3, 0xa2, 0xfb, 0xcd, 0x76,
-  0x3c, 0x3a, 0x0d, 0x32, 0xb2, 0x38, 0xbe, 0xfb, 0xf5, 0x68, 0x71, 0xec,
-  0x7e, 0xe6, 0xc5, 0xc7, 0xe6, 0x7f, 0x89, 0xff, 0x1f, 0x01, 0x02, 0x3f,
-  0xe6, 0x2a, 0x1f, 0x00, 0x00
+  0x7b, 0x73, 0xdb, 0x36, 0x12, 0xff, 0xdb, 0xf9, 0x14, 0xeb, 0xba, 0x17,
+  0xca, 0x8d, 0xde, 0xb2, 0xd3, 0x8c, 0xf5, 0xe8, 0xe4, 0xfa, 0xbe, 0x49,
+  0xd2, 0x4e, 0xed, 0x4e, 0xaf, 0x93, 0xc9, 0x74, 0x20, 0x12, 0xb4, 0x50,
+  0x53, 0x00, 0x0f, 0x00, 0x2d, 0xeb, 0xda, 0x7c, 0xf7, 0xdb, 0xe5, 0x12,
+  0xa2, 0x28, 0xaa, 0x9a, 0xeb, 0x34, 0x7a, 0x10, 0xd8, 0xc7, 0xee, 0x6f,
+  0x1f, 0xbb, 0x72, 0x67, 0xe7, 0x5f, 0xfd, 0xf0, 0xe5, 0xdd, 0xaf, 0x3f,
+  0x7e, 0x0d, 0x2b, 0xbf, 0xce, 0x16, 0xcf, 0x66, 0xfc, 0x81, 0x9f, 0x52,
+  0x24, 0x8b, 0x67, 0x67, 0xb3, 0xb5, 0xf4, 0x02, 0xb4, 0x58, 0xcb, 0x79,
+  0xf4, 0xa8, 0xe4, 0x26, 0x37, 0xd6, 0x47, 0x10, 0x1b, 0xed, 0xa5, 0xf6,
+  0xf3, 0x68, 0xa3, 0x12, 0xbf, 0x9a, 0x27, 0xf2, 0x51, 0xc5, 0xb2, 0x57,
+  0x3e, 0x74, 0x41, 0x69, 0xe5, 0x95, 0xc8, 0x7a, 0x2e, 0x16, 0x99, 0x9c,
+  0x8f, 0xfa, 0xc3, 0x88, 0xe4, 0x78, 0xe5, 0x33, 0xb9, 0xf8, 0x45, 0x7d,
+  0xa3, 0xe0, 0x8d, 0xb9, 0x57, 0x7a, 0x36, 0xe0, 0x13, 0xbc, 0x72, 0x7e,
+  0x9b, 0x49, 0xf0, 0xdb, 0x5c, 0xce, 0xbd, 0x7c, 0xf2, 0x83, 0xd8, 0x39,
+  0x3c, 0x3e, 0xfb, 0x0c, 0xfe, 0xc0, 0xf7, 0xb3, 0xb5, 0xb0, 0x48, 0x7e,
+  0x03, 0xc3, 0x29, 0x3d, 0xe5, 0x22, 0x49, 0x94, 0xbe, 0xaf, 0x1e, 0x3f,
+  0xe2, 0x0b, 0xff, 0x91, 0xcd, 0x5d, 0xfc, 0x5c, 0x9a, 0x64, 0xcb, 0x4c,
+  0x2b, 0xa9, 0xee, 0x57, 0xfe, 0x06, 0x46, 0xc3, 0xe1, 0x3f, 0x4a, 0xbe,
+  0x14, 0x2d, 0xee, 0xa5, 0x62, 0xad, 0xb2, 0xed, 0x0d, 0x38, 0xa1, 0x5d,
+  0xcf, 0x49, 0xab, 0xd2, 0xf2, 0x8e, 0x94, 0xf6, 0x44, 0xa6, 0xee, 0x51,
+  0x4b, 0x2c, 0xd1, 0x33, 0x5b, 0x1e, 0x2f, 0x45, 0xfc, 0x70, 0x6f, 0x4d,
+  0xa1, 0x93, 0x1b, 0xb8, 0xb8, 0xba, 0xba, 0x4a, 0xae, 0xae, 0xf6, 0x74,
+  0x5e, 0x54, 0x18, 0xb0, 0xbe, 0xdc, 0x38, 0x74, 0xda, 0xa0, 0x00, 0xb1,
+  0x74, 0x26, 0x2b, 0xbc, 0x64, 0xc9, 0x26, 0x0f, 0x86, 0x5b, 0x36, 0x88,
+  0x1f, 0x96, 0xc6, 0x7b, 0xb3, 0x0e, 0x4f, 0x99, 0x4c, 0x77, 0x37, 0x25,
+  0x86, 0x37, 0x30, 0x19, 0x0f, 0xf3, 0xa7, 0xe9, 0xbe, 0x27, 0x57, 0xaf,
+  0xc2, 0x49, 0x00, 0x44, 0x14, 0xde, 0xec, 0x19, 0xa4, 0x74, 0x5e, 0xf8,
+  0x12, 0x85, 0x02, 0x85, 0x6b, 0xfa, 0xe6, 0x64, 0x26, 0xe3, 0xca, 0xc2,
+  0xde, 0x46, 0x2e, 0x1f, 0x14, 0xfa, 0x99, 0xe7, 0x52, 0x58, 0xa1, 0x63,
+  0x79, 0x03, 0xda, 0x68, 0x59, 0xd9, 0x63, 0x13, 0x69, 0x7b, 0x56, 0x24,
+  0xaa, 0x70, 0x4d, 0x6c, 0x53, 0x25, 0xb3, 0xc4, 0x49, 0x96, 0x52, 0x11,
+  0xd6, 0x6e, 0x3c, 0xf5, 0xdc, 0x4a, 0x24, 0x66, 0x83, 0x27, 0xf8, 0xdf,
+  0xe8, 0x3a, 0x7f, 0x82, 0x11, 0xbe, 0xec, 0xfd, 0x52, 0x74, 0x86, 0x5d,
+  0xe0, 0x7f, 0xfd, 0xab, 0xcb, 0x9a, 0x5c, 0xfd, 0xb7, 0x0c, 0x5f, 0xa5,
+  0x11, 0x8f, 0x9a, 0x61, 0x25, 0xbf, 0x61, 0x82, 0x6f, 0xed, 0x10, 0xa4,
+  0x69, 0xca, 0xfe, 0x2b, 0xdd, 0x63, 0x54, 0x18, 0xa7, 0x26, 0x2a, 0x3d,
+  0xd4, 0x7f, 0x88, 0x4a, 0xd3, 0x76, 0x32, 0x10, 0x63, 0xa4, 0x12, 0xb8,
+  0x88, 0xe3, 0x78, 0x8f, 0xb9, 0x17, 0xc2, 0x32, 0x0a, 0x42, 0x39, 0x1a,
+  0x21, 0x8b, 0x4e, 0x7a, 0x10, 0x9b, 0xcc, 0x58, 0xb4, 0x72, 0x3c, 0x1e,
+  0xef, 0x12, 0x0e, 0x39, 0x5f, 0xa2, 0xb2, 0xb5, 0xd1, 0xc6, 0xe5, 0x22,
+  0x96, 0x0d, 0x57, 0x11, 0xad, 0x86, 0xa5, 0x21, 0x58, 0x27, 0x99, 0x6b,
+  0x40, 0x7a, 0x95, 0x42, 0x8f, 0xb1, 0xc4, 0x7b, 0x2b, 0xb5, 0x3f, 0x29,
+  0x9e, 0xb3, 0x82, 0xc5, 0x33, 0x6b, 0x40, 0xb4, 0x1d, 0xd5, 0x46, 0x32,
+  0x4c, 0xf2, 0xca, 0xc1, 0xc2, 0x3a, 0xe2, 0xca, 0x8d, 0xda, 0x95, 0x48,
+  0xa2, 0x5c, 0x9e, 0x89, 0x2d, 0x82, 0x91, 0x99, 0xf8, 0xe1, 0xc0, 0xef,
+  0xa3, 0x65, 0x96, 0xc8, 0xd8, 0x58, 0xc1, 0xa5, 0xc2, 0xe9, 0xd7, 0xb0,
+  0x99, 0xa2, 0x7f, 0x7d, 0x2c, 0xf8, 0x93, 0xd1, 0xf2, 0xea, 0xfa, 0xf3,
+  0xc3, 0xa0, 0xb4, 0xfc, 0xbb, 0x49, 0x4d, 0x5c, 0xb8, 0x6e, 0xfd, 0xbc,
+  0x32, 0x8f, 0xd2, 0x92, 0xd7, 0xed, 0x6c, 0x1d, 0xc2, 0x18, 0xb5, 0x11,
+  0x08, 0x5d, 0x7e, 0x26, 0x57, 0xf7, 0x35, 0x85, 0xee, 0x32, 0xa9, 0x83,
+  0x42, 0xd1, 0x97, 0xec, 0x5e, 0x23, 0xea, 0x2f, 0x5f, 0xbe, 0x3c, 0x96,
+  0x48, 0x21, 0x3b, 0x83, 0xa4, 0xab, 0x06, 0xfe, 0x9c, 0x7e, 0x4d, 0xff,
+  0x1b, 0xf4, 0xfd, 0xc2, 0xab, 0x4c, 0xf9, 0x6d, 0xa5, 0x3f, 0x33, 0x02,
+  0xa1, 0x2d, 0x1b, 0x09, 0x2b, 0xcf, 0xa4, 0x40, 0x31, 0xa8, 0x6c, 0x55,
+  0x29, 0x7f, 0xea, 0x55, 0xe0, 0x7c, 0x7e, 0x4d, 0xd8, 0x34, 0x6d, 0x9e,
+  0xe4, 0xc7, 0x33, 0x95, 0x6d, 0x66, 0xe5, 0x87, 0x5d, 0xb6, 0x2c, 0xe8,
+  0x76, 0x35, 0x06, 0xdb, 0x5b, 0x96, 0x06, 0xfc, 0xf7, 0x4e, 0xfe, 0x7e,
+  0x04, 0x9a, 0xa2, 0x2f, 0x12, 0x6b, 0x72, 0x64, 0xd1, 0x5d, 0x7a, 0x48,
+  0xc7, 0xfc, 0x31, 0x29, 0x3f, 0x96, 0x0f, 0x63, 0x96, 0x1c, 0x12, 0x31,
+  0xe4, 0x54, 0x8b, 0xf9, 0xb0, 0x4d, 0x5b, 0x99, 0x61, 0x16, 0x3e, 0xca,
+  0xa3, 0x65, 0x4e, 0x16, 0x23, 0xda, 0x1b, 0xee, 0xb1, 0x8d, 0x36, 0x7c,
+  0x8d, 0xdd, 0xe3, 0x54, 0xcb, 0x08, 0x7a, 0x45, 0x9e, 0x29, 0x77, 0x7a,
+  0x38, 0x34, 0xb5, 0xb6, 0x67, 0x56, 0x98, 0x1e, 0x61, 0x44, 0xb4, 0x87,
+  0xc7, 0xe9, 0xae, 0xd6, 0x9c, 0x79, 0xa1, 0x8f, 0x1c, 0xaf, 0xb8, 0xa6,
+  0xed, 0xd6, 0x9a, 0x4d, 0x33, 0x53, 0x5f, 0xbd, 0x7a, 0x35, 0x3d, 0xe1,
+  0x4a, 0x35, 0xdc, 0x5e, 0xb1, 0x1c, 0x36, 0x7c, 0x74, 0x20, 0x55, 0xa1,
+  0xc4, 0xe3, 0xc3, 0x96, 0x89, 0x66, 0x83, 0x72, 0x0f, 0xc0, 0x15, 0x64,
+  0xc0, 0xbb, 0xc7, 0xb3, 0x19, 0xcd, 0x73, 0x5a, 0x10, 0x12, 0xf5, 0x08,
+  0x2a, 0x99, 0x57, 0x13, 0x17, 0x4f, 0xce, 0x66, 0x61, 0x2c, 0xd1, 0x43,
+  0x20, 0xa8, 0xf6, 0x90, 0xef, 0x93, 0xc5, 0x6c, 0x80, 0x27, 0x8d, 0xab,
+  0x74, 0x84, 0x8f, 0xf4, 0xbc, 0x9a, 0x2c, 0xbe, 0x34, 0x5a, 0x53, 0xab,
+  0x65, 0x72, 0xf0, 0x06, 0xb6, 0xa6, 0xb0, 0xf0, 0x8b, 0xea, 0x7d, 0xa3,
+  0x50, 0xf9, 0xa4, 0xa2, 0xe4, 0x0e, 0x42, 0xcc, 0x5a, 0xfa, 0x8d, 0xb1,
+  0x0f, 0x8e, 0x77, 0x94, 0xea, 0x3c, 0xce, 0x84, 0x73, 0xf3, 0x2a, 0xcb,
+  0x51, 0x23, 0x1f, 0x33, 0x6f, 0xd0, 0x5a, 0x65, 0x1f, 0x9f, 0xe2, 0x31,
+  0x06, 0xa0, 0x14, 0x58, 0x22, 0xbc, 0x78, 0x7e, 0xf1, 0x34, 0xbe, 0x5e,
+  0xc6, 0x53, 0xf4, 0x1c, 0xcf, 0x03, 0x0d, 0xcf, 0x01, 0xa2, 0xe2, 0x1c,
+  0xe2, 0xe5, 0x8b, 0xbf, 0xa3, 0x1a, 0xbe, 0x66, 0x62, 0x76, 0x93, 0xbf,
+  0xf2, 0xa0, 0x43, 0x2e, 0xe7, 0x54, 0x52, 0x2f, 0x53, 0x65, 0x06, 0xc7,
+  0xc6, 0x5a, 0x64, 0x9a, 0x9b, 0x34, 0xe5, 0x67, 0x91, 0x2b, 0x2f, 0x32,
+  0x6c, 0x0b, 0x73, 0xaa, 0x17, 0xc0, 0xd2, 0x89, 0xe5, 0xca, 0x64, 0x98,
+  0x48, 0xf3, 0xa8, 0x84, 0x01, 0xde, 0xa1, 0xd2, 0x08, 0x06, 0x87, 0xc2,
+  0x37, 0x2a, 0x55, 0xbf, 0xe5, 0xe8, 0x38, 0xe2, 0xf1, 0x77, 0xb5, 0x30,
+  0xcd, 0x3a, 0xcf, 0xa4, 0x97, 0x44, 0xd4, 0x50, 0xfb, 0x63, 0x90, 0x39,
+  0x68, 0xa1, 0xef, 0x8a, 0xe5, 0x5a, 0xf9, 0x7d, 0xec, 0x17, 0xb7, 0xe2,
+  0x51, 0x36, 0x10, 0x3f, 0x12, 0xf0, 0x71, 0x08, 0xf8, 0x68, 0x71, 0x5b,
+  0xc4, 0xb1, 0x74, 0xee, 0x1c, 0x83, 0x3b, 0x6a, 0x06, 0x48, 0xe1, 0x63,
+  0x48, 0x8b, 0x5f, 0x31, 0x09, 0x42, 0x4e, 0xac, 0x84, 0x03, 0xc7, 0x5c,
+  0x69, 0x91, 0x65, 0x5b, 0x88, 0x39, 0x67, 0x64, 0x42, 0xe9, 0xe2, 0x57,
+  0x12, 0x18, 0xa6, 0x2a, 0x33, 0xfa, 0xb3, 0xa5, 0x45, 0xcb, 0xf1, 0x7d,
+  0x40, 0x62, 0x60, 0x2d, 0xb6, 0xa0, 0xb1, 0x86, 0xe2, 0xcc, 0x38, 0x89,
+  0xe4, 0xca, 0x01, 0xae, 0x5f, 0x90, 0x8b, 0x7b, 0xd9, 0x0f, 0x19, 0xd6,
+  0x30, 0xba, 0x6d, 0x7e, 0xa0, 0x59, 0x8d, 0x17, 0x77, 0x76, 0x8b, 0xb5,
+  0xda, 0xef, 0x13, 0xeb, 0xb8, 0x05, 0x0f, 0xf5, 0xc0, 0x76, 0x5e, 0x46,
+  0x55, 0x62, 0x46, 0x8b, 0x6f, 0x0d, 0xfc, 0x13, 0x1b, 0x37, 0xd9, 0xcd,
+  0x36, 0xdf, 0x4a, 0x5f, 0xe4, 0x47, 0xd1, 0xc3, 0x2f, 0x75, 0x5d, 0x91,
+  0xee, 0x2b, 0x52, 0x10, 0x39, 0x1f, 0x2d, 0x7e, 0xce, 0x13, 0xe1, 0xd1,
+  0x0a, 0xb8, 0xf5, 0xc2, 0x17, 0x8e, 0x8d, 0xb9, 0x42, 0xaa, 0xc0, 0x3b,
+  0x73, 0xb1, 0x55, 0x79, 0xc9, 0xf7, 0x28, 0x2c, 0x7c, 0x0a, 0x73, 0x48,
+  0x0b, 0x1d, 0x53, 0xb3, 0x80, 0x0e, 0x27, 0xad, 0xb1, 0x97, 0xf0, 0x07,
+  0x58, 0x54, 0x6f, 0x35, 0x24, 0x38, 0x28, 0xd6, 0x52, 0xfb, 0xfe, 0x7f,
+  0x0a, 0x69, 0xb7, 0xb7, 0x15, 0x41, 0x4d, 0x39, 0x85, 0x8f, 0xd3, 0x4a,
+  0x96, 0x58, 0xa2, 0xb0, 0x4f, 0x3b, 0xd1, 0x45, 0xa8, 0xc3, 0xe8, 0xb2,
+  0x0b, 0x22, 0xaf, 0x0e, 0xb9, 0x32, 0xa2, 0xcb, 0x40, 0xed, 0xbc, 0xc9,
+  0x5f, 0x67, 0x19, 0xe9, 0x17, 0x99, 0x93, 0x5d, 0xb0, 0x02, 0x5f, 0xae,
+  0x0b, 0x9c, 0x47, 0x18, 0xc2, 0x70, 0x35, 0x7d, 0x86, 0x2c, 0x3b, 0x23,
+  0xdd, 0xca, 0x6c, 0x3a, 0x38, 0x88, 0xb6, 0x97, 0xdc, 0xa8, 0x54, 0x0a,
+  0x9d, 0x2d, 0xcc, 0xe7, 0xa0, 0x31, 0x01, 0x2e, 0x01, 0xbf, 0x02, 0xef,
+  0x31, 0x9f, 0x76, 0xd2, 0xcb, 0x7e, 0xd9, 0xab, 0xfa, 0x3c, 0x76, 0xe8,
+  0xaa, 0xa4, 0x4c, 0xe1, 0x0b, 0x88, 0xca, 0x55, 0x28, 0x82, 0x1b, 0x88,
+  0x28, 0xeb, 0xa3, 0xd0, 0x02, 0x77, 0x7a, 0x56, 0x2a, 0x91, 0x28, 0x81,
+  0x95, 0x1c, 0x95, 0xf5, 0x17, 0x8c, 0xde, 0x74, 0xe2, 0x65, 0x17, 0x9e,
+  0x2a, 0xd6, 0x0a, 0x47, 0x8c, 0xd5, 0x9d, 0x5a, 0x4b, 0x53, 0x78, 0xba,
+  0xa5, 0xe1, 0x31, 0x84, 0xcf, 0x90, 0xa8, 0xc5, 0x6e, 0x65, 0x6a, 0x3b,
+  0x7b, 0xbe, 0x9d, 0x57, 0x40, 0x5d, 0xe2, 0x01, 0x92, 0x49, 0x1f, 0xaf,
+  0x3a, 0xd1, 0xc0, 0x71, 0x78, 0x7f, 0x77, 0x46, 0x7f, 0xa1, 0xe7, 0x11,
+  0xbc, 0x80, 0xb7, 0xc2, 0xaf, 0xfa, 0x56, 0xe8, 0xc4, 0xac, 0x3b, 0x88,
+  0x7b, 0xf4, 0xed, 0xd7, 0x77, 0x51, 0x17, 0xb4, 0xdc, 0xdc, 0xfa, 0x2e,
+  0x8c, 0xdb, 0x7a, 0xe2, 0xc2, 0xee, 0xdc, 0x23, 0x4c, 0x31, 0x44, 0xe9,
+  0x08, 0x39, 0x52, 0x22, 0xad, 0x8f, 0xc6, 0xed, 0xa3, 0x49, 0x38, 0x6a,
+  0x08, 0x64, 0x55, 0x1d, 0x0c, 0x60, 0xc2, 0x52, 0x79, 0xef, 0x09, 0x4e,
+  0x5b, 0xc7, 0x42, 0xac, 0x83, 0x39, 0x41, 0x44, 0x6e, 0x76, 0x61, 0x82,
+  0x87, 0xc1, 0x51, 0x07, 0xe7, 0x73, 0xdc, 0xc4, 0x86, 0x15, 0xf7, 0x19,
+  0x25, 0x0d, 0x25, 0x4c, 0x5f, 0x69, 0x2d, 0xed, 0x1d, 0xb6, 0x2f, 0xc2,
+  0xfc, 0xf5, 0x46, 0xa8, 0xbd, 0x04, 0x87, 0x0e, 0xf9, 0xee, 0xf0, 0x15,
+  0x5d, 0x52, 0x28, 0xd0, 0x26, 0x90, 0x98, 0x33, 0x24, 0xa3, 0x92, 0x4b,
+  0x45, 0x67, 0x52, 0x48, 0x30, 0xf2, 0xc8, 0xef, 0xbc, 0x45, 0xee, 0x28,
+  0x28, 0x39, 0xc3, 0x63, 0xf8, 0xd7, 0xed, 0x0f, 0xef, 0xfa, 0xb9, 0xb0,
+  0x4e, 0x76, 0x12, 0xb6, 0x12, 0x3d, 0xdb, 0xd9, 0x10, 0xa6, 0xd5, 0x81,
+  0x25, 0x9f, 0x7c, 0x55, 0x9e, 0xdf, 0xc0, 0x27, 0xa8, 0x3c, 0xe9, 0x33,
+  0x95, 0x4a, 0x4a, 0x7f, 0x38, 0xc3, 0x63, 0xa4, 0x4a, 0x50, 0xae, 0x22,
+  0x8d, 0x7b, 0xe7, 0x8e, 0xd8, 0xdf, 0xb3, 0xfa, 0xe8, 0xfb, 0x24, 0x93,
+  0x51, 0xb7, 0x7a, 0xa8, 0x26, 0x1e, 0x77, 0x91, 0xdd, 0xe9, 0x37, 0x42,
+  0x65, 0x32, 0x81, 0x1e, 0x6c, 0xac, 0x41, 0xc7, 0x43, 0x5b, 0x6f, 0xdf,
+  0x57, 0x75, 0x07, 0xda, 0x78, 0x48, 0x4d, 0xa1, 0x0f, 0x49, 0xc2, 0x63,
+  0x35, 0x3b, 0x8e, 0x37, 0xce, 0xf3, 0xa8, 0x24, 0xfa, 0xf0, 0x3e, 0xe9,
+  0x73, 0x92, 0x7d, 0x60, 0xd3, 0x39, 0x46, 0x7e, 0x57, 0x69, 0x2c, 0xca,
+  0x95, 0x50, 0x7c, 0xb2, 0x47, 0x72, 0x5e, 0xd7, 0xef, 0xf3, 0xe7, 0x10,
+  0x84, 0xc0, 0x02, 0x46, 0x8d, 0xe7, 0x19, 0x5c, 0x37, 0x44, 0xbc, 0x93,
+  0xc8, 0x20, 0xe0, 0x51, 0xd0, 0x6a, 0xf4, 0xae, 0x72, 0x04, 0xb3, 0x19,
+  0xc2, 0xc4, 0x09, 0x3a, 0x8e, 0xa6, 0x85, 0xf3, 0x7b, 0x16, 0x04, 0x1d,
+  0x65, 0xc0, 0xaf, 0x77, 0x91, 0xc6, 0x84, 0xe7, 0x84, 0xae, 0x42, 0x7c,
+  0x56, 0x77, 0x20, 0x6f, 0x0b, 0x49, 0x87, 0xad, 0xa4, 0x15, 0x4c, 0x1b,
+  0x92, 0x2a, 0x48, 0x0f, 0x1e, 0x1d, 0xca, 0x1e, 0x45, 0xbb, 0xf4, 0xe1,
+  0xb7, 0x66, 0x85, 0x30, 0x32, 0xa1, 0xb8, 0x6b, 0x9c, 0x82, 0x01, 0x55,
+  0x7e, 0x14, 0x96, 0x6c, 0xc2, 0x1a, 0x97, 0x9e, 0xe6, 0xf8, 0x17, 0xe5,
+  0x30, 0xa7, 0x75, 0xa1, 0xac, 0x73, 0xa9, 0x63, 0x93, 0xc8, 0x9f, 0x7f,
+  0xfa, 0xfe, 0x4b, 0x9c, 0xd1, 0x46, 0x4b, 0xed, 0x3b, 0x04, 0x09, 0xdd,
+  0x23, 0x28, 0x88, 0x5f, 0x21, 0x2f, 0xa9, 0x1c, 0x9e, 0x37, 0x76, 0x80,
+  0x53, 0xac, 0x0d, 0xc2, 0x9d, 0x8c, 0xe9, 0xf1, 0x12, 0xde, 0xf5, 0x20,
+  0xb4, 0xf2, 0x78, 0x97, 0x09, 0x60, 0x4c, 0xa2, 0x76, 0x8f, 0xd8, 0x63,
+  0x5d, 0x4b, 0xbf, 0x32, 0x49, 0x17, 0x62, 0x91, 0x65, 0xf4, 0x8b, 0xa5,
+  0x0b, 0x1e, 0xf5, 0xfc, 0x86, 0x8a, 0x10, 0x9f, 0x00, 0xc5, 0xd3, 0xca,
+  0xc2, 0x9c, 0xc4, 0xc3, 0xbf, 0xdf, 0xbe, 0xf9, 0xce, 0xfb, 0xfc, 0x27,
+  0x89, 0x73, 0xc8, 0xf9, 0x0e, 0x6b, 0xc2, 0xeb, 0xbe, 0xd1, 0x99, 0x11,
+  0x89, 0xd4, 0x49, 0x63, 0x92, 0x85, 0xc8, 0x04, 0xe9, 0x1d, 0x22, 0xe5,
+  0xc0, 0x75, 0x81, 0xbe, 0x5b, 0xe9, 0x10, 0x02, 0x27, 0x29, 0x81, 0x58,
+  0xd8, 0xc7, 0x5a, 0xa2, 0x67, 0x8f, 0x4f, 0x4b, 0xec, 0x8d, 0xba, 0x5c,
+  0x09, 0x07, 0xdc, 0xb9, 0xd4, 0x9d, 0xe0, 0x5c, 0xe9, 0x29, 0x05, 0xb7,
+  0xb6, 0x17, 0xa3, 0x5a, 0x39, 0xf1, 0x9d, 0x44, 0xbb, 0x11, 0xaa, 0xd7,
+  0x58, 0x86, 0xb9, 0x8f, 0x10, 0x4d, 0x91, 0xe3, 0x90, 0x8c, 0x05, 0x29,
+  0x1c, 0x50, 0x6b, 0x8f, 0x6a, 0xb6, 0xda, 0xa4, 0x4e, 0xc0, 0x09, 0xfe,
+  0xfc, 0x13, 0x46, 0xd8, 0x2e, 0x3f, 0x2b, 0xa7, 0xc9, 0x9e, 0x02, 0x9d,
+  0x74, 0xda, 0xd0, 0xdf, 0x1b, 0xff, 0x3a, 0xa7, 0xf6, 0x4c, 0x82, 0xf7,
+  0x20, 0xa6, 0xa9, 0x3c, 0x0d, 0x3d, 0x98, 0x6b, 0x06, 0x9b, 0x30, 0xd5,
+  0x2a, 0x11, 0xc2, 0x79, 0x55, 0xee, 0xed, 0x86, 0x4a, 0xd7, 0x8d, 0x9e,
+  0x1a, 0x78, 0xfa, 0x99, 0xd4, 0xf7, 0x7e, 0x05, 0x0b, 0x18, 0xee, 0x0a,
+  0x84, 0xb4, 0x34, 0x3b, 0x2d, 0x51, 0xb6, 0xab, 0xab, 0x25, 0xdb, 0x2c,
+  0x7f, 0x97, 0xb1, 0x8f, 0x0e, 0x05, 0x11, 0x41, 0xa3, 0x53, 0xd3, 0x79,
+  0xdf, 0x19, 0xeb, 0x3b, 0x75, 0xc8, 0x44, 0x17, 0x96, 0x81, 0x31, 0xcc,
+  0xe1, 0x65, 0xdf, 0x62, 0xa9, 0x40, 0x0f, 0x44, 0xf9, 0xa5, 0x92, 0x41,
+  0x86, 0x54, 0x78, 0x98, 0xdc, 0x51, 0xf5, 0xcd, 0x4c, 0x4e, 0x42, 0x16,
+  0xbc, 0xf1, 0x80, 0x08, 0x3d, 0xa9, 0xdc, 0xa8, 0xaa, 0xbb, 0x88, 0xb9,
+  0x52, 0x63, 0xa1, 0x43, 0xac, 0x0a, 0x19, 0x87, 0x53, 0xfc, 0x98, 0x95,
+  0xa8, 0x56, 0x38, 0x4c, 0xe1, 0xc5, 0x0b, 0xb5, 0x33, 0x83, 0xc4, 0xbf,
+  0xd8, 0x93, 0x4f, 0x75, 0x49, 0xc4, 0xef, 0xd5, 0x87, 0x3e, 0xd5, 0x30,
+  0x95, 0x6e, 0x43, 0x41, 0xc8, 0xad, 0x33, 0x91, 0x73, 0xcb, 0xfb, 0xee,
+  0xee, 0xed, 0x1b, 0x54, 0x84, 0x82, 0xf8, 0x56, 0x2c, 0x69, 0x27, 0x11,
+  0xcb, 0xac, 0xde, 0x98, 0xf8, 0xc2, 0x9b, 0x7b, 0x8c, 0x38, 0x45, 0x2f,
+  0xe4, 0x60, 0xa0, 0x37, 0x3a, 0xc6, 0x3c, 0x7b, 0x40, 0xf2, 0x92, 0xa6,
+  0x35, 0x37, 0x91, 0xa6, 0x39, 0x75, 0xdf, 0x99, 0x30, 0x5c, 0x1c, 0x4f,
+  0x96, 0xf6, 0xdc, 0x3d, 0xb3, 0xa2, 0x9e, 0xec, 0xaf, 0xf3, 0x2e, 0x5c,
+  0xb3, 0xbe, 0x56, 0x17, 0x64, 0xb3, 0xe4, 0x63, 0x17, 0x25, 0xd9, 0x58,
+  0xee, 0xaf, 0x3a, 0xe5, 0x01, 0xa5, 0xb5, 0xc8, 0x0f, 0xb7, 0xad, 0x79,
+  0xd8, 0xd8, 0x02, 0x92, 0xe5, 0x7e, 0x16, 0x85, 0x3f, 0x1c, 0x84, 0x52,
+  0x09, 0x4b, 0x0a, 0xb7, 0xc3, 0xe9, 0x51, 0x67, 0x6e, 0x63, 0xa1, 0x49,
+  0x77, 0x08, 0xa9, 0x8b, 0x8e, 0x00, 0xc3, 0x5e, 0xb4, 0x91, 0x61, 0xf9,
+  0x4d, 0xb5, 0xc1, 0x9a, 0xd3, 0x6a, 0xdf, 0x0a, 0x5d, 0x88, 0x0c, 0xbe,
+  0xd6, 0xde, 0x6e, 0xa3, 0xe3, 0xd0, 0xb0, 0xd2, 0xd0, 0x6a, 0x5a, 0x76,
+  0x4b, 0x61, 0xe3, 0x15, 0x56, 0x5a, 0x69, 0x7c, 0x88, 0x07, 0x26, 0x24,
+  0x4a, 0x6b, 0xe5, 0x01, 0x4f, 0x94, 0x76, 0xda, 0x84, 0xc4, 0x83, 0x40,
+  0xbb, 0x20, 0x38, 0x34, 0x4a, 0x6d, 0x66, 0xf6, 0xe9, 0xf5, 0x93, 0x97,
+  0xf9, 0x53, 0x9b, 0x27, 0xf7, 0x1b, 0x5a, 0x74, 0x77, 0xad, 0x68, 0xa3,
+  0x90, 0x64, 0xc3, 0x0d, 0x7b, 0xbf, 0x5b, 0x57, 0xfe, 0x02, 0xfc, 0x7f,
+  0x81, 0x02, 0xf8, 0x8b, 0x40, 0x41, 0xe3, 0x77, 0x06, 0x91, 0xac, 0x84,
+  0xbe, 0x97, 0xc7, 0xba, 0x38, 0xc0, 0xe1, 0xcc, 0x6c, 0xfc, 0x4a, 0x09,
+  0x87, 0x2c, 0xf5, 0x63, 0x2d, 0x9c, 0x67, 0x36, 0x5e, 0xd7, 0xfa, 0xf9,
+  0xa8, 0x26, 0xc1, 0xdf, 0x79, 0xf5, 0xfd, 0x71, 0xdd, 0xf5, 0xb6, 0xc0,
+  0xf2, 0xcb, 0xf7, 0xe6, 0x62, 0x3c, 0xec, 0x5f, 0x57, 0xb8, 0x01, 0xcc,
+  0x06, 0xe1, 0x37, 0xdb, 0x6c, 0xc0, 0x7f, 0x6a, 0xc1, 0x2f, 0xe5, 0xff,
+  0xff, 0xf9, 0x1f, 0xa1, 0xc6, 0xa0, 0x64, 0x16, 0x1a, 0x00, 0x00
 };
-unsigned int http_html_backup_len = 2393;
+unsigned int http_html_backup_len = 2423;

+ 10 - 4
docs/en/modules/enduser-setup.md

@@ -7,7 +7,8 @@ This module provides a simple way of configuring ESP8266 chips without using a s
 
 ![enduser setup config dialog](../../img/enduser-setup.jpg "enduser setup config dialog")
 
-After running [`enduser_setup.start()`](#enduser_setupstart), a wireless network named "SetupGadget_XXXXXX" will start. Connect to that SSID and then navigate to the root
+After running [`enduser_setup.start()`](#enduser_setupstart), a wireless network named "SetupGadget_XXXXXX" will start (this prefix can be overridden in `user_config.h` by defining 
+`ENDUSER_SETUP_AP_SSID`). Connect to that SSID and then navigate to the root
 of any website (e.g., `http://example.com/` will work, but do not use `.local` domains because it will fail on iOS). A web page similar to the picture above will load, allowing the 
 end user to provide their Wi-Fi information.
 
@@ -16,7 +17,9 @@ teardown to allow connected clients to obtain a last status message while the So
 
 Alternative HTML can be served by placing a file called `enduser_setup.html` on the filesystem. Everything needed by the web page must be included in this one file. This file will be kept 
 in RAM, so keep it as small as possible. The file can be gzip'd ahead of time to reduce the size (i.e., using `gzip -n` or `zopfli`), and when served, the End User Setup module will add 
-the appropriate `Content-Encoding` header to the response. *Note: Even if gzipped, the file still needs to be named `enduser_setup.html`.*
+the appropriate `Content-Encoding` header to the response. 
+
+*Note: If gzipped, the file can also be named `enduser_setup.html.gz` for semantic purposes. Gzip encoding is determined by the file's contents, not the filename.*
 
 The following HTTP endpoints exist:
 
@@ -64,7 +67,9 @@ enduser_setup.start(
 
 ## enduser_setup.start()
 
-Starts the captive portal.
+Starts the captive portal. 
+
+*Note: Calling start() while EUS is already running is an error, and will result in stop() to be invoked to shut down EUS.*
 
 #### Syntax
 `enduser_setup.start([onConnected()], [onError(err_num, string)], [onDebug(string)])`
@@ -85,7 +90,8 @@ enduser_setup.start(
   end,
   function(err, str)
     print("enduser_setup: Err #" .. err .. ": " .. str)
-  end
+  end,
+  print -- Lua print function can serve as the debug callback
 );
 ```