|
@@ -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>
|