HTML for Apple devices to mitigate POST fragmentation (#3069)
This commit is contained in:
parent
95fc8b14b3
commit
c50b4789c4
|
@ -0,0 +1,322 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||||
|
<title>WiFi Login</title>
|
||||||
|
<style type=text/css>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
font-family: sans-serif;
|
||||||
|
text-align: center;
|
||||||
|
background: #444d44;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 320px;
|
||||||
|
height: 480px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
input,
|
||||||
|
button,
|
||||||
|
select {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 0;
|
||||||
|
box-shadow: 0 0 15px 1px rgba(0, 0, 0, .4);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 20px 30px;
|
||||||
|
background: #fff;
|
||||||
|
min-height: 320px;
|
||||||
|
margin: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #222;
|
||||||
|
font: 16px monospace;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
font: 16px monospace;
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
color: #fff;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
font: 16px sans-serif;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 10px 5px;
|
||||||
|
background: #31b457;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:focus,
|
||||||
|
button:hover {
|
||||||
|
box-shadow: 0 0 0 2px #fff, 0 0 0 3px #31b457;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
color: #ccc;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.utility {
|
||||||
|
float: right;
|
||||||
|
clear: both;
|
||||||
|
max-width: 75%;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #222;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.utility:focus,
|
||||||
|
.utility:hover {
|
||||||
|
box-shadow: 0 0 0 2px #fff, 0 0 0 3px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown,
|
||||||
|
#f2,
|
||||||
|
#f3,
|
||||||
|
#bk2 {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dropdown {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
height: 51px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#aplist {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
font-family: monospace;
|
||||||
|
padding: 10px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#arrow {
|
||||||
|
color: #888;
|
||||||
|
position: absolute;
|
||||||
|
right: 8px;
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#i {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id=content>
|
||||||
|
<fieldset>
|
||||||
|
<div id=deviceId></div>
|
||||||
|
<div id=f1>
|
||||||
|
<h3>Connect device to your Wi-Fi</h3>
|
||||||
|
<button id=networks type=button class=utility></button>
|
||||||
|
<div id=dropdown>
|
||||||
|
<span id=arrow>▼</span>
|
||||||
|
<select id=aplist name=aplist></select>
|
||||||
|
</div>
|
||||||
|
<input id=ssid type=text autocorrect=off autocapitalize=none placeholder='Wi-Fi Name' />
|
||||||
|
<input id=wifi_password type=text autocorrect=off autocapitalize=none autocomplete=off placeholder=Password />
|
||||||
|
<button id=submit type=button>Save</button>
|
||||||
|
</div>
|
||||||
|
<div id=f2>
|
||||||
|
<h1>Success!</h1>
|
||||||
|
<div id=i>
|
||||||
|
<h3>Your device has successfully connected to the Wi-Fi network.<br /><br/>You may now close this web page.</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id=f3>
|
||||||
|
<h2>Trying...</h2>
|
||||||
|
<button id=bk2 type=button class='utility'>Go Back to Wi-Fi Setup</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<h4 id='st'>Updating Status...</h4>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var $ = function (selector) { return document.querySelector(selector); };
|
||||||
|
var ab = $('#networks'), ap = $('#aplist');
|
||||||
|
var stopAll = false, ra, rs, submitted = false;
|
||||||
|
|
||||||
|
function show(f, y) {
|
||||||
|
if (y == null) y = f;
|
||||||
|
$(f).style.display = y == f ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
function hide(f) {
|
||||||
|
$(f).style.display = 'none';
|
||||||
|
}
|
||||||
|
function to(cb, x) {
|
||||||
|
return setTimeout(cb, 1000 * x);
|
||||||
|
}
|
||||||
|
function refr() {
|
||||||
|
if (!stopAll)
|
||||||
|
fetch('/status.json?n=' + Math.random(), 'GET', newSt, 2);
|
||||||
|
}
|
||||||
|
function cur(f) {
|
||||||
|
show('#f1', f);
|
||||||
|
show('#f2', f);
|
||||||
|
show('#f3', f);
|
||||||
|
}
|
||||||
|
function newSt(s, d) {
|
||||||
|
clearTimeout(rs);
|
||||||
|
rs = to(refr, 3);
|
||||||
|
|
||||||
|
if (s != 200) {
|
||||||
|
$('#st').innerText = 'Awaiting Status (' + s + ')';
|
||||||
|
} else {
|
||||||
|
if (typeof d === 'string') {
|
||||||
|
d = JSON.parse(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#deviceId').innerText = "Device: " + d.deviceid;
|
||||||
|
|
||||||
|
var c = d.pairing;
|
||||||
|
|
||||||
|
var st = [
|
||||||
|
'Idle',
|
||||||
|
'Connecting...',
|
||||||
|
'Failed - wrong password',
|
||||||
|
'Failed - network not found',
|
||||||
|
'Failed',
|
||||||
|
'Wi-Fi successfully connected!'
|
||||||
|
][d.status];
|
||||||
|
|
||||||
|
if (st == null)
|
||||||
|
st = "";
|
||||||
|
|
||||||
|
if (!submitted && d.status > 1 && d.status < 5)
|
||||||
|
st = "Need a valid Network and Password";
|
||||||
|
|
||||||
|
$('#st').innerText = st;
|
||||||
|
|
||||||
|
if (d.status === 5) {
|
||||||
|
cur('#f2');
|
||||||
|
stopAll = true;
|
||||||
|
clearTimeout(ra);
|
||||||
|
} else if (d.status > 1) {
|
||||||
|
cur('#f1');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function submit() {
|
||||||
|
submitted = true;
|
||||||
|
var url = '/update?wifi_ssid=' + encodeURIComponent($('#ssid').value) + '&wifi_password=' + encodeURIComponent($('#wifi_password').value);
|
||||||
|
clearTimeout(rs);
|
||||||
|
fetch(url, 'GET', refr, 2);
|
||||||
|
cur('#f3');
|
||||||
|
}
|
||||||
|
function fetch(url, method, callback, time_out) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onloadend = function () {
|
||||||
|
callback(xhr.status, xhr.responseText);
|
||||||
|
}
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
callback(-1, null);
|
||||||
|
}
|
||||||
|
xhr.open(method, url, true);
|
||||||
|
xhr.setRequestHeader('Accept', 'application/json');
|
||||||
|
xhr.timeout = (time_out || 10) * 1000;
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
function gotAp(s, json) {
|
||||||
|
var list;
|
||||||
|
if (s === 200 && json != null) {
|
||||||
|
if (typeof json === 'string' && json.length > 0) {
|
||||||
|
list = JSON.parse(json);
|
||||||
|
} else if (typeof json === 'object') {
|
||||||
|
list = json;
|
||||||
|
}
|
||||||
|
|
||||||
|
list.sort(function (a, b) {
|
||||||
|
return b.rssi - a.rssi;
|
||||||
|
});
|
||||||
|
var ops = '<option>Select a Network...</option>';
|
||||||
|
for (var i = 0; i < list.length; ++i) {
|
||||||
|
ops += '<option>' + list[i].ssid + '</option>';
|
||||||
|
}
|
||||||
|
ap.innerHTML = ops;
|
||||||
|
ab.disabled = false;
|
||||||
|
togAp(null, true);
|
||||||
|
ab.onclick = togAp;
|
||||||
|
} else {
|
||||||
|
ab.innerText = 'No networks found (' + s + ')';
|
||||||
|
ra = to(refrAp, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function togAp(ev, force) {
|
||||||
|
if (!force || ap.style.display == 'block') {
|
||||||
|
hide('#dropdown');
|
||||||
|
show('#ssid');
|
||||||
|
ab.innerText = 'Scan for Networks';
|
||||||
|
ab.onclick = refrAp;
|
||||||
|
} else {
|
||||||
|
show('#dropdown');
|
||||||
|
hide('#ssid');
|
||||||
|
ab.innerText = 'Manual Entry';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function refrAp() {
|
||||||
|
ab.innerText = 'Searching for networks...';
|
||||||
|
ab.disabled = true;
|
||||||
|
ap.innerHTML = '<option disabled>Scanning...</option>';
|
||||||
|
if (!stopAll)
|
||||||
|
fetch('/aplist?n=' + Math.random(), 'GET', gotAp, 10);
|
||||||
|
}
|
||||||
|
window.onload = function() {
|
||||||
|
ab.innerText = 'Scan for Networks';
|
||||||
|
ab.onclick = refrAp;
|
||||||
|
$('#aplist').onchange = function () {
|
||||||
|
$('#ssid').value = $('#aplist').value;
|
||||||
|
};
|
||||||
|
$('#submit').onclick = submit;
|
||||||
|
$('#bk2').onclick = function () {
|
||||||
|
cur('#f1')
|
||||||
|
}
|
||||||
|
rs = to(refr, 0.5);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -6,6 +6,13 @@
|
||||||
This module provides a simple way of configuring ESP8266 chips without using a
|
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.
|
||||||
|
|
||||||
|
!!! attention "ATTENTION Apple users"
|
||||||
|
|
||||||
|
Due to bug [#2931](https://github.com/nodemcu/nodemcu-firmware/issues/2931) the configuration does currently not work for many Safari browsers (iOS & macOS).
|
||||||
|
As a **workaround** there is alternative HTML file which uses another method to transfer the login credentials. It does not support sending arbitrary additional configuration parameters and likewise no `eus_params.lua` will be written. The WiFi credentials will be stored in the ESP flash.
|
||||||
|
|
||||||
|
Just copy [enduser_setup_apple.html](../../app/modules/enduser_setup/enduser_setup_apple.html) to the ESP file system and rename it to `enduser_setup.html`.
|
||||||
|
|
||||||
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 "SetupGadget_XXXXXX" will starting. 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`. Connect to that SSID
|
||||||
|
|
Loading…
Reference in New Issue