Improve the enduser setup experience by triggering captive portal detection. (#3282)

* Make captive portal detection work on macOS
* Change the default SSID prefix to be NodeMCU
This commit is contained in:
Philip Gladstone 2020-09-18 17:47:52 -04:00 committed by GitHub
parent dc334f87a6
commit 9d74cd5aa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 346 additions and 291 deletions

View File

@ -174,7 +174,7 @@
// If you use the enduser_setup module, then you can also set the default // If you use the enduser_setup module, then you can also set the default
// SSID when this module is running in AP mode. // SSID when this module is running in AP mode.
#define ENDUSER_SETUP_AP_SSID "SetupGadget" #define ENDUSER_SETUP_AP_SSID "NodeMCU"
// I2C software driver partially supports use of GPIO16 (D0) pin for SCL line. // I2C software driver partially supports use of GPIO16 (D0) pin for SCL line.

View File

@ -92,7 +92,7 @@ static const char http_html_gz_filename[] = "enduser_setup.html.gz";
static const char http_html_filename[] = "enduser_setup.html"; 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; charset=utf-8\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; charset=utf-8\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: http://nodemcu.portal/\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_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:10\r\nConnection:close\r\n\r\nNot found\n"; static const char http_header_404[] = "HTTP/1.1 404 Not found\r\nContent-Length:10\r\nConnection:close\r\n\r\nNot found\n";
@ -135,6 +135,7 @@ typedef struct
struct tcp_pcb *http_pcb; struct tcp_pcb *http_pcb;
char *http_payload_data; char *http_payload_data;
uint32_t http_payload_len; uint32_t http_payload_len;
char *ap_ssid;
os_timer_t check_station_timer; os_timer_t check_station_timer;
os_timer_t shutdown_timer; os_timer_t shutdown_timer;
int lua_connected_cb_ref; int lua_connected_cb_ref;
@ -931,6 +932,8 @@ static err_t streamout_sent (void *arg, struct tcp_pcb *pcb, u16_t len)
{ {
tcp_sent (pcb, 0); tcp_sent (pcb, 0);
deferred_close (pcb); deferred_close (pcb);
free(state->http_payload_data);
state->http_payload_data = NULL;
} }
else else
tcp_arg (pcb, (void *)offs); tcp_arg (pcb, (void *)offs);
@ -1123,9 +1126,9 @@ static void enduser_setup_handle_OPTIONS (struct tcp_pcb *http_client, char *dat
int type = 0; int type = 0;
if (strncmp(data, "GET ", 4) == 0) if (strncmp(data, "OPTIONS ", 8) == 0)
{ {
if (strncmp(data + 4, "/aplist", 7) == 0 || strncmp(data + 4, "/setwifi?", 9) == 0 || strncmp(data + 4, "/status.json", 12) == 0) if (strncmp(data + 8, "/aplist", 7) == 0 || strncmp(data + 8, "/setwifi?", 9) == 0 || strncmp(data + 8, "/status.json", 12) == 0)
{ {
enduser_setup_http_serve_header (http_client, json, strlen(json)); enduser_setup_http_serve_header (http_client, json, strlen(json));
return; return;
@ -1283,7 +1286,7 @@ static void on_scan_done (void *arg, STATUS status)
const size_t hdr_sz = sizeof (header_fmt) +1 -1; /* +expand %4d, -\0 */ 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 */ /* 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 = 35 + 2*32 + 9; /* {"ssid":"","rssi":,"chan":,"auth":} */
const size_t alloc_sz = hdr_sz + num_nets * max_entry_sz + 3; const size_t alloc_sz = hdr_sz + num_nets * max_entry_sz + 3;
char *http = calloc (1, alloc_sz); char *http = calloc (1, alloc_sz);
if (!http) if (!http)
@ -1319,6 +1322,12 @@ static void on_scan_done (void *arg, STATUS status)
p += sprintf (p, "%d", wn->channel); p += sprintf (p, "%d", wn->channel);
const char entry_auth[] = ",\"auth\":";
strcpy (p, entry_auth);
p += sizeof (entry_auth) -1;
p += sprintf (p, "%d", wn->authmode);
*p++ = '}'; *p++ = '}';
} }
*p++ = ']'; *p++ = ']';
@ -1579,15 +1588,10 @@ static err_t enduser_setup_http_recvcb(void *arg, struct tcp_pcb *http_client, s
break; break;
} }
} }
else if (strncmp(data + 4, "/generate_204", 13) == 0)
{
/* Convince Android devices that they have internet access to avoid pesky dialogues. */
enduser_setup_http_serve_header(http_client, http_header_204, LITLEN(http_header_204));
}
else else
{ {
ENDUSER_SETUP_DEBUG("serving 404"); // All other URLs redirect to http://nodemcu.portal/ -- this triggers captive portal.
enduser_setup_http_serve_header(http_client, http_header_404, LITLEN(http_header_404)); enduser_setup_http_serve_header(http_client, http_header_302, LITLEN(http_header_302));
} }
} }
else if (strncmp(data, "OPTIONS ", 8) == 0) else if (strncmp(data, "OPTIONS ", 8) == 0)
@ -1706,9 +1710,13 @@ static void enduser_setup_ap_start(void)
memset(&(cnf), 0, sizeof(struct softap_config)); memset(&(cnf), 0, sizeof(struct softap_config));
#ifndef ENDUSER_SETUP_AP_SSID #ifndef ENDUSER_SETUP_AP_SSID
#define ENDUSER_SETUP_AP_SSID "SetupGadget" #define ENDUSER_SETUP_AP_SSID "NodeMCU"
#endif #endif
if (state->ap_ssid) {
strncpy(cnf.ssid, state->ap_ssid, sizeof(cnf.ssid));
cnf.ssid_len = strlen(cnf.ssid);
} else {
char ssid[] = ENDUSER_SETUP_AP_SSID; char ssid[] = ENDUSER_SETUP_AP_SSID;
int ssid_name_len = strlen(ssid); int ssid_name_len = strlen(ssid);
memcpy(&(cnf.ssid), ssid, ssid_name_len); memcpy(&(cnf.ssid), ssid, ssid_name_len);
@ -1718,6 +1726,7 @@ static void enduser_setup_ap_start(void)
cnf.ssid[ssid_name_len] = '_'; cnf.ssid[ssid_name_len] = '_';
sprintf(cnf.ssid + ssid_name_len + 1, "%02X%02X%02X", mac[3], mac[4], mac[5]); sprintf(cnf.ssid + ssid_name_len + 1, "%02X%02X%02X", mac[3], mac[4], mac[5]);
cnf.ssid_len = ssid_name_len + 7; cnf.ssid_len = ssid_name_len + 7;
}
cnf.channel = state == NULL? 1 : state->softAPchannel; cnf.channel = state == NULL? 1 : state->softAPchannel;
cnf.authmode = AUTH_OPEN; cnf.authmode = AUTH_OPEN;
cnf.ssid_hidden = 0; cnf.ssid_hidden = 0;
@ -1895,6 +1904,8 @@ static void enduser_setup_free(void)
free_scan_listeners (); free_scan_listeners ();
free(state->ap_ssid);
free(state); free(state);
state = NULL; state = NULL;
} }
@ -1999,21 +2010,33 @@ static int enduser_setup_init(lua_State *L)
} }
} }
if (!lua_isnoneornil(L, 1)) int argno = 1;
if (lua_isstring(L, argno)) {
/* Get the SSID */
state->ap_ssid = strdup(lua_tostring(L, argno));
argno++;
}
if (!lua_isnoneornil(L, argno))
{ {
lua_pushvalue(L, 1); lua_pushvalue(L, argno);
state->lua_connected_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); state->lua_connected_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} }
if (!lua_isnoneornil(L, 2)) argno++;
if (!lua_isnoneornil(L, argno))
{ {
lua_pushvalue (L, 2); lua_pushvalue (L, argno);
state->lua_err_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); state->lua_err_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
} }
if (!lua_isnoneornil(L, 3)) argno++;
if (!lua_isnoneornil(L, argno))
{ {
lua_pushvalue (L, 3); lua_pushvalue (L, argno);
state->lua_dbg_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX); state->lua_dbg_cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
ENDUSER_SETUP_DEBUG("enduser_setup_init: Debug callback has been set"); ENDUSER_SETUP_DEBUG("enduser_setup_init: Debug callback has been set");
} }

