소스 검색

HTML for Apple devices to mitigate POST fragmentation (#3069)

Gregor Hartmann 4 년 전
부모
커밋
c50b4789c4
2개의 변경된 파일329개의 추가작업 그리고 0개의 파일을 삭제
  1. 322 0
      app/modules/enduser_setup/enduser_setup_apple.html
  2. 7 0
      docs/modules/enduser-setup.md

+ 322 - 0
app/modules/enduser_setup/enduser_setup_apple.html

@@ -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>&#x25bc;</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>

+ 7 - 0
docs/modules/enduser-setup.md

@@ -6,6 +6,13 @@
 This module provides a simple way of configuring ESP8266 chips without using a
 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 
 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