Save the post data in a file on the filesystem (#2810)

* Use cross-browser JS for query params in EUS

* Update EUS doc to explain how to use parameters

* Remove ; in Lua code

* Rewrite the endpoint table

* Do not use properties as global Lua variables

* remove enduser_setup.html.gz

* rename folder 'eus' to 'enduser_setup'

* Change input type for password to "password"

* Replace outdated captive portal screen shot
This commit is contained in:
Marcel Stör 2019-07-08 21:48:16 +02:00 committed by GitHub
parent bc7ffb3eb8
commit 0398c3360b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 547 additions and 297 deletions

View File

@ -93,6 +93,7 @@ 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_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"; static const char http_header_204[] = "HTTP/1.1 204 No Content\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
static const char http_header_302[] = "HTTP/1.1 302 Moved\r\nLocation: /\r\nContent-Length:0\r\nConnection:close\r\n\r\n"; static const char http_header_302[] = "HTTP/1.1 302 Moved\r\nLocation: /\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
static const char http_header_302_trying[] = "HTTP/1.1 302 Moved\r\nLocation: /?trying=true\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
static const char http_header_400[] = "HTTP/1.1 400 Bad request\r\nContent-Length:0\r\nConnection:close\r\n\r\n"; static const char http_header_400[] = "HTTP/1.1 400 Bad request\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
static const char http_header_404[] = "HTTP/1.1 404 Not found\r\nContent-Length:0\r\nConnection:close\r\n\r\n"; static const char http_header_404[] = "HTTP/1.1 404 Not found\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
static const char http_header_405[] = "HTTP/1.1 405 Method Not Allowed\r\nContent-Length:0\r\nConnection:close\r\n\r\n"; static const char http_header_405[] = "HTTP/1.1 405 Method Not Allowed\r\nContent-Length:0\r\nConnection:close\r\n\r\n";
@ -101,8 +102,8 @@ 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_header_content_len_fmt[] = "Content-length:%5d\r\n\r\n";
static const char http_html_gzip_contentencoding[] = "Content-Encoding: gzip\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 enduser_setup_html_default[] = ... */
#include "eus/http_html_backup.def" #include "enduser_setup/enduser_setup.html.gz.def.h"
typedef struct scan_listener typedef struct scan_listener
{ {
@ -398,9 +399,9 @@ static err_t close_once_sent (void *arg, struct tcp_pcb *pcb, u16_t len)
/** /**
* Search String * Search String
* *
* Search string for first occurance of any char in srch_str. * Search string for first occurence of any char in srch_str.
* *
* @return -1 iff no occurance of char was found. * @return -1 if no occurence of char was found.
*/ */
static int enduser_setup_srch_str(const char *str, const char *srch_str) static int enduser_setup_srch_str(const char *str, const char *srch_str)
{ {
@ -418,9 +419,9 @@ static int enduser_setup_srch_str(const char *str, const char *srch_str)
/** /**
* Load HTTP Payload * Load HTTP Payload
* *
* @return - 0 iff payload loaded successfully * @return - 0 if payload loaded successfully
* 1 iff backup html was loaded * 1 if default html was loaded
* 2 iff out of memory * 2 if out of memory
*/ */
static int enduser_setup_http_load_payload(void) static int enduser_setup_http_load_payload(void)
{ {
@ -466,16 +467,16 @@ static int enduser_setup_http_load_payload(void)
if (!f || err == VFS_RES_ERR || err2 == VFS_RES_ERR) if (!f || err == VFS_RES_ERR || err2 == VFS_RES_ERR)
{ {
ENDUSER_SETUP_DEBUG("Unable to load file enduser_setup.html, loading backup HTML..."); ENDUSER_SETUP_DEBUG("Unable to load file enduser_setup.html, loading default HTML...");
c_sprintf(cl_hdr, http_header_content_len_fmt, sizeof(http_html_backup)); c_sprintf(cl_hdr, http_header_content_len_fmt, sizeof(enduser_setup_html_default));
cl_len = c_strlen(cl_hdr); cl_len = c_strlen(cl_hdr);
int html_len = LITLEN(http_html_backup); int html_len = LITLEN(enduser_setup_html_default);
if (http_html_backup[0] == 0x1f && http_html_backup[1] == 0x8b) if (enduser_setup_html_default[0] == 0x1f && enduser_setup_html_default[1] == 0x8b)
{ {
ce_len = c_strlen(http_html_gzip_contentencoding); ce_len = c_strlen(http_html_gzip_contentencoding);
html_len = http_html_backup_len; /* Defined in eus/http_html_backup.def by xxd -i */ html_len = enduser_setup_html_default_len; /* Defined in enduser_setup/enduser_setup.html.gz.def.h by xxd -i */
ENDUSER_SETUP_DEBUG("Content is gzipped"); ENDUSER_SETUP_DEBUG("Content is gzipped");
} }
@ -499,7 +500,7 @@ static int enduser_setup_http_load_payload(void)
c_memcpy(&(state->http_payload_data[offset]), &(cl_hdr), cl_len); c_memcpy(&(state->http_payload_data[offset]), &(cl_hdr), cl_len);
offset += cl_len; offset += cl_len;
c_memcpy(&(state->http_payload_data[offset]), &(http_html_backup), sizeof(http_html_backup)); c_memcpy(&(state->http_payload_data[offset]), &(enduser_setup_html_default), sizeof(enduser_setup_html_default));
return 1; return 1;
} }
@ -548,7 +549,7 @@ static int enduser_setup_http_load_payload(void)
* *
* Parse escaped and form encoded data of request. * Parse escaped and form encoded data of request.
* *
* @return - return 0 iff the HTTP parameter is decoded into a valid string. * @return - return 0 if the HTTP parameter is decoded into a valid string.
*/ */
static int enduser_setup_http_urldecode(char *dst, const char *src, int src_len, int dst_len) static int enduser_setup_http_urldecode(char *dst, const char *src, int src_len, int dst_len)
{ {
@ -631,13 +632,167 @@ static void do_station_cfg (task_param_t param, uint8_t prio)
luaM_free(lua_getstate(), cnf); luaM_free(lua_getstate(), cnf);
} }
/**
* Count the number of occurences of a character in a string
*
* return the number of times the character was encountered in the string
*/
static int count_char_occurence(const char *input, const char char_to_count) {
const char *current = input;
int occur = 0;
while (*current != 0) {
if (*current == char_to_count) occur++;
current++;
}
return occur;
}
/* structure used to store the key/value pairs that we find in a HTTP POST body */
struct keypairs_t {
char **keypairs;
int keypairs_nb;
};
static void enduser_setup_free_keypairs(struct keypairs_t *kp) {
if (kp == NULL) return;
if (kp->keypairs != NULL) {
for (int i = 0; i < kp->keypairs_nb * 2; i++) {
os_free(kp->keypairs[i]);
}
}
os_free(kp->keypairs);
os_free(kp);
}
static struct keypairs_t * enduser_setup_alloc_keypairs(int kp_number ){
struct keypairs_t *kp = os_malloc(sizeof(struct keypairs_t));
os_memset(kp, 0, sizeof(struct keypairs_t));
kp->keypairs = os_malloc(kp_number * 2 * sizeof(char *));
kp->keypairs_nb = kp_number;
return kp;
}
/**
* Parses a form-urlencoded body into a struct keypairs_t, which contains an array of key,values strings and the size of the array.
*/
static struct keypairs_t *enduser_setup_get_keypairs_from_form(char *form_body, int form_length) {
int keypair_nb = count_char_occurence(form_body, '&') + 1;
int equal_nb = count_char_occurence(form_body, '=');
if (keypair_nb == 1 && equal_nb == 0) {
ENDUSER_SETUP_DEBUG("No keypair in form body");
return NULL;
}
struct keypairs_t *kp = enduser_setup_alloc_keypairs(keypair_nb);
int current_idx = 0;
int err;
char *body_copy = os_malloc(form_length+1);
os_bzero(body_copy, form_length+1);
os_memcpy(body_copy, form_body, form_length);
char *tok = strtok(body_copy, "=");
char last_tok = '=';
while (tok) {
size_t len = strlen(tok);
kp->keypairs[current_idx] = os_malloc(len + 1);
err = enduser_setup_http_urldecode(kp->keypairs[current_idx], tok, len, len + 1);
if (err) {
ENDUSER_SETUP_DEBUG("Unable to decode parameter");
enduser_setup_free_keypairs(kp);
os_free(body_copy);
return NULL;
}
current_idx++;
if (current_idx > keypair_nb*2) {
ENDUSER_SETUP_DEBUG("Too many keypairs!");
enduser_setup_free_keypairs(kp);
os_free(body_copy);
return NULL;
}
if (last_tok == '=') {
tok = strtok(NULL, "&"); // now search for the '&'
last_tok='&';
} else {
tok = strtok(NULL, "="); // search for the next '='
last_tok='=';
}
}
os_free(body_copy);
return kp;
}
/**
* This function saves the form data received when the configuration is sent to the ESP into a eus_params.lua file
*/
static int enduser_setup_write_file_with_extra_configuration_data(char *form_body, int form_length) {
ENDUSER_SETUP_DEBUG("enduser: write data from posted form");
ENDUSER_SETUP_DEBUG(form_body);
// We will save the form data into a file in the LUA format: KEY="VALUE", so that configuration data is available for load in the lua code.
// As input, we have a string as such: "key1=value1&key2=value2&key3=value%203" (urlencoded), the number of '&' tells us how many keypairs there are (the count + 1)
struct keypairs_t *kp = enduser_setup_get_keypairs_from_form(form_body, form_length);
if (kp == NULL || kp->keypairs_nb == 0) {
ENDUSER_SETUP_DEBUG("enduser: No extra configuration.");
if (kp != NULL) enduser_setup_free_keypairs(kp);
return 1;
}
// Now that we have the keys and the values, let's save them in a lua file
int p_file = vfs_open("eus_params.lua", "w");
if (p_file == 0)
{
ENDUSER_SETUP_DEBUG("Can't open file in write mode!");
enduser_setup_free_keypairs(kp);
return 1;
}
// write all key pairs as KEY="VALUE"\n into a Lua table, example:
// local p = {}
// p.wifi_ssid="ssid"
// p.wifi_password="password"
// p.device_name="foo-node"
// return p
vfs_write(p_file, "local p={}\n", 11);
int idx = 0;
for( idx = 0; idx < kp->keypairs_nb*2; idx=idx+2){
char* to_write = kp->keypairs[idx];
size_t length = c_strlen(to_write);
vfs_write(p_file, "p.", 2);
vfs_write(p_file, to_write, length);
vfs_write(p_file, "=\"", 2);
to_write = kp->keypairs[idx+1];
length = c_strlen(to_write);
vfs_write(p_file, to_write, length);
vfs_write(p_file, "\"\n", 2);
}
vfs_write(p_file, "return p\n", 9);
vfs_close(p_file);
enduser_setup_free_keypairs(kp);
// TODO: we could call back in the LUA with an associative table setup, but this is MVP2...
return 0;
}
/** /**
* Handle HTTP Credentials * Handle HTTP Credentials
* *
* @return - return 0 iff credentials are found and handled successfully * @return - return 0 if credentials are found and handled successfully
* return 1 iff credentials aren't found * return 1 if credentials aren't found
* return 2 iff an error occured * return 2 if an error occured
*/ */
static int enduser_setup_http_handle_credentials(char *data, unsigned short data_len) static int enduser_setup_http_handle_credentials(char *data, unsigned short data_len)
{ {
@ -682,7 +837,6 @@ static int enduser_setup_http_handle_credentials(char *data, unsigned short data
return 1; return 1;
} }
ENDUSER_SETUP_DEBUG(""); ENDUSER_SETUP_DEBUG("");
ENDUSER_SETUP_DEBUG("WiFi Credentials Stored"); ENDUSER_SETUP_DEBUG("WiFi Credentials Stored");
ENDUSER_SETUP_DEBUG("-----------------------"); ENDUSER_SETUP_DEBUG("-----------------------");
@ -702,7 +856,7 @@ static int enduser_setup_http_handle_credentials(char *data, unsigned short data
/** /**
* Serve HTML * Serve HTML
* *
* @return - return 0 iff html was served successfully * @return - return 0 if html was served successfully
*/ */
static int enduser_setup_http_serve_header(struct tcp_pcb *http_client, const char *header, uint32_t header_len) static int enduser_setup_http_serve_header(struct tcp_pcb *http_client, const char *header, uint32_t header_len)
{ {
@ -763,7 +917,7 @@ static err_t streamout_sent (void *arg, struct tcp_pcb *pcb, u16_t len)
/** /**
* Serve HTML * Serve HTML
* *
* @return - return 0 iff html was served successfully * @return - return 0 if html was served successfully
*/ */
static int enduser_setup_http_serve_html(struct tcp_pcb *http_client) static int enduser_setup_http_serve_html(struct tcp_pcb *http_client)
{ {
@ -957,6 +1111,37 @@ static void enduser_setup_handle_OPTIONS (struct tcp_pcb *http_client, char *dat
} }
static err_t enduser_setup_handle_POST(struct tcp_pcb *http_client, char* data, size_t data_len)
{
ENDUSER_SETUP_DEBUG("Handling POST");
if (c_strncmp(data + 5, "/setwifi ", 9) == 0) // User clicked the submit button
{
switch (enduser_setup_http_handle_credentials(data, data_len))
{
case 0: {
// all went fine, extract all the form data into a file
char* body=strstr(data, "\r\n\r\n");
char *content_length_str = strstr(data, "Content-Length: ");
if( body != NULL && content_length_str != NULL){
int bodylength = c_atoi(content_length_str + 16);
body += 4; // length of the double CRLF found above
enduser_setup_write_file_with_extra_configuration_data(body, bodylength);
}
// redirect user to the base page with the trying flag
enduser_setup_http_serve_header(http_client, http_header_302_trying, LITLEN(http_header_302_trying));
break;
}
case 1:
enduser_setup_http_serve_header(http_client, http_header_400, LITLEN(http_header_400));
break;
default:
ENDUSER_SETUP_ERROR("http_recvcb failed. Failed to handle wifi credentials.", ENDUSER_SETUP_ERR_UNKOWN_ERROR, ENDUSER_SETUP_ERR_NONFATAL);
break;
}
}
}
/* --- WiFi AP scanning support -------------------------------------------- */ /* --- WiFi AP scanning support -------------------------------------------- */
static void free_scan_listeners (void) static void free_scan_listeners (void)
@ -1165,7 +1350,7 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
if (c_strncmp(data, "GET ", 4) == 0) if (c_strncmp(data, "GET ", 4) == 0)
{ {
if (c_strncmp(data + 4, "/ ", 2) == 0) if (c_strncmp(data + 4, "/ ", 2) == 0 || c_strncmp(data + 4, "/?", 2) == 0)
{ {
if (enduser_setup_http_serve_html(http_client) != 0) if (enduser_setup_http_serve_html(http_client) != 0)
{ {
@ -1237,21 +1422,6 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
break; break;
} }
} }
else if (c_strncmp(data + 4, "/setwifi?", 9) == 0)
{
switch (enduser_setup_http_handle_credentials(data, data_len))
{
case 0:
enduser_setup_serve_status_as_json(http_client);
break;
case 1:
enduser_setup_http_serve_header(http_client, http_header_400, LITLEN(http_header_400));
break;
default:
ENDUSER_SETUP_ERROR("http_recvcb failed. Failed to handle wifi credentials.", ENDUSER_SETUP_ERR_UNKOWN_ERROR, ENDUSER_SETUP_ERR_NONFATAL);
break;
}
}
else if (c_strncmp(data + 4, "/generate_204", 13) == 0) else if (c_strncmp(data + 4, "/generate_204", 13) == 0)
{ {
/* Convince Android devices that they have internet access to avoid pesky dialogues. */ /* Convince Android devices that they have internet access to avoid pesky dialogues. */
@ -1267,6 +1437,10 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
{ {
enduser_setup_handle_OPTIONS(http_client, data, data_len); enduser_setup_handle_OPTIONS(http_client, data, data_len);
} }
else if (c_strncmp(data, "POST ", 5) == 0)
{
enduser_setup_handle_POST(http_client, data, data_len);
}
else /* not GET or OPTIONS */ else /* not GET or OPTIONS */
{ {
enduser_setup_http_serve_header(http_client, http_header_405, LITLEN(http_header_405)); enduser_setup_http_serve_header(http_client, http_header_405, LITLEN(http_header_405));
@ -1279,6 +1453,7 @@ free_out:
return ret; return ret;
} }
static err_t enduser_setup_http_connectcb(void *arg, struct tcp_pcb *pcb, err_t err) static err_t enduser_setup_http_connectcb(void *arg, struct tcp_pcb *pcb, err_t err)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_connectcb"); ENDUSER_SETUP_DEBUG("enduser_setup_http_connectcb");
@ -1332,7 +1507,7 @@ static int enduser_setup_http_start(void)
int err = enduser_setup_http_load_payload(); int err = enduser_setup_http_load_payload();
if (err == 1) if (err == 1)
{ {
ENDUSER_SETUP_DEBUG("enduser_setup_http_start info. Loaded backup HTML."); ENDUSER_SETUP_DEBUG("enduser_setup_http_start info. Loaded default HTML.");
} }
else if (err == 2) else if (err == 2)
{ {

View File

@ -0,0 +1 @@
*.sh text eol=lf

1
app/modules/enduser_setup/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
enduser_setup.html.gz

View File

@ -153,14 +153,17 @@
<div id=deviceId></div> <div id=deviceId></div>
<div id=f1> <div id=f1>
<h3>Connect device to your Wi-Fi</h3> <h3>Connect device to your Wi-Fi</h3>
<button id=networks type=button class=utility></button> <form action="/setwifi" method="POST">
<div id=dropdown> <button id=networks type=button class=utility></button>
<span id=arrow>&#x25bc;</span> <div id=dropdown>
<select id=aplist name=aplist></select> <span id=arrow>&#x25bc;</span>
</div> <select id=aplist name=aplist></select>
<input id=ssid type=text autocorrect=off autocapitalize=none placeholder='Wi-Fi Name' /> </div>
<input id=wifi_password type=text autocorrect=off autocapitalize=none autocomplete=off placeholder=Password /> <input id=ssid name=wifi_ssid type=text autocorrect=off autocapitalize=none placeholder='Wi-Fi Name' />
<button id=submit type=button>Save</button> <input name=wifi_password type=password autocorrect=off autocapitalize=none autocomplete=off placeholder=Password />
<!-- You can add inputs here and have them pop up in your lua code through the file eus_params.lua -->
<input type="submit" value="Save"/>
</form>
</div> </div>
<div id=f2> <div id=f2>
<h1>Success!</h1> <h1>Success!</h1>
@ -180,6 +183,11 @@
var ab = $('#networks'), ap = $('#aplist'); var ab = $('#networks'), ap = $('#aplist');
var stopAll = false, ra, rs, submitted = false; var stopAll = false, ra, rs, submitted = false;
$.urlParam = function (name) {
var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href);
if (results == null) { return null;}
else { return decodeURI(results[1]) || 0;}
}
function show(f, y) { function show(f, y) {
if (y == null) y = f; if (y == null) y = f;
$(f).style.display = y == f ? 'block' : 'none'; $(f).style.display = y == f ? 'block' : 'none';
@ -240,13 +248,6 @@
} }
} }
} }
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) { function fetch(url, method, callback, time_out) {
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.onloadend = function () { xhr.onloadend = function () {
@ -305,18 +306,19 @@
fetch('/aplist?n=' + Math.random(), 'GET', gotAp, 10); fetch('/aplist?n=' + Math.random(), 'GET', gotAp, 10);
} }
window.onload = function() { window.onload = function() {
ab.innerText = 'Scan for Networks'; let trying = $.urlParam('trying');
ab.onclick = refrAp; ab.innerText = 'Scan for Networks';
$('#aplist').onchange = function () { ab.onclick = refrAp;
$('#ssid').value = $('#aplist').value; $('#aplist').onchange = function () {
}; $('#ssid').value = $('#aplist').value;
$('#submit').onclick = submit; };
$('#bk2').onclick = function () { $('#bk2').onclick = function () {
cur('#f1') cur('#f1')
} }
rs = to(refr, 0.5); rs = to(refr, 0.5);
if( trying ) cur("#f3");
} }
</script> </script>
</body> </body>
</html> </html>

View File

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

View File

@ -3,5 +3,5 @@
# Uses zopfli for better gzip compression # Uses zopfli for better gzip compression
# sudo apt-get install zopfli # sudo apt-get install zopfli
zopfli --gzip ./enduser_setup.html zopfli --gzip ./enduser_setup.html
xxd -i ./enduser_setup.html.gz | sed 's/unsigned char/static const char/; s/__enduser_setup_html_gz/http_html_backup/' > http_html_backup.def xxd -i ./enduser_setup.html.gz | sed 's/unsigned char/static const char/; s/__enduser_setup_html_gz/enduser_setup_html_default/' > enduser_setup.html.gz.def.h

View File

@ -1,205 +0,0 @@
static const char http_html_backup[] = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x95, 0x59,
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 = 2423;

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@ -3,49 +3,107 @@
| :----- | :-------------------- | :---------- | :------ | | :----- | :-------------------- | :---------- | :------ |
| 2015-09-02 | [Robert Foss](https://github.com/robertfoss) | [Robert Foss](https://github.com/robertfoss) | [enduser_setup.c](../../app/modules/enduser_setup.c)| | 2015-09-02 | [Robert Foss](https://github.com/robertfoss) | [Robert Foss](https://github.com/robertfoss) | [enduser_setup.c](../../app/modules/enduser_setup.c)|
This module provides a simple way of configuring ESP8266 chips without using a serial interface or pre-programming WiFi credentials onto the chip. This module provides a simple way of configuring ESP8266 chips without using a
serial interface or pre-programming WiFi credentials onto the chip.
![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 starting. 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 or to 192.168.4.1.
`http://example.com/` will work, but do not use `.local` domains because it
will fail on iOS. A web page similar to the one depicted below will load,
allowing the end user to provide their Wi-Fi credentials.
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 config dialog](../img/enduser-setup-captive-portal.png "enduser setup config dialog")
`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.
After an IP address has been successfully obtained, then this module will stop as if [`enduser_setup.stop()`](#enduser_setupstop) had been called. There is a 10-second delay before After an IP address has been successfully obtained, then this module will stop
teardown to allow connected clients to obtain a last status message while the SoftAP is still active. as if [`enduser_setup.stop()`](#enduser_setupstop) had been called. There is a
10-second delay before teardown to allow connected clients to obtain a last
status message while the SoftAP is still active.
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 Alternative HTML can be served by placing a file called `enduser_setup.html` on
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 filesystem. Everything needed by the web page must be included in this one
the appropriate `Content-Encoding` header to the response. 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: 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.* *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: ### Additional configuration parameters
You can also add some additional inputs in the `enduser_setup.html` (as long as
you keep those needed for the WiFi setup). The additional data will be written
in a `eus_params.lua` file in the root filesystem of the ESP8266, which you can
then load in your own code. In this case, the data will be saved as a set of
variables with the name being the input name, and the value being a string
representing what you put in the form.
For instance, if your HTML contains two additional inputs:
```html
<input name=timeout_delay type=text placeholder="Delay in seconds" />
<input name=device_name type=text placeholder="Unique device name" />
```
Then the `eus_params.lua` file will contain the following:
```lua
-- those wifi_* are the base parameters that are saved anyway
local p = {}
p.wifi_ssid="ssid"
p.wifi_password="password"
-- your own parameters:
p.timeout_delay="xxx"
p.device_name="yyy"
return p
```
### How to use the eus_params.lua file
Simply include the file by using the `dofile` function:
```lua
p = dofile('eus_params.lua')
-- now use the parameters in the Lua table
print("Wifi device_name: " .. p.device_name)
```
### HTTP endpoints:
|Path|Method|Description|
|----|------|-----------|
|/|GET|Returns HTML for the web page. Will return the contents of `enduser_setup.html` if it exists on the filesystem, otherwise will return a page embedded into the firmware image.|
|/aplist|GET|Forces the ESP8266 to perform a site survey across all channels, reporting access points that it can find. Return payload is a JSON array: `[{"ssid":"foobar","rssi":-36,"chan":3}]`|
|/generate_204|GET|Returns a HTTP 204 status (expected by certain Android clients during Wi-Fi connectivity checks)|
|/status|GET|Returns plaintext status description, used by the web page|
|/status.json|GET|Returns a JSON payload containing the ESP8266's chip id in hexadecimal format and the status code: 0=Idle, 1=Connecting, 2=Wrong Password, 3=Network not Found, 4=Failed, 5=Success|
|/setwifi|POST|HTML form post for setting the WiFi credentials. Expects HTTP content type `application/x-www-form-urlencoded`. Supports sending and storing additinal configuration parameters (as input fields). Returns the same payload as `/status.json` instead of redirecting to `/`. See also: `/update`.|
|/update|GET|Data submission target. Example: `http://example.com/update?wifi_ssid=foobar&wifi_password=CorrectHorseBatteryStaple`. Will redirect to `/` when complete. Note that will NOT update the `eus_params.lua` file i.e. it does NOT support sending arbitrary parameters. See also: `/setwifi`. |
Module functions are described below.
|Endpoint|Description|
|--------|-----------|
|/|Returns HTML for the web page. Will return the contents of `enduser_setup.html` if it exists on the filesystem, otherwise will return a page embedded into the firmware image.|
|/aplist|Forces the ESP8266 to perform a site survey across all channels, reporting access points that it can find. Return payload is a JSON array: `[{"ssid":"foobar","rssi":-36,"chan":3}]`|
|/generate_204|Returns a HTTP 204 status (expected by certain Android clients during Wi-Fi connectivity checks)|
|/status|Returns plaintext status description, used by the web page|
|/status.json|Returns a JSON payload containing the ESP8266's chip id in hexadecimal format and the status code: 0=Idle, 1=Connecting, 2=Wrong Password, 3=Network not Found, 4=Failed, 5=Success|
|/setwifi|Endpoint intended for services to use for setting the wifi credentials. Identical to `/update` except returns the same payload as `/status.json` instead of redirecting to `/`.|
|/update|Form submission target. Example: `http://example.com/update?wifi_ssid=foobar&wifi_password=CorrectHorseBatteryStaple`. Must be a GET request. Will redirect to `/` when complete. |
## enduser_setup.manual() ## enduser_setup.manual()
Controls whether manual AP configuration is used. Controls whether manual AP configuration is used.
By default the `enduser_setup` module automatically configures an open access point when starting, and stops it when the device has been successfully joined to a WiFi network. If manual mode has been enabled, neither of this is done. The device must be manually configured for `wifi.SOFTAP` mode prior to calling `enduser_setup.start()`. Additionally, the portal is not stopped after the device has successfully joined to a WiFi network. By default the `enduser_setup` module automatically configures an open access
point when starting, and stops it when the device has been successfully joined
to a WiFi network. If manual mode has been enabled, neither of this is done.
The device must be manually configured for `wifi.SOFTAP` mode prior to calling
`enduser_setup.start()`. Additionally, the portal is not stopped after the
device has successfully joined to a WiFi network.
#### Syntax #### Syntax
`enduser_setup.manual([on_off])` `enduser_setup.manual([on_off])`
#### Parameters #### Parameters
- `on_off` a boolean value indicating whether to use manual mode; if not given, the function only returns the current setting. - `on_off` a boolean value indicating whether to use manual mode; if not
given, the function only returns the current setting.
#### Returns #### Returns
The current setting, true if manual mode is enabled, false if it is not. The current setting, true if manual mode is enabled, false if it is not.
@ -57,12 +115,12 @@ wifi.ap.config({ssid="MyPersonalSSID", auth=wifi.OPEN})
enduser_setup.manual(true) enduser_setup.manual(true)
enduser_setup.start( enduser_setup.start(
function() function()
print("Connected to wifi as:" .. wifi.sta.getip()) print("Connected to WiFi as:" .. wifi.sta.getip())
end, end,
function(err, str) function(err, str)
print("enduser_setup: Err #" .. err .. ": " .. str) print("enduser_setup: Err #" .. err .. ": " .. str)
end end
); )
``` ```
## enduser_setup.start() ## enduser_setup.start()
@ -86,13 +144,13 @@ Starts the captive portal.
```lua ```lua
enduser_setup.start( enduser_setup.start(
function() function()
print("Connected to wifi as:" .. wifi.sta.getip()) print("Connected to WiFi as:" .. wifi.sta.getip())
end, end,
function(err, str) function(err, str)
print("enduser_setup: Err #" .. err .. ": " .. str) print("enduser_setup: Err #" .. err .. ": " .. str)
end, end,
print -- Lua print function can serve as the debug callback print -- Lua print function can serve as the debug callback
); )
``` ```
## enduser_setup.stop() ## enduser_setup.stop()