View File

@ -160,7 +160,7 @@
<select id=aplist name=aplist></select> <select id=aplist name=aplist></select>
</div> </div>
<input id=ssid name=wifi_ssid type=text autocorrect=off autocapitalize=none placeholder='Wi-Fi Name' /> <input id=ssid name=wifi_ssid type=text autocorrect=off autocapitalize=none placeholder='Wi-Fi Name' />
<input name=wifi_password type=password autocorrect=off autocapitalize=none autocomplete=off placeholder=Password /> <input id=wifi_password 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 --> <!-- 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"/> <input type="submit" value="Save"/>
</form> </form>
@ -279,7 +279,8 @@
var ssid = list[i].ssid; var ssid = list[i].ssid;
if (!seen[ssid]) { if (!seen[ssid]) {
seen[ssid] = 1; seen[ssid] = 1;
ops += '<option>' + ssid.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;") + '</option>'; ops += '<option data-auth=' + list[i].auth + '>' +
ssid.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;") + '</option>';
} }
} }
ap.innerHTML = ops; ap.innerHTML = ops;
@ -302,6 +303,10 @@
hide('#ssid'); hide('#ssid');
ab.innerText = 'Manual Entry'; ab.innerText = 'Manual Entry';
} }
let pw = $('#wifi_password');
pw.placeholder = "Password";
pw.disabled = false;
pw.required = true;
} }
function refrAp() { function refrAp() {
ab.innerText = 'Searching for networks...'; ab.innerText = 'Searching for networks...';
@ -316,12 +321,23 @@
ab.onclick = refrAp; ab.onclick = refrAp;
$('#aplist').onchange = function () { $('#aplist').onchange = function () {
$('#ssid').value = $('#aplist').value; $('#ssid').value = $('#aplist').value;
let pw = $('#wifi_password');
if ($('#aplist').selectedOptions[0].dataset.auth > 0) {
pw.placeholder = "Password";
pw.disabled = false;
pw.required = true;
} else {
pw.placeholder = "Open -- no password";
pw.disabled = true;
pw.required = false;
}
}; };
$('#bk2').onclick = function () { $('#bk2').onclick = function () {
cur('#f1') cur('#f1')
} }
rs = to(refr, 0.5); rs = to(refr, 0.5);
if( trying ) cur("#f3"); if( trying ) cur("#f3");
refrAp();
} }
</script> </script>
</body> </body>

