|
@@ -0,0 +1,669 @@
|
|
|
|
+//===== Collection of small utilities
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Bind/Unbind events
|
|
|
|
+ *
|
|
|
|
+ * Usage:
|
|
|
|
+ * var el = document.getElementyById('#container');
|
|
|
|
+ * bnd(el, 'click', function() {
|
|
|
|
+ * console.log('clicked');
|
|
|
|
+ * });
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+var bnd = function(
|
|
|
|
+ d, // a DOM element
|
|
|
|
+ e, // an event name such as "click"
|
|
|
|
+ f // a handler function
|
|
|
|
+){
|
|
|
|
+ d.addEventListener(e, f, false);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Create DOM element
|
|
|
|
+ *
|
|
|
|
+ * Usage:
|
|
|
|
+ * var el = m('<h1>Hello</h1>');
|
|
|
|
+ * document.body.appendChild(el);
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
|
|
|
|
+ * More: https://gist.github.com/966233
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+var m = function(
|
|
|
|
+ a, // an HTML string
|
|
|
|
+ b, // placeholder
|
|
|
|
+ c // placeholder
|
|
|
|
+){
|
|
|
|
+ b = document; // get the document,
|
|
|
|
+ c = b.createElement("p"); // create a container element,
|
|
|
|
+ c.innerHTML = a; // write the HTML to it, and
|
|
|
|
+ a = b.createDocumentFragment(); // create a fragment.
|
|
|
|
+
|
|
|
|
+ while ( // while
|
|
|
|
+ b = c.firstChild // the container element has a first child
|
|
|
|
+ ) a.appendChild(b); // append the child to the fragment,
|
|
|
|
+
|
|
|
|
+ return a // and then return the fragment.
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * DOM selector
|
|
|
|
+ *
|
|
|
|
+ * Usage:
|
|
|
|
+ * $('div');
|
|
|
|
+ * $('#name');
|
|
|
|
+ * $('.name');
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2011 Jed Schmidt <http://jed.is> - WTFPL
|
|
|
|
+ * More: https://gist.github.com/991057
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+var $ = function(
|
|
|
|
+ a, // take a simple selector like "name", "#name", or ".name", and
|
|
|
|
+ b // an optional context, and
|
|
|
|
+){
|
|
|
|
+ a = a.match(/^(\W)?(.*)/); // split the selector into name and symbol.
|
|
|
|
+ return( // return an element or list, from within the scope of
|
|
|
|
+ b // the passed context
|
|
|
|
+ || document // or document,
|
|
|
|
+ )[
|
|
|
|
+ "getElement" + ( // obtained by the appropriate method calculated by
|
|
|
|
+ a[1]
|
|
|
|
+ ? a[1] == "#"
|
|
|
|
+ ? "ById" // the node by ID,
|
|
|
|
+ : "sByClassName" // the nodes by class name, or
|
|
|
|
+ : "sByTagName" // the nodes by tag name,
|
|
|
|
+ )
|
|
|
|
+ ](
|
|
|
|
+ a[2] // called with the name.
|
|
|
|
+ )
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Get cross browser xhr object
|
|
|
|
+ *
|
|
|
|
+ * Copyright (C) 2011 Jed Schmidt <http://jed.is>
|
|
|
|
+ * More: https://gist.github.com/993585
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+var j = function(
|
|
|
|
+ a // cursor placeholder
|
|
|
|
+){
|
|
|
|
+ for( // for all a
|
|
|
|
+ a=0; // from 0
|
|
|
|
+ a<4; // to 4,
|
|
|
|
+ a++ // incrementing
|
|
|
|
+ ) try { // try
|
|
|
|
+ return a // returning
|
|
|
|
+ ? new ActiveXObject( // a new ActiveXObject
|
|
|
|
+ [ // reflecting
|
|
|
|
+ , // (elided)
|
|
|
|
+ "Msxml2", // the various
|
|
|
|
+ "Msxml3", // working
|
|
|
|
+ "Microsoft" // options
|
|
|
|
+ ][a] + // for Microsoft implementations, and
|
|
|
|
+ ".XMLHTTP" // the appropriate suffix,
|
|
|
|
+ ) // but make sure to
|
|
|
|
+ : new XMLHttpRequest // try the w3c standard first, and
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ catch(e){} // ignore when it fails.
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// dom element iterator: domForEach($(".some-class"), function(el) { ... });
|
|
|
|
+function domForEach(els, fun) { return Array.prototype.forEach.call(els, fun); }
|
|
|
|
+
|
|
|
|
+// createElement short-hand
|
|
|
|
+
|
|
|
|
+e = function(a) { return document.createElement(a); }
|
|
|
|
+
|
|
|
|
+// chain onload handlers
|
|
|
|
+
|
|
|
|
+function onLoad(f) {
|
|
|
|
+ var old = window.onload;
|
|
|
|
+ if (typeof old != 'function') {
|
|
|
|
+ window.onload = f;
|
|
|
|
+ } else {
|
|
|
|
+ window.onload = function() {
|
|
|
|
+ old();
|
|
|
|
+ f();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== helpers to add/remove/toggle HTML element classes
|
|
|
|
+
|
|
|
|
+function addClass(el, cl) {
|
|
|
|
+ el.className += ' ' + cl;
|
|
|
|
+}
|
|
|
|
+function removeClass(el, cl) {
|
|
|
|
+ var cls = el.className.split(/\s+/),
|
|
|
|
+ l = cls.length;
|
|
|
|
+ for (var i=0; i<l; i++) {
|
|
|
|
+ if (cls[i] === cl) cls.splice(i, 1);
|
|
|
|
+ }
|
|
|
|
+ el.className = cls.join(' ');
|
|
|
|
+ return cls.length != l
|
|
|
|
+}
|
|
|
|
+function toggleClass(el, cl) {
|
|
|
|
+ if (!removeClass(el, cl)) addClass(el, cl);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== AJAX
|
|
|
|
+
|
|
|
|
+function ajaxReq(method, url, ok_cb, err_cb, data) {
|
|
|
|
+ var xhr = j();
|
|
|
|
+ xhr.open(method, url, true);
|
|
|
|
+ var timeout = setTimeout(function() {
|
|
|
|
+ xhr.abort();
|
|
|
|
+ console.log("XHR abort:", method, url);
|
|
|
|
+ xhr.status = 599;
|
|
|
|
+ xhr.responseText = "request time-out";
|
|
|
|
+ }, 9000);
|
|
|
|
+ xhr.onreadystatechange = function() {
|
|
|
|
+ if (xhr.readyState != 4) { return; }
|
|
|
|
+ clearTimeout(timeout);
|
|
|
|
+ if (xhr.status >= 200 && xhr.status < 300) {
|
|
|
|
+// console.log("XHR done:", method, url, "->", xhr.status);
|
|
|
|
+ ok_cb(xhr.responseText);
|
|
|
|
+ } else {
|
|
|
|
+ console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText, xhr);
|
|
|
|
+ err_cb(xhr.status, xhr.responseText);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+// console.log("XHR send:", method, url);
|
|
|
|
+ try {
|
|
|
|
+ xhr.send(data);
|
|
|
|
+ } catch(err) {
|
|
|
|
+ console.log("XHR EXC :", method, url, "->", err);
|
|
|
|
+ err_cb(599, err);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function dispatchJson(resp, ok_cb, err_cb) {
|
|
|
|
+ var j;
|
|
|
|
+ try { j = JSON.parse(resp); }
|
|
|
|
+ catch(err) {
|
|
|
|
+ console.log("JSON parse error: " + err + ". In: " + resp);
|
|
|
|
+ err_cb(500, "JSON parse error: " + err);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ ok_cb(j);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ajaxJson(method, url, ok_cb, err_cb) {
|
|
|
|
+ ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ajaxSpin(method, url, ok_cb, err_cb) {
|
|
|
|
+ $("#spinner").removeAttribute('hidden');
|
|
|
|
+ ajaxReq(method, url, function(resp) {
|
|
|
|
+ $("#spinner").setAttribute('hidden', '');
|
|
|
|
+ ok_cb(resp);
|
|
|
|
+ }, function(status, statusText) {
|
|
|
|
+ $("#spinner").setAttribute('hidden', '');
|
|
|
|
+ //showWarning("Error: " + statusText);
|
|
|
|
+ err_cb(status, statusText);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ajaxJsonSpin(method, url, ok_cb, err_cb) {
|
|
|
|
+ ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== main menu, header spinner and notification boxes
|
|
|
|
+
|
|
|
|
+function hidePopup(el) {
|
|
|
|
+ addClass(el, "popup-hidden");
|
|
|
|
+ addClass(el.parentNode, "popup-target");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/*onLoad(function() {
|
|
|
|
+ var l = $("#layout");
|
|
|
|
+ var o = l.childNodes[0];
|
|
|
|
+ // spinner
|
|
|
|
+ l.insertBefore(m('<div id="spinner" class="spinner" hidden></div>'), o);
|
|
|
|
+ // notification boxes
|
|
|
|
+ l.insertBefore(m(
|
|
|
|
+ '<div id="messages"><div id="warning" hidden></div><div id="notification" hidden></div></div>'), o);
|
|
|
|
+ // menu hamburger button
|
|
|
|
+ l.insertBefore(m('<a href="#menu" id="menuLink" class="menu-link"><span></span></a>'), o);
|
|
|
|
+ // menu left-pane
|
|
|
|
+ var mm = m(
|
|
|
|
+ '<div id="menu">\
|
|
|
|
+ <div class="pure-menu">\
|
|
|
|
+ <a class="pure-menu-heading" href="https://github.com/jeelabs/meta-id">\
|
|
|
|
+ <img src="/favicon.ico" height="32"> meta-id</a>\
|
|
|
|
+ <div class="pure-menu-heading system-name" style="padding: 0px 0.6em"></div>\
|
|
|
|
+ <ul id="menu-list" class="pure-menu-list"></ul>\
|
|
|
|
+ </div>\
|
|
|
|
+ </div>\
|
|
|
|
+ ');
|
|
|
|
+ l.insertBefore(mm, o);
|
|
|
|
+
|
|
|
|
+ // make hamburger button pull out menu
|
|
|
|
+ var ml = $('#menuLink'), mm = $('#menu');
|
|
|
|
+ bnd(ml, 'click', function (e) {
|
|
|
|
+// console.log("hamburger time");
|
|
|
|
+ var active = 'active';
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ toggleClass(l, active);
|
|
|
|
+ toggleClass(mm, active);
|
|
|
|
+ toggleClass(ml, active);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // hide pop-ups
|
|
|
|
+ domForEach($(".popup"), function(el) {
|
|
|
|
+ hidePopup(el);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // populate menu via ajax call
|
|
|
|
+ var getMenu = function() {
|
|
|
|
+ ajaxJson("GET", "/menu", function(data) {
|
|
|
|
+ var html = "", path = window.location.pathname;
|
|
|
|
+ for (var i=0; i<data.menu.length; i+=2) {
|
|
|
|
+ var href = data.menu[i+1];
|
|
|
|
+ html = html.concat(" <li class=\"pure-menu-item" +
|
|
|
|
+ (path === href ? " pure-menu-selected" : "") + "\">" +
|
|
|
|
+ "<a href=\"" + href + "\" class=\"pure-menu-link\">" +
|
|
|
|
+ data.menu[i] + "</a></li>");
|
|
|
|
+ }
|
|
|
|
+ $("#menu-list").innerHTML = html;
|
|
|
|
+
|
|
|
|
+ var v = $("#version");
|
|
|
|
+ if (v != null) { v.innerHTML = data.version; }
|
|
|
|
+
|
|
|
|
+ $('title')[0].innerHTML = data["name"];
|
|
|
|
+ setEditToClick("system-name", data["name"]);
|
|
|
|
+ }, function() { setTimeout(getMenu, 1000); });
|
|
|
|
+ };
|
|
|
|
+ getMenu();
|
|
|
|
+});
|
|
|
|
+*/
|
|
|
|
+//===== Wifi info
|
|
|
|
+
|
|
|
|
+function showWifiInfo(data) {
|
|
|
|
+ Object.keys(data).forEach(function(v) {
|
|
|
|
+ el = $("#wifi-" + v);
|
|
|
|
+ if (el != null) {
|
|
|
|
+ if (el.nodeName === "INPUT") el.value = data[v];
|
|
|
|
+ else el.innerHTML = data[v];
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ var dhcp = $('#dhcp-r'+data.dhcp);
|
|
|
|
+ if (dhcp) dhcp.click();
|
|
|
|
+ $("#wifi-table").removeAttribute("hidden");
|
|
|
|
+ currAp = data.ssid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getWifiInfo() {
|
|
|
|
+ ajaxJson('GET', "/wifi/info", showWifiInfo,
|
|
|
|
+ function(s, st) { window.setTimeout(getWifiInfo, 1000); });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== System info
|
|
|
|
+
|
|
|
|
+function showSystemInfo(data) {
|
|
|
|
+ Object.keys(data).forEach(function(v) {
|
|
|
|
+ setEditToClick("system-"+v, data[v]);
|
|
|
|
+ });
|
|
|
|
+ $("#system-spinner").setAttribute("hidden", "");
|
|
|
|
+ $("#system-table").removeAttribute("hidden");
|
|
|
|
+ currAp = data.ssid;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function getSystemInfo() {
|
|
|
|
+ ajaxJson('GET', "/system/info", showSystemInfo,
|
|
|
|
+ function(s, st) { window.setTimeout(getSystemInfo, 1000); });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function makeAjaxInput(klass, field) {
|
|
|
|
+ domForEach($("."+klass+"-"+field), function(div) {
|
|
|
|
+ var eon = $(".edit-on", div);
|
|
|
|
+ var eoff = $(".edit-off", div)[0];
|
|
|
|
+ var url = "/"+klass+"/update?"+field;
|
|
|
|
+
|
|
|
|
+ if (eoff === undefined || eon == undefined) return;
|
|
|
|
+
|
|
|
|
+ var enableEditToClick = function() {
|
|
|
|
+ eoff.setAttribute('hidden','');
|
|
|
|
+ domForEach(eon, function(el){ el.removeAttribute('hidden'); });
|
|
|
|
+ eon[0].select();
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ var submitEditToClick = function(v) {
|
|
|
|
+// console.log("Submit POST "+url+"="+v);
|
|
|
|
+ ajaxSpin("POST", url+"="+v, function() {
|
|
|
|
+ domForEach(eon, function(el){ el.setAttribute('hidden',''); });
|
|
|
|
+ eoff.removeAttribute('hidden');
|
|
|
|
+ setEditToClick(klass+"-"+field, v)
|
|
|
|
+ showNotification(field + " changed to " + v);
|
|
|
|
+ }, function() {
|
|
|
|
+ showWarning(field + " change failed");
|
|
|
|
+ });
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ bnd(eoff, "click", function(){return enableEditToClick();});
|
|
|
|
+ bnd(eon[0], "blur", function(){return submitEditToClick(eon[0].value);});
|
|
|
|
+ bnd(eon[0], "keyup", function(ev){
|
|
|
|
+ if ((ev||window.event).keyCode==13) return submitEditToClick(eon[0].value);
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function setEditToClick(klass, value) {
|
|
|
|
+ domForEach($("."+klass), function(div) {
|
|
|
|
+ if (div.children.length > 0) {
|
|
|
|
+ domForEach(div.children, function(el) {
|
|
|
|
+ if (el.nodeName === "INPUT") el.value = value;
|
|
|
|
+ else if (el.nodeName !== "DIV") el.innerHTML = value;
|
|
|
|
+ });
|
|
|
|
+ } else {
|
|
|
|
+ div.innerHTML = value;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== Notifications
|
|
|
|
+
|
|
|
|
+function showWarning(text) {
|
|
|
|
+ var el = $("#notification");
|
|
|
|
+ el.innerHTML = text;
|
|
|
|
+ el.removeAttribute('hidden');
|
|
|
|
+ window.scrollTo(0, 0);
|
|
|
|
+}
|
|
|
|
+function hideWarning() {
|
|
|
|
+ el = $("#notification").setAttribute('hidden', '');
|
|
|
|
+}
|
|
|
|
+var notifTimeout = null;
|
|
|
|
+function showNotification(text) {
|
|
|
|
+ if(text=='')return;
|
|
|
|
+ var el = $("#notification");
|
|
|
|
+ el.innerHTML = text;
|
|
|
|
+ el.removeAttribute('hidden');
|
|
|
|
+ if (notifTimeout != null) clearTimeout(notifTimeout);
|
|
|
|
+ notifTimout = setTimeout(function() {
|
|
|
|
+ el.setAttribute('hidden', '');
|
|
|
|
+ notifTimout = null;
|
|
|
|
+ }, 4000);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loginNotification(text) {
|
|
|
|
+ if(text=='')return;
|
|
|
|
+ var el = $("#loginnotification");
|
|
|
|
+ el.innerHTML = text;
|
|
|
|
+ el.removeAttribute('hidden');
|
|
|
|
+ if (notifTimeout != null) clearTimeout(notifTimeout);
|
|
|
|
+ notifTimout = setTimeout(function() {
|
|
|
|
+ el.setAttribute('hidden', '');
|
|
|
|
+ notifTimout = null;
|
|
|
|
+ }, 4000);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//===== GPIO Pin mux card
|
|
|
|
+
|
|
|
|
+var pinPresets = {
|
|
|
|
+ // array: reset, isp, conn, ser, swap, rxpup, txen
|
|
|
|
+ "esp-01": [ 0, -1, 2, -1, 0, 1, -1 ],
|
|
|
|
+ "esp-12": [ 12, 14, 0, 2, 0, 1, -1 ],
|
|
|
|
+ "esp-12 swap": [ 1, 3, 0, 2, 1, 1, -1 ],
|
|
|
|
+ "esp-bridge": [ 12, 13, 0, 14, 0, 0, -1 ],
|
|
|
|
+ "wifi-link-12": [ 1, 3, 0, 2, 1, 0, -1 ],
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+function createPresets(sel) {
|
|
|
|
+ for (var p in pinPresets) {
|
|
|
|
+ var opt = m('<option value="' + p + '">' + p + '</option>');
|
|
|
|
+ sel.appendChild(opt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function applyPreset(v) {
|
|
|
|
+ var pp = pinPresets[v];
|
|
|
|
+ if (pp === undefined) return pp;
|
|
|
|
+// console.log("apply preset:", v, pp);
|
|
|
|
+ function setPP(k, v) { $("#pin-"+k).value = v; };
|
|
|
|
+ setPP("reset", pp[0]);
|
|
|
|
+ setPP("isp", pp[1]);
|
|
|
|
+ setPP("conn", pp[2]);
|
|
|
|
+ setPP("ser", pp[3]);
|
|
|
|
+ setPP("swap", pp[4]);
|
|
|
|
+ $("#pin-rxpup").checked = !!pp[5];
|
|
|
|
+ setPP("txen", pp[6]);
|
|
|
|
+ sel.value = 0;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ bnd(sel, "change", function(ev) {
|
|
|
|
+ ev.preventDefault();
|
|
|
|
+ applyPreset(sel.value);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function displayPins(resp) {
|
|
|
|
+ function createSelectForPin(name, v) {
|
|
|
|
+ var sel = $("#pin-"+name);
|
|
|
|
+ addClass(sel, "pure-button");
|
|
|
|
+ sel.innerHTML = "";
|
|
|
|
+ [-1,0,1,2,3,4,5,12,13,14,15].forEach(function(i) {
|
|
|
|
+ var opt = document.createElement("option");
|
|
|
|
+ opt.value = i;
|
|
|
|
+ if (i >= 0) opt.innerHTML = "gpio"+i;
|
|
|
|
+ else opt.innerHTML = "disabled";
|
|
|
|
+ if (i===1) opt.innerHTML += "/TX0";
|
|
|
|
+ if (i===2) opt.innerHTML += "/TX1";
|
|
|
|
+ if (i===3) opt.innerHTML += "/RX0";
|
|
|
|
+ if (i==v) opt.selected = true;
|
|
|
|
+ sel.appendChild(opt);
|
|
|
|
+ });
|
|
|
|
+ var pup = $(".popup", sel.parentNode);
|
|
|
|
+ if (pup !== undefined) hidePopup(pup[0]);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ createSelectForPin("reset", resp["reset"]);
|
|
|
|
+ createSelectForPin("isp", resp["isp"]);
|
|
|
|
+ createSelectForPin("conn", resp["conn"]);
|
|
|
|
+ createSelectForPin("ser", resp["ser"]);
|
|
|
|
+ $("#pin-swap").value = resp["swap"];
|
|
|
|
+ $("#pin-rxpup").checked = !!resp["rxpup"];
|
|
|
|
+ createSelectForPin("txen", resp["txen"]);
|
|
|
|
+ createPresets($("#pin-preset"));
|
|
|
|
+
|
|
|
|
+ $("#pin-spinner").setAttribute("hidden", "");
|
|
|
|
+ $("#pin-table").removeAttribute("hidden");
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function fetchPins() {
|
|
|
|
+ ajaxJson("GET", "/pins", displayPins, function() {
|
|
|
|
+ window.setTimeout(fetchPins, 1000);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function setPins(ev) {
|
|
|
|
+ ev.preventDefault();
|
|
|
|
+ var url = "/pins";
|
|
|
|
+ var sep = "?";
|
|
|
|
+ ["reset", "isp", "conn", "ser", "swap", "txen"].forEach(function(p) {
|
|
|
|
+ url += sep + p + "=" + $("#pin-"+p).value;
|
|
|
|
+ sep = "&";
|
|
|
|
+ });
|
|
|
|
+ url += "&rxpup=" + ($("#pin-rxpup").checked ? "1" : "0");
|
|
|
|
+// console.log("set pins: " + url);
|
|
|
|
+ ajaxSpin("POST", url, function() {
|
|
|
|
+ showNotification("Pin assignment changed");
|
|
|
|
+ }, function(status, errMsg) {
|
|
|
|
+ showWarning(errMsg);
|
|
|
|
+ window.setTimeout(fetchPins, 100);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loadWifiInfo(data){
|
|
|
|
+ showWifiInfo(data);
|
|
|
|
+ wifiInfo=data;
|
|
|
|
+ if(data != null){
|
|
|
|
+ if (data.status == "connecting") {
|
|
|
|
+ curState=1;
|
|
|
|
+ }
|
|
|
|
+ else if(data.status == "got IP address"){
|
|
|
|
+ showWifiInfo(data);
|
|
|
|
+ curState=2;
|
|
|
|
+ }
|
|
|
|
+ else{
|
|
|
|
+ curState=0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ stateMachine();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * -1 : unknown, waiting for authentication
|
|
|
|
+ * 0 : login box // if no wifi config and no auth
|
|
|
|
+ * 1 : login success // if auth ok
|
|
|
|
+ * 2 : wifi config // if no wifi connection and on request
|
|
|
|
+ * 3 : connecting //
|
|
|
|
+ * 4 : connected
|
|
|
|
+ **/
|
|
|
|
+var curState=-1;
|
|
|
|
+var lastState=-2
|
|
|
|
+var wifiInfo=null;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function resetWifiAp(e) {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ showNotification("Ressetting configuration...");
|
|
|
|
+ var url = "/wifi/connect?essid=&passwd=";
|
|
|
|
+ hideWarning();
|
|
|
|
+ $("#reconnect").setAttribute("hidden", "");
|
|
|
|
+ $("#wifi-passwd").value = "";
|
|
|
|
+ var cb = $("#reset-button");
|
|
|
|
+ var cn = cb.className;
|
|
|
|
+ cb.className += ' pure-button-disabled';
|
|
|
|
+ blockScan = 1;
|
|
|
|
+ ajaxSpin("POST", url, function(resp) {
|
|
|
|
+ $("#spinner").removeAttribute('hidden'); // hack
|
|
|
|
+ showNotification("Waiting for network change...");
|
|
|
|
+ window.scrollTo(0, 0);
|
|
|
|
+ window.setTimeout(getStatus, 2000);
|
|
|
|
+ }, function(s, st) {
|
|
|
|
+ showWarning("Error resetting network: "+st);
|
|
|
|
+ cb.className = cn;
|
|
|
|
+ window.setTimeout(scanAPs, 1000);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function toggle(a){
|
|
|
|
+ del=document.getElementById(a);
|
|
|
|
+ if(del.hasAttribute("hidden")){
|
|
|
|
+ del.removeAttribute("hidden");
|
|
|
|
+ }
|
|
|
|
+ else{
|
|
|
|
+ del.setAttribute("hidden","");}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function restartSM(resp){
|
|
|
|
+ stateMachine(resp);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function stateMachine (resp) {
|
|
|
|
+ try { jrep = JSON.parse(resp); }
|
|
|
|
+ catch(err) {
|
|
|
|
+ console.log("JSON parse error: " + err + ". In: " + resp);
|
|
|
|
+ jrep['state']=-1;
|
|
|
|
+ jrep['msg']="not initialized";
|
|
|
|
+ }
|
|
|
|
+ curState=jrep['state'];
|
|
|
|
+ if(lastState!=curState){
|
|
|
|
+ showNotification(jrep['msg']);
|
|
|
|
+ if(jrep['auth'] == 0){
|
|
|
|
+ curState=-1
|
|
|
|
+ }
|
|
|
|
+ for(i=-1;i<5;i++){
|
|
|
|
+ del=$("#state-"+i);
|
|
|
|
+ del.setAttribute('hidden','');
|
|
|
|
+ }
|
|
|
|
+ del=$("#state-"+curState);
|
|
|
|
+ del.removeAttribute('hidden');
|
|
|
|
+ }
|
|
|
|
+ lastState=curState;
|
|
|
|
+ if(curState== 1 || curState == 3){
|
|
|
|
+ window.setTimeout(function (){ajaxReq('GET', "/meta/state", stateMachine)}, 2000);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loginSuccess(resp){
|
|
|
|
+ loginNotification("Login success");
|
|
|
|
+ document.location.href="wifi.html";
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function loginFail(s,st){
|
|
|
|
+ loginNotification("Login failed");
|
|
|
|
+ stateMachine(st);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function submitPass(e){
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ajaxReq('GET', "/meta/auth?passwd="+$("#passwd").value,
|
|
|
|
+ loginSuccess,loginFail);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function displayMeta(data) {
|
|
|
|
+ Object.keys(data).forEach(function (v) {
|
|
|
|
+ el = $("#" + v);
|
|
|
|
+ if (el != null) {
|
|
|
|
+ console.log("have "+v+" : "+data[v]);
|
|
|
|
+ if (data[v]==1)el.checked=false;
|
|
|
|
+ if (data[v]==2)el.checked=true;
|
|
|
|
+
|
|
|
|
+ }});
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function fetchMeta() {
|
|
|
|
+// console.log("fetchMeta !");
|
|
|
|
+ ajaxJson("GET", "/meta/gpio", displayMeta, function () {
|
|
|
|
+ window.setTimeout(fetchMeta, 1000);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function changeMetaStatus(e) {
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ var v = document.querySelector('input[name="meta-status-topic"]').value;
|
|
|
|
+ ajaxSpin("POST", "/meta?meta-status-topic=" + v, function () {
|
|
|
|
+ showNotification("meta status settings updated");
|
|
|
|
+ }, function (s, st) {
|
|
|
|
+ showWarning("Error: " + st);
|
|
|
|
+ window.setTimeout(fetchMeta, 100);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function setMeta(b,d){
|
|
|
|
+ ajaxReq("POST","/meta/gpio?num="+b+"&v="+(d?"-1":"-2"),
|
|
|
|
+ function(){fetchMeta();
|
|
|
|
+ }, function () {
|
|
|
|
+ fetchMeta();
|
|
|
|
+ showWarning("Enable/disable failed");
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+function ledControl05(e){
|
|
|
|
+setMeta("05",$('#meta-gpio-05').checked);
|
|
|
|
+}
|
|
|
|
+function ledControl12(e){
|
|
|
|
+setMeta("12",$('#meta-gpio-12').checked);
|
|
|
|
+}
|
|
|
|
+function ledControl13(e){
|
|
|
|
+setMeta("13",$('#meta-gpio-13').checked);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+function sendServer(e){
|
|
|
|
+ e.preventDefault();
|
|
|
|
+ var v = document.querySelector('input[name="send-msg"]').value;
|
|
|
|
+ ajaxSpin("GET", "/meta/sand?msg=" + v, function () {
|
|
|
|
+ showNotification("Your message was sent !");
|
|
|
|
+ }, function (s, st) {
|
|
|
|
+ showWarning("Error: " + st);
|
|
|
|
+ });
|
|
|
|
+}
|
|
|
|
+
|