View File

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

View File

@ -7,9 +7,11 @@ This module provides a simple way of configuring ESP8266 chips without using a
serial interface or pre-programming WiFi credentials onto the chip. serial interface or pre-programming WiFi credentials onto the chip.
After running [`enduser_setup.start()`](#enduser_setupstart), a wireless After running [`enduser_setup.start()`](#enduser_setupstart), a wireless
network named "SetupGadget_XXXXXX" will starting. This prefix can be overridden network named "NodeMCU_XXXXXX" will start. This prefix can be overridden
in `user_config.h` by defining `ENDUSER_SETUP_AP_SSID`. Connect to that SSID in `user_config.h` by defining `ENDUSER_SETUP_AP_SSID` or by supplying the whole SSID to the
and then navigate to the root of any website or to 192.168.4.1. `enduser_setup.start` method. Connect to that SSID and captive portal detection on the client
should automatically open the configuration dialog. If not, 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 `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, 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. allowing the end user to provide their Wi-Fi credentials.
@ -76,7 +78,6 @@ print("Wifi device_name: " .. p.device_name)
|----|------|-----------| |----|------|-----------|
|/|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.| |/|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}]`| |/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|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| |/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`.| |/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`.|
@ -130,9 +131,10 @@ 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.* *Note: Calling start() while EUS is already running is an error, and will result in stop() to be invoked to shut down EUS.*
#### Syntax #### Syntax
`enduser_setup.start([onConnected()], [onError(err_num, string)], [onDebug(string)])` `enduser_setup.start([AP_SSID,] [onConnected()], [onError(err_num, string)], [onDebug(string)])`
#### Parameters #### Parameters
- `AP_SSID` the (optional) SSID to use for the AP. This defaults to `NodeMCU_<device id>`.
- `onConnected()` callback will be fired when an IP-address has been obtained, just before the enduser_setup module will terminate itself - `onConnected()` callback will be fired when an IP-address has been obtained, just before the enduser_setup module will terminate itself
- `onError()` callback will be fired if an error is encountered. `err_num` is a number describing the error, and `string` contains a description of the error. - `onError()` callback will be fired if an error is encountered. `err_num` is a number describing the error, and `string` contains a description of the error.
- `onDebug()` callback is disabled by default (controlled by `#define ENDUSER_SETUP_DEBUG_ENABLE` in `enduser_setup.c`). It is intended to be used to find internal issues in the module. `string` contains a description of what is going on. - `onDebug()` callback is disabled by default (controlled by `#define ENDUSER_SETUP_DEBUG_ENABLE` in `enduser_setup.c`). It is intended to be used to find internal issues in the module. `string` contains a description of what is going on.