Before Width: | Height: | Size: 874 B After Width: | Height: | Size: 874 B |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 425 B |
@ -0,0 +1,56 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main class="flex-fill flex-vbox" style="max-height:100%"><div class=header><h1>Microcontroller Console</h1></div><div class="content flex-fill flex-vbox"><p><a id=reset-button class="pure-button button-primary" href="#">Reset µC</a> <a id=clear-button class="pure-button button-primary" href="#">Clear Log</a> Baud: <select id=baud-sel class=pure-button href="#"><option value=460800>460800</option><option value=250000>250000</option><option value=230400>230400</option><option value=115200>115200</option><option value=57600>57600</option><option value=38400>38400</option><option value=19200>19200</option><option value=9600>9600</option><option value=4800>4800</option><option value=2400>2400</option><option value=1200>1200</option><option value=600>600</option><option value=300>300</option></select> Fmt: <select id=fmt-sel class=pure-button href="#"><option value=8N1>8N1</option><option value=8E1>8E1</option><option value=8N2>8N2</option><option value=8E2>8E2</option><option value=7N1>7N1</option><option value=7E1>7E1</option><option value=7N2>7N2</option><option value=7E2>7E2</option></select></p><div class=pure-g><div class=pure-u-1-4><legend><b>Console</b></legend></div><div class=pure-u-3-4></div></div><pre class="console flex-fill" id=console>--- No Content ---</pre><div><div class=pure-g><div class=pure-u-1-4><legend><b>Console entry</b></legend></div><div class=pure-u-2-4><legend>(ENTER to submit, ESC to clear)</legend></div><div class=pure-u-1-4><legend>Add: <input type=checkbox id=input-add-cr checked class=inline><label>CR(\r)</label><input type=checkbox id=input-add-lf checked class=inline><label>LF(\n)</label></legend></div></div><div class=pure-g><div class=pure-u-1-1><span style="float:right; width:10px;"></span><input type=text class=console-in id=input-text value=""></div></div><div class=pure-g><div class=pure-u-1-4><legend><b>History buffer</b></legend></div><div class=pure-u-2-4><legend>(UP/DOWN arrows to select)</legend></div><div class=pure-u-1-4></div></div><div class=pure-g><div class=pure-u-1-1><select class=console-in id=send-history size=5></select></div></div></div></div></div></div><script type="text/javascript">console_url = "/console/text"</script><script src="console.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
fetchText(100, true); |
||||||
|
|
||||||
|
$("#reset-button").addEventListener("click", function(e) { |
||||||
|
e.preventDefault(); |
||||||
|
var co = $("#console"); |
||||||
|
co.innerHTML = ""; |
||||||
|
ajaxSpin('POST', "/console/reset", |
||||||
|
function(resp) { showNotification("uC reset"); co.textEnd = 0; }, |
||||||
|
function(s, st) { showWarning("Error resetting uC"); } |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
$("#clear-button").addEventListener("click", function(e) { |
||||||
|
e.preventDefault(); |
||||||
|
var co = $("#console"); |
||||||
|
co.innerHTML = ""; |
||||||
|
}); |
||||||
|
|
||||||
|
ajaxJson('GET', "/console/baud", |
||||||
|
function(data) { $("#baud-sel").value = data.rate; }, |
||||||
|
function(s, st) { showNotification(st); } |
||||||
|
); |
||||||
|
|
||||||
|
bnd($("#baud-sel"), "change", function(ev) { |
||||||
|
ev.preventDefault(); |
||||||
|
var baud = $("#baud-sel").value; |
||||||
|
ajaxSpin('POST', "/console/baud?rate="+baud, |
||||||
|
function(resp) { showNotification("" + baud + " baud set"); }, |
||||||
|
function(s, st) { showWarning("Error setting baud rate: " + st); } |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
ajaxJson('GET', "/console/fmt", |
||||||
|
function(data) { $("#fmt-sel").value = data.fmt; }, |
||||||
|
function(s, st) { showNotification(st); } |
||||||
|
); |
||||||
|
|
||||||
|
bnd($("#fmt-sel"), "change", function(ev) { |
||||||
|
ev.preventDefault(); |
||||||
|
var fmt = $("#fmt-sel").value; |
||||||
|
ajaxSpin('POST', "/console/fmt?fmt="+fmt, |
||||||
|
function(resp) { showNotification("" + fmt + " format set"); }, |
||||||
|
function(s, st) { showWarning("Error setting format: " + st); } |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
consoleSendInit(); |
||||||
|
|
||||||
|
addClass($('html')[0], "height100"); |
||||||
|
addClass($('body')[0], "height100"); |
||||||
|
addClass($('#layout'), "height100"); |
||||||
|
addClass($('#layout'), "flex-vbox"); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,72 @@ |
|||||||
|
function fetchText(a,c){var b=$("#console"); |
||||||
|
if(b.textEnd==undefined){b.textEnd=0; |
||||||
|
b.innerHTML="" |
||||||
|
}window.setTimeout(function(){ajaxJson("GET",console_url+"?start="+b.textEnd,function(e){var d=updateText(e); |
||||||
|
if(c){fetchText(d,c) |
||||||
|
}},function(){retryLoad(c) |
||||||
|
}) |
||||||
|
},a) |
||||||
|
}function updateText(d){var b=$("#console"); |
||||||
|
var a=3000; |
||||||
|
if(d!=null&&d.len>0){var c=b.scrollHeight-b.clientHeight<=b.scrollTop+1; |
||||||
|
if(d.start>b.textEnd){b.innerHTML=b.innerHTML.concat("\r\n<missing lines\r\n") |
||||||
|
}b.innerHTML=b.innerHTML.concat(d.text.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")); |
||||||
|
b.textEnd=d.start+d.len; |
||||||
|
a=500; |
||||||
|
if(c){b.scrollTop=b.scrollHeight-b.clientHeight |
||||||
|
}}return a |
||||||
|
}function retryLoad(a){fetchText(1000,a) |
||||||
|
}function consoleSendInit(){var e=$("#send-history"); |
||||||
|
var h=$("#input-text"); |
||||||
|
var d=$("#input-add-cr"); |
||||||
|
var b=$("#input-add-lf"); |
||||||
|
function g(k){for(var j=0; |
||||||
|
j<e.children.length; |
||||||
|
j++){if(k==e.children[j].value){return j |
||||||
|
}}return null |
||||||
|
}function a(i){e.value=e.children[i].value; |
||||||
|
h.value=e.children[i].value |
||||||
|
}function f(j){var i=g(e.value)+j; |
||||||
|
if(i<0){i=e.children.length-1 |
||||||
|
}if(i>=e.children.length){i=0 |
||||||
|
}a(i) |
||||||
|
}e.addEventListener("change",function(i){h.value=e.value |
||||||
|
}); |
||||||
|
function c(k){var i=g(k); |
||||||
|
if(i!==null){a(i); |
||||||
|
return false |
||||||
|
}var j=m("<option>"+(k.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""))+"</option>"); |
||||||
|
j.value=k; |
||||||
|
e.appendChild(j); |
||||||
|
e.value=k; |
||||||
|
for(; |
||||||
|
e.children.length>15; |
||||||
|
){e.removeChild(e.children[0]) |
||||||
|
}return true |
||||||
|
}h.addEventListener("keydown",function(i){switch(i.keyCode){case 38:i.preventDefault(); |
||||||
|
f(-1); |
||||||
|
break; |
||||||
|
case 40:i.preventDefault(); |
||||||
|
f(+1); |
||||||
|
break; |
||||||
|
case 27:i.preventDefault(); |
||||||
|
h.value=""; |
||||||
|
e.value=""; |
||||||
|
break; |
||||||
|
case 13:i.preventDefault(); |
||||||
|
var j=h.value; |
||||||
|
if(d.checked){j+="\r" |
||||||
|
}if(b.checked){j+="\n" |
||||||
|
}c(h.value); |
||||||
|
h.value=""; |
||||||
|
ajaxSpin("POST","/console/send?text="+encodeURIComponent(j),function(k){showNotification("Text sent") |
||||||
|
},function(l,k){showWarning("Error sending text") |
||||||
|
}); |
||||||
|
break |
||||||
|
}}) |
||||||
|
}function showDbgMode(c){var b=$(".dbg-btn"); |
||||||
|
for(var a=0; |
||||||
|
a<b.length; |
||||||
|
a++){if(b[a].id==="dbg-"+c){addClass(b[a],"button-selected") |
||||||
|
}else{removeClass(b[a],"button-selected") |
||||||
|
}}}; |
After Width: | Height: | Size: 874 B |
@ -0,0 +1,6 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>Upgrade Firmware</h1></div><div class=content><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Upgrade Firmware <div id=fw-spinner class="spinner spinner-small"></div></h1><form action="#" id=fw-form class=pure-form hidden><legend>Firmware Info</legend><p>Current firmware: <span style="font-weight: bold;" id=current-fw></span></p><div class=pure-form-stacked><p>Make sure you upload the file called: <span style="font-weight: bold;" id=fw-slot></span></p><label>Firmware File</label><input type=file name=fw-file id=fw-file /></div><button id=fw-button type=submit class="pure-button button-primary"> Update the firmware </button></form></div></div></div></div></div></div><script src="flash.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
fetchFlash(); |
||||||
|
bnd($("#fw-form"), "submit", flashFirmware); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,20 @@ |
|||||||
|
function flashFirmware(b){b.preventDefault(); |
||||||
|
var a=document.getElementById("fw-file").files[0]; |
||||||
|
$("#fw-form").setAttribute("hidden",""); |
||||||
|
$("#fw-spinner").removeAttribute("hidden"); |
||||||
|
showNotification("Firmware is being updated ..."); |
||||||
|
ajaxReq("POST","/flash/upload",function(c){ajaxReq("GET","/flash/reboot",function(d){showNotification("Firmware has been successfully updated!"); |
||||||
|
setTimeout(function(){window.location.reload() |
||||||
|
},4000); |
||||||
|
$("#fw-spinner").setAttribute("hidden",""); |
||||||
|
$("#fw-form").removeAttribute("hidden") |
||||||
|
}) |
||||||
|
},null,a) |
||||||
|
}function fetchFlash(){ajaxReq("GET","/flash/next",function(a){$("#fw-slot").innerHTML=a; |
||||||
|
$("#fw-spinner").setAttribute("hidden",""); |
||||||
|
$("#fw-form").removeAttribute("hidden") |
||||||
|
}); |
||||||
|
ajaxJson("GET","/menu",function(b){var a=$("#current-fw"); |
||||||
|
if(a!=null){a.innerHTML=b.version |
||||||
|
}}) |
||||||
|
}; |
@ -0,0 +1,31 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>Debug Log</h1></div><div class=content><p>The debug log shows the most recent characters printed by the esp-link software itself to its own debug log.</p><div class=pure-g><p class=pure-u-1-4 style="vertical-align: baseline;width:40%"><a id=refresh-button class="pure-button button-primary" href="#">Refresh</a> <a id=reset-button class="dbg-btn pure-button button-primary" href="#">Reset esp-link</a></p><p class=pure-u-3-4 style="vertical-align: baseline;width:60%">UART debug log: <a id=dbg-auto class="dbg-btn pure-button" href="#">auto</a><a id=dbg-off class="dbg-btn pure-button" href="#">off</a><a id=dbg-on0 class="dbg-btn pure-button" href="#">on uart0</a><a id=dbg-on1 class="dbg-btn pure-button" href="#">on uart1</a></p></div><pre id=console class=console style="margin-top: 0px;"></pre></div></div></div><script type="text/javascript">console_url = "/log/text"</script><script src="console.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
fetchText(100, false); |
||||||
|
|
||||||
|
$("#refresh-button").addEventListener("click", function(e) { |
||||||
|
e.preventDefault(); |
||||||
|
fetchText(100, false); |
||||||
|
}); |
||||||
|
|
||||||
|
$("#reset-button").addEventListener("click", function (e) { |
||||||
|
e.preventDefault(); |
||||||
|
var co = $("#console"); |
||||||
|
co.innerHTML = ""; |
||||||
|
ajaxSpin('POST', "/log/reset", |
||||||
|
function (resp) { showNotification("Resetting esp-link"); co.textEnd = 0; fetchText(2000, false); }, |
||||||
|
function (s, st) { showWarning("Error resetting esp-link"); } |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
["auto", "off", "on0", "on1"].forEach(function(mode) { |
||||||
|
bnd($('#dbg-'+mode), "click", function(el) { |
||||||
|
ajaxJsonSpin('POST', "/log/dbg?mode="+mode, |
||||||
|
function(data) { showNotification("UART mode " + data.mode); showDbgMode(data.mode); }, |
||||||
|
function(s, st) { showWarning("Error setting UART mode: " + st); } |
||||||
|
); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
ajaxJson('GET', "/log/dbg", function(data) { showDbgMode(data.mode); }, function() {}); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,7 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>REST & MQTT</h1></div><div class=content><div class=pure-g><div class=pure-u-1><div class=card><p>The REST & MQTT support uses the SLIP protocol over the serial port to enable the attached microcontroller to initiate outbound connections. The REST support lets the uC initiate simple HTTP requests while the MQTT support lets it communicate with an MQTT server bidirectionally at QoS 0 thru 2.</p><p>The MQTT support is in the form of a built-in client that connects to a server using parameters set below and stored in esp-link's flash settings. This allows esp-link to take care of connection parameters and disconnect/reconnect operations.</p><p>The MQTT client also supports sending periodic status messages about esp-link itself, including WiFi RSSI, and free heap memory.</p><div class=form-horizontal><input type=checkbox name=slip-enable /><label>Enable SLIP on serial port</label></div></div></div></div><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>MQTT <div id=mqtt-spinner class="spinner spinner-small"></div></h1><form action="#" id=mqtt-form class=pure-form hidden><div><input type=checkbox name=mqtt-enable /><label>Enable MQTT client</label></div><div><label>MQTT client state: </label><b id=mqtt-state></b></div><br><legend>MQTT server settings</legend><div class=pure-form-stacked><label>Server hostname or IP</label><input type=text name=mqtt-host /><label>Server port</label><input type=text name=mqtt-port /><label>Client ID</label><input type=text name=mqtt-client-id /><label>Client Timeout (seconds)</label><input type=text name=mqtt-timeout /><label>Keep Alive Interval (seconds)</label><input type=text name=mqtt-keepalive /><label>Username</label><input type=text name=mqtt-username /><label>Password</label><input type=password name=mqtt-password /></div><button id=mqtt-button type=submit class="pure-button button-primary"> Update server settings! </button></form></div></div><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Status reporting <div id=mqtt-status-spinner class="spinner spinner-small"></div></h1><form action="#" id=mqtt-status-form class=pure-form hidden><div class=form-horizontal><input type=checkbox name=mqtt-status-enable /><label>Enable status reporting via MQTT</label></div><br><div class=pure-form-stacked><label>Status topic</label><input type=text name=mqtt-status-topic /> Message: <tt id=mqtt-status-value></tt><div class=popup>MQTT topic to which status message is sent</div></div><button id=mqtt-status-button type=submit class="pure-button button-primary"> Update status settings! </button></form></div><div class=card><h1>REST</h1><p>REST requests are enabled as soon as SLIP is enabled. There are no REST-specific settings.</p></div></div></div></div></div></div><script src="mqtt.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
fetchMqtt(); |
||||||
|
bnd($("#mqtt-form"), "submit", changeMqtt); |
||||||
|
bnd($("#mqtt-status-form"), "submit", changeMqttStatus); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,46 @@ |
|||||||
|
function changeMqtt(f){f.preventDefault(); |
||||||
|
var c="mqtt?1=1"; |
||||||
|
var d,b=document.querySelectorAll("#mqtt-form input"); |
||||||
|
for(d=0; |
||||||
|
d<b.length; |
||||||
|
d++){if(b[d].type!="checkbox"){c+="&"+b[d].name+"="+b[d].value |
||||||
|
}}hideWarning(); |
||||||
|
var a=$("#mqtt-button"); |
||||||
|
addClass(a,"pure-button-disabled"); |
||||||
|
ajaxSpin("POST",c,function(e){showNotification("MQTT updated"); |
||||||
|
removeClass(a,"pure-button-disabled") |
||||||
|
},function(g,e){showWarning("Error: "+e); |
||||||
|
removeClass(a,"pure-button-disabled"); |
||||||
|
window.setTimeout(fetchMqtt,100) |
||||||
|
}) |
||||||
|
}function displayMqtt(c){Object.keys(c).forEach(function(d){el=$("#"+d); |
||||||
|
if(el!=null){if(el.nodeName==="INPUT"){el.value=c[d] |
||||||
|
}else{el.innerHTML=c[d] |
||||||
|
}return |
||||||
|
}el=document.querySelector('input[name="'+d+'"]'); |
||||||
|
if(el!=null){if(el.type=="checkbox"){el.checked=c[d]>0 |
||||||
|
}else{el.value=c[d] |
||||||
|
}}}); |
||||||
|
$("#mqtt-spinner").setAttribute("hidden",""); |
||||||
|
$("#mqtt-status-spinner").setAttribute("hidden",""); |
||||||
|
$("#mqtt-form").removeAttribute("hidden"); |
||||||
|
$("#mqtt-status-form").removeAttribute("hidden"); |
||||||
|
var b,a=$("input"); |
||||||
|
for(b=0; |
||||||
|
b<a.length; |
||||||
|
b++){if(a[b].type=="checkbox"){a[b].onclick=function(){setMqtt(this.name,this.checked) |
||||||
|
} |
||||||
|
}}}function fetchMqtt(){ajaxJson("GET","/mqtt",displayMqtt,function(){window.setTimeout(fetchMqtt,1000) |
||||||
|
}) |
||||||
|
}function changeMqttStatus(b){b.preventDefault(); |
||||||
|
var a=document.querySelector('input[name="mqtt-status-topic"]').value; |
||||||
|
ajaxSpin("POST","/mqtt?mqtt-status-topic="+a,function(){showNotification("MQTT status settings updated") |
||||||
|
},function(d,c){showWarning("Error: "+c); |
||||||
|
window.setTimeout(fetchMqtt,100) |
||||||
|
}) |
||||||
|
}function setMqtt(b,a){ajaxSpin("POST","/mqtt?"+b+"="+(a?1:0),function(){var c=b.replace("-enable",""); |
||||||
|
showNotification(c+" is now "+(a?"enabled":"disabled")) |
||||||
|
},function(){showWarning("Enable/disable failed"); |
||||||
|
window.setTimeout(fetchMqtt,100) |
||||||
|
}) |
||||||
|
}; |
@ -0,0 +1,8 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>Services</h1></div><div class=content><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Syslog <div id=syslog-spinner class="spinner spinner-small"></div></h1><form action="#" id=Syslog-form class=pure-form hidden><div class=pure-form-stacked><label>Syslog Host</label><input type=text name=syslog_host /><div class=popup>Esp-link sends event/debug info to this syslog host (hostname:port). Leave empty to disable syslog.</div></div><div class=pure-form-stacked><label>Min Heap</label><div><input type=text name=syslog_minheap /><div class=popup>Stop sending syslog if free heap drops below this many bytes</div></div><div><label>Filter</label><select name=syslog_filter href="#"><option value=0>EMERG</option><option value=1>ALERT</option><option value=2>CRIT</option><option value=3>ERR</option><option value=4>WARNING</option><option value=5>NOTICE</option><option value=6>INFO</option><option value=7>DEBUG</option></select><div class=popup>Minimum severity to send</div></div></div><div><input type=checkbox name=syslog_showtick /><label>Include esp-link millisecond ticker</label></div><div><input type=checkbox name=syslog_showdate /><label>Include esp-link datetime</label><div class=popup>Some syslog servers rotate log if timestamp is in the past so disable to prevent this</div></div><button id=Syslog-button type=submit class="pure-button button-primary"> Update Syslog settings! </button></form></div><div class=card><h1>mDNS <div id=mdns-spinner class="spinner spinner-small"></div></h1><form action="#" id=mDNS-form class=pure-form hidden><div class=form-horizontal><input type=checkbox name=mdns_enable /><label>Enable mDNS</label><div class=popup>Esp-link can advertise its hostname and service name (both with a .local suffix) via multicast DNS.</div></div><br><div class=pure-form-stacked><label>Service Name</label><input type=text name=mdns_servername /><div class=popup>The default service is http. For the arduino IDE use arduino</div></div><button id=mDNS-button type=submit class="pure-button button-primary"> Update mDNS settings! </button></form></div></div><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>SNTP <div id=sntp-spinner class="spinner spinner-small"></div></h1><form action="#" id=SNTP-form class=pure-form hidden><div class=pure-form-stacked><div><label>SNTP Server</label><input type=text name=sntp_server /><div class=popup>Simple Network Time Protocol server to query. Leave empty to disable SNTP</div></div><div><label>Timezone Offset</label><input type=text name=timezone_offset /><div class=popup>Offset hours to apply (no daylight savings support)</div></div></div><button id=SNTP-button type=submit class="pure-button button-primary"> Update SNTP settings! </button></form></div></div></div></div></div></div><script src="services.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
fetchServices(); |
||||||
|
bnd($("#Syslog-form"), "submit", changeServices); |
||||||
|
bnd($("#SNTP-form"), "submit", changeServices); |
||||||
|
bnd($("#mDNS-form"), "submit", changeServices); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,47 @@ |
|||||||
|
function changeServices(f){f.preventDefault(); |
||||||
|
var c="services/update?1=1"; |
||||||
|
var d,b=document.querySelectorAll("#"+f.target.id+" input,select"); |
||||||
|
for(d=0; |
||||||
|
d<b.length; |
||||||
|
d++){if(b[d].type=="checkbox"){if(b[d].name.slice(-6)=="enable"){continue |
||||||
|
}var g=(b[d].checked)?1:0; |
||||||
|
c+="&"+b[d].name+"="+g |
||||||
|
}else{c+="&"+b[d].name+"="+b[d].value |
||||||
|
}}hideWarning(); |
||||||
|
var h=f.target.id.replace("-form",""); |
||||||
|
var a=$("#"+h+"-button"); |
||||||
|
addClass(a,"pure-button-disabled"); |
||||||
|
ajaxSpin("POST",c,function(e){showNotification(h+" updated"); |
||||||
|
removeClass(a,"pure-button-disabled") |
||||||
|
},function(i,e){showWarning("Error: "+e); |
||||||
|
removeClass(a,"pure-button-disabled"); |
||||||
|
window.setTimeout(fetchServices,100) |
||||||
|
}) |
||||||
|
}function displayServices(c){Object.keys(c).forEach(function(d){el=$("#"+d); |
||||||
|
if(el!=null){if(el.nodeName==="INPUT"){el.value=c[d] |
||||||
|
}else{el.innerHTML=c[d] |
||||||
|
}return |
||||||
|
}el=document.querySelector('input[name="'+d+'"]'); |
||||||
|
if(el==null){el=document.querySelector('select[name="'+d+'"]') |
||||||
|
}if(el!=null){if(el.type=="checkbox"){el.checked=c[d]=="enabled" |
||||||
|
}else{el.value=c[d] |
||||||
|
}}}); |
||||||
|
$("#syslog-spinner").setAttribute("hidden",""); |
||||||
|
$("#sntp-spinner").setAttribute("hidden",""); |
||||||
|
$("#mdns-spinner").setAttribute("hidden",""); |
||||||
|
if(c.syslog_host!==undefined){$("#Syslog-form").removeAttribute("hidden") |
||||||
|
}else{$("#Syslog-form").parentNode.setAttribute("hidden","") |
||||||
|
}$("#SNTP-form").removeAttribute("hidden"); |
||||||
|
$("#mDNS-form").removeAttribute("hidden"); |
||||||
|
var b,a=$("input"); |
||||||
|
for(b=0; |
||||||
|
b<a.length; |
||||||
|
b++){if(a[b].name=="mdns_enable"){a[b].onclick=function(){setMDNS(this.checked) |
||||||
|
} |
||||||
|
}}}function setMDNS(a){ajaxSpin("POST","/services/update?mdns_enable="+(a?1:0),function(){showNotification("mDNS is now "+(a?"enabled":"disabled")) |
||||||
|
},function(){showWarning("Enable/disable failed"); |
||||||
|
window.setTimeout(fetchServices,100) |
||||||
|
}) |
||||||
|
}function fetchServices(){ajaxJson("GET","/services/info",displayServices,function(){window.setTimeout(fetchServices,1000) |
||||||
|
}) |
||||||
|
}; |
@ -0,0 +1,213 @@ |
|||||||
|
var bnd=function(c,b,a){c.addEventListener(b,a,false) |
||||||
|
}; |
||||||
|
var m=function(f,d,g){d=document; |
||||||
|
g=d.createElement("p"); |
||||||
|
g.innerHTML=f; |
||||||
|
f=d.createDocumentFragment(); |
||||||
|
while(d=g.firstChild){f.appendChild(d) |
||||||
|
}return f |
||||||
|
}; |
||||||
|
var $=function(d,c){d=d.match(/^(\W)?(.*)/); |
||||||
|
return(c||document)["getElement"+(d[1]?d[1]=="#"?"ById":"sByClassName":"sByTagName")](d[2]) |
||||||
|
}; |
||||||
|
var j=function(b){for(b=0; |
||||||
|
b<4; |
||||||
|
b++){try{return b?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][b]+".XMLHTTP"):new XMLHttpRequest |
||||||
|
}catch(c){}}}; |
||||||
|
function domForEach(b,a){return Array.prototype.forEach.call(b,a) |
||||||
|
}e=function(b){return document.createElement(b) |
||||||
|
}; |
||||||
|
function onLoad(b){var a=window.onload; |
||||||
|
if(typeof a!="function"){window.onload=b |
||||||
|
}else{window.onload=function(){a(); |
||||||
|
b() |
||||||
|
} |
||||||
|
}}function addClass(b,a){b.className+=" "+a |
||||||
|
}function removeClass(f,c){var b=f.className.split(/\s+/),a=b.length; |
||||||
|
for(var d=0; |
||||||
|
d<a; |
||||||
|
d++){if(b[d]===c){b.splice(d,1) |
||||||
|
}}f.className=b.join(" "); |
||||||
|
return b.length!=a |
||||||
|
}function toggleClass(b,a){if(!removeClass(b,a)){addClass(b,a) |
||||||
|
}}function ajaxReq(i,a,h,c,f){var g=j(); |
||||||
|
g.open(i,a,true); |
||||||
|
var d=setTimeout(function(){g.abort(); |
||||||
|
console.log("XHR abort:",i,a); |
||||||
|
g.status=599; |
||||||
|
g.responseText="request time-out" |
||||||
|
},9000); |
||||||
|
g.onreadystatechange=function(){if(g.readyState!=4){return |
||||||
|
}clearTimeout(d); |
||||||
|
if(g.status>=200&&g.status<300){h(g.responseText) |
||||||
|
}else{console.log("XHR ERR :",i,a,"->",g.status,g.responseText,g); |
||||||
|
c(g.status,g.responseText) |
||||||
|
}}; |
||||||
|
try{g.send(f) |
||||||
|
}catch(b){console.log("XHR EXC :",i,a,"->",b); |
||||||
|
c(599,b) |
||||||
|
}}function dispatchJson(f,d,c){var a; |
||||||
|
try{a=JSON.parse(f) |
||||||
|
}catch(b){console.log("JSON parse error: "+b+". In: "+f); |
||||||
|
c(500,"JSON parse error: "+b); |
||||||
|
return |
||||||
|
}d(a) |
||||||
|
}function ajaxJson(d,a,c,b){ajaxReq(d,a,function(f){dispatchJson(f,c,b) |
||||||
|
},b) |
||||||
|
}function ajaxSpin(d,a,c,b){$("#spinner").removeAttribute("hidden"); |
||||||
|
ajaxReq(d,a,function(f){$("#spinner").setAttribute("hidden",""); |
||||||
|
c(f) |
||||||
|
},function(f,g){$("#spinner").setAttribute("hidden",""); |
||||||
|
b(f,g) |
||||||
|
}) |
||||||
|
}function ajaxJsonSpin(d,a,c,b){ajaxSpin(d,a,function(f){dispatchJson(f,c,b) |
||||||
|
},b) |
||||||
|
}function hidePopup(a){addClass(a,"popup-hidden"); |
||||||
|
addClass(a.parentNode,"popup-target") |
||||||
|
}onLoad(function(){var a=$("#layout"); |
||||||
|
var d=a.childNodes[0]; |
||||||
|
a.insertBefore(m('<div id="spinner" class="spinner" hidden></div>'),d); |
||||||
|
a.insertBefore(m('<div id="messages"><div id="warning" hidden></div><div id="notification" hidden></div></div>'),d); |
||||||
|
a.insertBefore(m('<a href="#menu" id="menuLink" class="menu-link"><span></span></a>'),d); |
||||||
|
var c=m('<div id="menu"> <div class="pure-menu"> <a class="pure-menu-heading" href="https://github.com/jeelabs/esp-link"> <img src="/favicon.ico" height="32"> esp-link</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> '); |
||||||
|
a.insertBefore(c,d); |
||||||
|
var f=$("#menuLink"),c=$("#menu"); |
||||||
|
bnd(f,"click",function(h){var g="active"; |
||||||
|
h.preventDefault(); |
||||||
|
toggleClass(a,g); |
||||||
|
toggleClass(c,g); |
||||||
|
toggleClass(f,g) |
||||||
|
}); |
||||||
|
domForEach($(".popup"),function(g){hidePopup(g) |
||||||
|
}); |
||||||
|
var b=function(){ajaxJson("GET","/menu",function(n){var l="",o=window.location.pathname; |
||||||
|
for(var k=0; |
||||||
|
k<n.menu.length; |
||||||
|
k+=2){var h=n.menu[k+1]; |
||||||
|
l=l.concat(' <li class="pure-menu-item'+(o===h?" pure-menu-selected":"")+'"><a href="'+h+'" class="pure-menu-link">'+n.menu[k]+"</a></li>") |
||||||
|
}$("#menu-list").innerHTML=l; |
||||||
|
var g=$("#version"); |
||||||
|
if(g!=null){g.innerHTML=n.version |
||||||
|
}$("title")[0].innerHTML=n.name; |
||||||
|
setEditToClick("system-name",n.name) |
||||||
|
},function(){setTimeout(b,1000) |
||||||
|
}) |
||||||
|
}; |
||||||
|
b() |
||||||
|
}); |
||||||
|
function showWifiInfo(b){Object.keys(b).forEach(function(c){el=$("#wifi-"+c); |
||||||
|
if(el!=null){if(el.nodeName==="INPUT"){el.value=b[c] |
||||||
|
}else{el.innerHTML=b[c] |
||||||
|
}}}); |
||||||
|
var a=$("#dhcp-r"+b.dhcp); |
||||||
|
if(a){a.click() |
||||||
|
}$("#wifi-spinner").setAttribute("hidden",""); |
||||||
|
$("#wifi-table").removeAttribute("hidden"); |
||||||
|
currAp=b.ssid |
||||||
|
}function getWifiInfo(){ajaxJson("GET","/wifi/info",showWifiInfo,function(b,a){window.setTimeout(getWifiInfo,1000) |
||||||
|
}) |
||||||
|
}function showSystemInfo(a){Object.keys(a).forEach(function(b){setEditToClick("system-"+b,a[b]) |
||||||
|
}); |
||||||
|
$("#system-spinner").setAttribute("hidden",""); |
||||||
|
$("#system-table").removeAttribute("hidden"); |
||||||
|
currAp=a.ssid |
||||||
|
}function getSystemInfo(){ajaxJson("GET","/system/info",showSystemInfo,function(b,a){window.setTimeout(getSystemInfo,1000) |
||||||
|
}) |
||||||
|
}function makeAjaxInput(a,b){domForEach($("."+a+"-"+b),function(i){var f=$(".edit-on",i); |
||||||
|
var d=$(".edit-off",i)[0]; |
||||||
|
var c="/"+a+"/update?"+b; |
||||||
|
if(d===undefined||f==undefined){return |
||||||
|
}var h=function(){d.setAttribute("hidden",""); |
||||||
|
domForEach(f,function(k){k.removeAttribute("hidden") |
||||||
|
}); |
||||||
|
f[0].select(); |
||||||
|
return false |
||||||
|
}; |
||||||
|
var g=function(k){ajaxSpin("POST",c+"="+k,function(){domForEach(f,function(l){l.setAttribute("hidden","") |
||||||
|
}); |
||||||
|
d.removeAttribute("hidden"); |
||||||
|
setEditToClick(a+"-"+b,k); |
||||||
|
showNotification(b+" changed to "+k) |
||||||
|
},function(){showWarning(b+" change failed") |
||||||
|
}); |
||||||
|
return false |
||||||
|
}; |
||||||
|
bnd(d,"click",function(){return h() |
||||||
|
}); |
||||||
|
bnd(f[0],"blur",function(){return g(f[0].value) |
||||||
|
}); |
||||||
|
bnd(f[0],"keyup",function(k){if((k||window.event).keyCode==13){return g(f[0].value) |
||||||
|
}}) |
||||||
|
}) |
||||||
|
}function setEditToClick(a,b){domForEach($("."+a),function(c){if(c.children.length>0){domForEach(c.children,function(d){if(d.nodeName==="INPUT"){d.value=b |
||||||
|
}else{if(d.nodeName!=="DIV"){d.innerHTML=b |
||||||
|
}}}) |
||||||
|
}else{c.innerHTML=b |
||||||
|
}}) |
||||||
|
}function showWarning(b){var a=$("#warning"); |
||||||
|
a.innerHTML=b; |
||||||
|
a.removeAttribute("hidden"); |
||||||
|
window.scrollTo(0,0) |
||||||
|
}function hideWarning(){el=$("#warning").setAttribute("hidden","") |
||||||
|
}var notifTimeout=null; |
||||||
|
function showNotification(b){var a=$("#notification"); |
||||||
|
a.innerHTML=b; |
||||||
|
a.removeAttribute("hidden"); |
||||||
|
if(notifTimeout!=null){clearTimeout(notifTimeout) |
||||||
|
}notifTimout=setTimeout(function(){a.setAttribute("hidden",""); |
||||||
|
notifTimout=null |
||||||
|
},4000) |
||||||
|
}var pinPresets={"esp-01":[0,-1,2,-1,0,1],"esp-12":[12,14,0,2,0,1],"esp-12 swap":[1,3,0,2,1,1],"esp-bridge":[12,13,0,14,0,0],"wifi-link-12":[1,3,0,2,1,0]}; |
||||||
|
function createPresets(c){for(var d in pinPresets){var a=m('<option value="'+d+'">'+d+"</option>"); |
||||||
|
c.appendChild(a) |
||||||
|
}function b(h){var f=pinPresets[h]; |
||||||
|
if(f===undefined){return f |
||||||
|
}function g(l,i){$("#pin-"+l).value=i |
||||||
|
}g("reset",f[0]); |
||||||
|
g("isp",f[1]); |
||||||
|
g("conn",f[2]); |
||||||
|
g("ser",f[3]); |
||||||
|
g("swap",f[4]); |
||||||
|
$("#pin-rxpup").checked=!!f[5]; |
||||||
|
c.value=0 |
||||||
|
}bnd(c,"change",function(f){f.preventDefault(); |
||||||
|
b(c.value) |
||||||
|
}) |
||||||
|
}function displayPins(b){function a(f,c){var g=$("#pin-"+f); |
||||||
|
addClass(g,"pure-button"); |
||||||
|
g.innerHTML=""; |
||||||
|
[-1,0,1,2,3,4,5,12,13,14,15].forEach(function(k){var h=document.createElement("option"); |
||||||
|
h.value=k; |
||||||
|
if(k>=0){h.innerHTML="gpio"+k |
||||||
|
}else{h.innerHTML="disabled" |
||||||
|
}if(k===1){h.innerHTML+="/TX0" |
||||||
|
}if(k===2){h.innerHTML+="/TX1" |
||||||
|
}if(k===3){h.innerHTML+="/RX0" |
||||||
|
}if(k==c){h.selected=true |
||||||
|
}g.appendChild(h) |
||||||
|
}); |
||||||
|
var d=$(".popup",g.parentNode); |
||||||
|
if(d!==undefined){hidePopup(d[0]) |
||||||
|
}}a("reset",b.reset); |
||||||
|
a("isp",b.isp); |
||||||
|
a("conn",b.conn); |
||||||
|
a("ser",b.ser); |
||||||
|
$("#pin-swap").value=b.swap; |
||||||
|
$("#pin-rxpup").checked=!!b.rxpup; |
||||||
|
createPresets($("#pin-preset")); |
||||||
|
$("#pin-spinner").setAttribute("hidden",""); |
||||||
|
$("#pin-table").removeAttribute("hidden") |
||||||
|
}function fetchPins(){ajaxJson("GET","/pins",displayPins,function(){window.setTimeout(fetchPins,1000) |
||||||
|
}) |
||||||
|
}function setPins(c){c.preventDefault(); |
||||||
|
var b="/pins"; |
||||||
|
var a="?"; |
||||||
|
["reset","isp","conn","ser","swap"].forEach(function(d){b+=a+d+"="+$("#pin-"+d).value; |
||||||
|
a="&" |
||||||
|
}); |
||||||
|
b+="&rxpup="+($("#pin-rxpup").checked?"1":"0"); |
||||||
|
ajaxSpin("POST",b,function(){showNotification("Pin assignment changed") |
||||||
|
},function(d,f){showWarning(f); |
||||||
|
window.setTimeout(fetchPins,100) |
||||||
|
}) |
||||||
|
}; |
@ -0,0 +1,115 @@ |
|||||||
|
var loadCounter=0; |
||||||
|
var refreshRate=0; |
||||||
|
var refreshTimer; |
||||||
|
var hiddenInputs=[]; |
||||||
|
function notifyResponse(a){Object.keys(a).forEach(function(m){var c=document.getElementsByName(m); |
||||||
|
var n; |
||||||
|
for(n=0; |
||||||
|
n<c.length; |
||||||
|
n++){var d=c[n]; |
||||||
|
if(d.tagName=="INPUT"){if(d.type=="radio"){d.checked=a[m]==d.value |
||||||
|
}else{if(d.type=="checkbox"){if(a[m]=="on"){d.checked=true |
||||||
|
}else{if(a[m]=="off"){d.checked=false |
||||||
|
}else{if(a[m]==true){d.checked=true |
||||||
|
}else{d.checked=false |
||||||
|
}}}}else{d.value=a[m] |
||||||
|
}}}if(d.tagName=="SELECT"){d.value=a[m] |
||||||
|
}}var e=document.getElementById(m); |
||||||
|
if(e!=null){if(e.tagName=="P"||e.tagName=="DIV"||e.tagName=="SPAN"||e.tagName=="TR"||e.tagName=="TH"||e.tagName=="TD"||e.tagName=="TEXTAREA"){e.innerHTML=a[m] |
||||||
|
}if(e.tagName=="UL"||e.tagName=="OL"){var l=a[m]; |
||||||
|
var k=""; |
||||||
|
for(var h=0; |
||||||
|
h<l.length; |
||||||
|
h++){k=k.concat("<li>"+l[h]+"</li>") |
||||||
|
}e.innerHTML=k |
||||||
|
}if(e.tagName=="TABLE"){var l=a[m]; |
||||||
|
var k=""; |
||||||
|
if(l.length>0){var b=l[0]; |
||||||
|
k=k.concat("<tr>"); |
||||||
|
for(var h=0; |
||||||
|
h<b.length; |
||||||
|
h++){k=k.concat("<th>"+b[h]+"</th>") |
||||||
|
}k=k.concat("</tr>") |
||||||
|
}for(var h=1; |
||||||
|
h<l.length; |
||||||
|
h++){var g=l[h]; |
||||||
|
k=k.concat("<tr>"); |
||||||
|
for(var f=0; |
||||||
|
f<g.length; |
||||||
|
f++){k=k.concat("<td>"+g[f]+"</td>") |
||||||
|
}k=k.concat("</tr>") |
||||||
|
}e.innerHTML=k |
||||||
|
}}}); |
||||||
|
if(refreshRate!=0){clearTimeout(refreshTimer); |
||||||
|
refreshTimer=setTimeout(function(){ajaxJson("GET",window.location.pathname+".json?reason=refresh",notifyResponse) |
||||||
|
},refreshRate) |
||||||
|
}}function notifyButtonPressed(a){ajaxJson("POST",window.location.pathname+".json?reason=button&id="+a,notifyResponse) |
||||||
|
}function refreshFormData(){setTimeout(function(){ajaxJson("GET",window.location.pathname+".json?reason=refresh",function(a){notifyResponse(a); |
||||||
|
if(loadCounter>0){loadCounter--; |
||||||
|
refreshFormData() |
||||||
|
}}) |
||||||
|
},250) |
||||||
|
}function recalculateHiddenInputs(){for(var f=0; |
||||||
|
f<hiddenInputs.length; |
||||||
|
f++){var g=hiddenInputs[f]; |
||||||
|
var d=g.name; |
||||||
|
var b=document.getElementsByName(d); |
||||||
|
for(var c=0; |
||||||
|
c<b.length; |
||||||
|
c++){var a=b[c]; |
||||||
|
var e=a.type; |
||||||
|
if(e=="checkbox"){if(a.checked){g.disabled=true; |
||||||
|
g.value="on" |
||||||
|
}else{g.disabled=false; |
||||||
|
g.value="off" |
||||||
|
}}}}}document.addEventListener("DOMContentLoaded",function(){var btns=document.getElementsByTagName("button"); |
||||||
|
var ndx; |
||||||
|
for(ndx=0; |
||||||
|
ndx<btns.length; |
||||||
|
ndx++){var btn=btns[ndx]; |
||||||
|
var id=btn.getAttribute("id"); |
||||||
|
var onclk=btn.getAttribute("onclick"); |
||||||
|
var type=btn.getAttribute("type"); |
||||||
|
if(id!=null&&onclk==null&&type=="button"){var fn; |
||||||
|
eval('fn = function() { notifyButtonPressed("'+id+'") }'); |
||||||
|
btn.onclick=fn |
||||||
|
}}var frms=document.getElementsByTagName("form"); |
||||||
|
for(ndx=0; |
||||||
|
ndx<frms.length; |
||||||
|
ndx++){var frm=frms[ndx]; |
||||||
|
var method=frm.method; |
||||||
|
var action=frm.action; |
||||||
|
frm.method="POST"; |
||||||
|
frm.action=window.location.pathname+".json?reason=submit"; |
||||||
|
loadCounter=4; |
||||||
|
frm.onsubmit=function(){recalculateHiddenInputs(); |
||||||
|
refreshFormData(); |
||||||
|
return true |
||||||
|
} |
||||||
|
}var metas=document.getElementsByTagName("meta"); |
||||||
|
for(ndx=0; |
||||||
|
ndx<metas.length; |
||||||
|
ndx++){var meta=metas[ndx]; |
||||||
|
if(meta.getAttribute("name")=="refresh-rate"){refreshRate=meta.getAttribute("content") |
||||||
|
}}var inputs=document.getElementsByTagName("input"); |
||||||
|
for(ndx=0; |
||||||
|
ndx<inputs.length; |
||||||
|
ndx++){var inp=inputs[ndx]; |
||||||
|
if(inp.getAttribute("type")=="checkbox"){var name=inp.getAttribute("name"); |
||||||
|
var hasHidden=false; |
||||||
|
if(name!=null){var inpelems=document.getElementsByName(name); |
||||||
|
for(var i=0; |
||||||
|
i<inpelems.length; |
||||||
|
i++){var inptp=inpelems[i].type; |
||||||
|
if(inptp=="hidden"){hasHidden=true |
||||||
|
}}}if(!hasHidden){var parent=inp.parentElement; |
||||||
|
var input=document.createElement("input"); |
||||||
|
input.type="hidden"; |
||||||
|
input.name=inp.name; |
||||||
|
parent.appendChild(input); |
||||||
|
hiddenInputs.push(input) |
||||||
|
}}}var loadVariables=function(){ajaxJson("GET",window.location.pathname+".json?reason=load",notifyResponse,function(){setTimeout(loadVariables,1000) |
||||||
|
}) |
||||||
|
}; |
||||||
|
loadVariables() |
||||||
|
}); |
@ -0,0 +1,10 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>Web Server</h1></div><div class=content><p>User defined web pages can be uploaded to esp-link. This is useful if esp-link acts as a web server while MCU provides the measurement data.</p><form method=post action="web-server/upload" name=submit enctype="multipart/form-data" onSubmit="return onSubmit()">The custom web page to upload: <input type=file name=webpage multiple><input type=submit name=submit value=Submit></form></div></div><script> |
||||||
|
var allowSubmit = true; |
||||||
|
|
||||||
|
function onSubmit() { |
||||||
|
setTimeout(function() { |
||||||
|
window.location.reload(); |
||||||
|
}, 1000); |
||||||
|
return true; |
||||||
|
} |
||||||
|
</script></body></html> |
After Width: | Height: | Size: 425 B |
@ -0,0 +1,10 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>WiFi Soft-AP Configuration</h1></div><div class=content><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Soft-AP State</h1><div id=wifi-spinner class="spinner spinner-small"></div><table id=wifi-table class="pure-table pure-table-horizontal" hidden><tbody><tr><td>WiFi mode</td><td id=wifi-mode></td></tr><tr><td>Soft-AP SSID</td><td id=wifi-apssid></td></tr><tr><td>Soft-AP Password</td><td id=wifi-appass></td></tr><tr><td>Soft-AP Channel</td><td id=wifi-apchan></td></tr><tr><td>Soft-AP Max Conn</td><td id=wifi-apmaxc></td></tr><tr><td>Soft-AP Hidden</td><td id=wifi-aphidd></td></tr><tr><td>Soft-AP Beacon Int</td><td id=wifi-apbeac></td></tr><tr><td>Soft-AP Auth Mode</td><td id=wifi-apauth></td></tr><tr><td>Soft-AP MAC</td><td id=wifi-apmac></td></tr><tr><td colspan=2 id=wifi-apwarn></td></tr></tbody></table></div></div><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Soft-AP Settings</h1><div id=AP_Settings-spinner class="spinner spinner-small"></div><form action="#" id=AP_Settings-form class=pure-form hidden><legend>Soft-AP main settings, use with care!</legend><div class=pure-form-stacked><label>Soft-AP SSID</label><input type=text name=ap_ssid /><div class=popup>Change the name of your AP!</div></div><div class=pure-form-stacked><label>Soft-AP Password</label><input type=text name=ap_password /><div class=popup>Password must be at least 8 chars long!</div></div><div class=pure-form-stacked><label>Soft-AP Auth Mode</label><select name=ap_authmode href="#"><option value=0>OPEN</option><option value=1>WEP</option><option value=2>WPA_PSK</option><option value=3>WPA2_PSK</option><option value=4>WPA_WPA2_PSK</option></select><div class=popup>Default WPA_WPA2_PSK</div></div><div class=pure-form-stacked><label>Soft-AP Max Connections</label><input type=text name=ap_maxconn /><div class=popup>Max 4 ( default 4 )</div></div><div class=pure-form-stacked><label>Soft-AP Beacon Interval</label><input type=text name=ap_beacon /><div class=popup>Between 100 - 60000 ms ( default 100ms )</div></div><div class=form-horizontal><label><input type=checkbox name=ap_hidden />Soft-AP SSID hidden</label><div class=popup>Check this box to hide you Soft-AP SSID ( default Not Hidden )</div></div><button id=AP_Settings-button type=submit class="pure-button button-primary"> Change Soft-AP settings! </button></form></div></div></div></div></div></div><script type="text/javascript"></script><script src="wifiAp.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
// Show info about AP |
||||||
|
getWifiInfo(); |
||||||
|
// Fetch actual settings |
||||||
|
fetchApSettings(); |
||||||
|
// Wire-up form |
||||||
|
bnd($("#AP_Settings-form"), "submit", changeApSettings); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,53 @@ |
|||||||
|
var specials=[]; |
||||||
|
specials.ap_ssid="SSID name"; |
||||||
|
specials.ap_password="PASSWORD"; |
||||||
|
specials.ap_maxconn="Max Connections number"; |
||||||
|
specials.ap_beacon="Beacon Interval"; |
||||||
|
function changeWifiMode(a){blockScan=1; |
||||||
|
hideWarning(); |
||||||
|
ajaxSpin("POST","setmode?mode="+a,function(b){showNotification("Mode changed"); |
||||||
|
window.setTimeout(getWifiInfo,100); |
||||||
|
blockScan=0 |
||||||
|
},function(c,b){showWarning("Error changing mode: "+b); |
||||||
|
window.setTimeout(getWifiInfo,100); |
||||||
|
blockScan=0 |
||||||
|
}) |
||||||
|
}function changeApSettings(j){j.preventDefault(); |
||||||
|
var a="/wifi/apchange?100=1"; |
||||||
|
var f,h=document.querySelectorAll("#"+j.target.id+" input,select"); |
||||||
|
for(f=0; |
||||||
|
f<h.length; |
||||||
|
f++){if(h[f].type=="checkbox"){var c=(h[f].checked)?1:0; |
||||||
|
a+="&"+h[f].name+"="+c |
||||||
|
}else{var k=h[f].value.replace(/[^!-~]/g,""); |
||||||
|
var g=k.localeCompare(h[f].value); |
||||||
|
if(g!=0){showWarning("Invalid characters in "+specials[h[f].name]); |
||||||
|
return |
||||||
|
}a+="&"+h[f].name+"="+k |
||||||
|
}}hideWarning(); |
||||||
|
var b=j.target.id.replace("-form",""); |
||||||
|
var d=$("#"+b+"-button"); |
||||||
|
addClass(d,"pure-button-disabled"); |
||||||
|
ajaxSpin("POST",a,function(e){showNotification(b+" updated"); |
||||||
|
removeClass(d,"pure-button-disabled"); |
||||||
|
window.setTimeout(getWifiInfo,100) |
||||||
|
},function(i,e){showWarning(e); |
||||||
|
removeClass(d,"pure-button-disabled"); |
||||||
|
window.setTimeout(fetchApSettings,2000) |
||||||
|
}) |
||||||
|
}function displayApSettings(a){Object.keys(a).forEach(function(b){el=$("#"+b); |
||||||
|
if(el!=null){if(el.nodeName==="INPUT"){el.value=a[b] |
||||||
|
}else{el.innerHTML=a[b] |
||||||
|
}return |
||||||
|
}el=document.querySelector('input[name="'+b+'"]'); |
||||||
|
if(el==null){el=document.querySelector('select[name="'+b+'"]') |
||||||
|
}if(el!=null){if(el.type=="checkbox"){el.checked=a[b]=="enabled" |
||||||
|
}else{el.value=a[b] |
||||||
|
}}}); |
||||||
|
$("#AP_Settings-spinner").setAttribute("hidden",""); |
||||||
|
$("#AP_Settings-form").removeAttribute("hidden"); |
||||||
|
showWarning("Don't modify SOFTAP parameters with active connections"); |
||||||
|
window.setTimeout(hideWarning(),2000) |
||||||
|
}function fetchApSettings(){ajaxJson("GET","/wifi/apinfo",displayApSettings,function(){window.setTimeout(fetchApSettings,1000) |
||||||
|
}) |
||||||
|
}; |
@ -0,0 +1,10 @@ |
|||||||
|
<!doctype html><html><head><title>esp-link</title><link rel=stylesheet href="/pure.css"><link rel=stylesheet href="/style.css"><meta name=viewport content="width=device-width, initial-scale=1"><script src="/ui.js"></script></head><body><div id=layout><div id=main><div class=header><h1>WiFi Station Configuration</h1></div><div class=content><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>WiFi State</h1><div id=wifi-spinner class="spinner spinner-small"></div><table id=wifi-table class="pure-table pure-table-horizontal" hidden><tbody><tr><td>WiFi mode</td><td id=wifi-mode></td></tr><tr><td>WiFi channel</td><td id=wifi-chan></td></tr><tr><td>Configured network</td><td id=wifi-ssid></td></tr><tr><td>WiFi status</td><td id=wifi-status></td></tr><tr><td>WiFi address</td><td id=wifi-ip></td></tr><tr><td>WiFi rssi</td><td id=wifi-rssi></td></tr><tr><td>WiFi phy</td><td id=wifi-phy></td></tr><tr><td>WiFi MAC</td><td id=wifi-mac></td></tr><tr><td colspan=2 id=wifi-warn></td></tr></tbody></table></div></div><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>WiFi Association</h1><p id=reconnect style="color: #600" hidden></p><form action="#" id=wifiform class="pure-form pure-form-stacked"><legend>To connect to a WiFi network, please select one of the detected networks, enter the password, and hit the connect button...</legend><label>Network SSID</label><div id=aps>Scanning... <div class="spinner spinner-small"></div></div><label for=opt-hiddenssid><input type=radio name=essid value=_hidden_ssid_ id=opt-hiddenssid><input type=text id=hidden-ssid value="" style="width:auto; display:inline-block; margin-left: 0.7em"></label><label>WiFi password, if applicable:</label><input id=wifi-passwd type=password name=passwd placeholder=password><button id=connect-button type=submit class="pure-button button-primary">Connect!</button></form></div></div></div><div class=pure-g><div class="pure-u-1 pure-u-md-1-2"><div class=card><h1>Special Settings</h1><form action="#" id=specform class=pure-form><legend>Special settings, use with care!</legend><div class=form-horizontal><label for=dhcp-ron style="margin-right:1em"><input type=radio name=dhcp value=on id=dhcp-ron /> DHCP</label><label for=dhcp-roff><input type=radio name=dhcp value=off id=dhcp-roff /> Static IP</label></div><div id=dhcp-on class=pure-form-stacked></div><div id=dhcp-off class=pure-form-stacked><label>Static IP address</label><input id=wifi-staticip type=text name=staticip /><label>Netmask (for static IP)</label><input id=wifi-netmask type=text name=netmask /><label>Gateway (for static IP)</label><input id=wifi-gateway type=text name=gateway /></div><button id=special-button type=submit class="pure-button button-primary">Change!</button></form></div></div></div></div></div></div><script type="text/javascript"></script><script src="wifiSta.js"></script><script type="text/javascript"> |
||||||
|
onLoad(function() { |
||||||
|
getWifiInfo(); |
||||||
|
bnd($("#wifiform"), "submit", changeWifiAp); |
||||||
|
bnd($("#specform"), "submit", changeSpecial); |
||||||
|
bnd($("#dhcp-ron"), "click", doDhcp); |
||||||
|
bnd($("#dhcp-roff"), "click", doStatic); |
||||||
|
scanTimeout = window.setTimeout(scanAPs, 500); |
||||||
|
}); |
||||||
|
</script></body></html> |
@ -0,0 +1,134 @@ |
|||||||
|
var currAp=""; |
||||||
|
var blockScan=0; |
||||||
|
function createInputForAp(b){if(b.essid==""&&b.rssi==0){return |
||||||
|
}var g=e("input"); |
||||||
|
g.type="radio"; |
||||||
|
g.name="essid"; |
||||||
|
g.value=b.essid; |
||||||
|
g.id="opt-"+b.essid; |
||||||
|
if(currAp==b.essid){g.checked="1" |
||||||
|
}var i=e("div"); |
||||||
|
var j=-Math.floor(b.rssi/51)*32; |
||||||
|
i.className="lock-icon"; |
||||||
|
i.style.backgroundPosition="0px "+(j-1)+"px"; |
||||||
|
var d=e("div"); |
||||||
|
d.innerHTML=""+b.rssi+"dB"; |
||||||
|
var c=e("div"); |
||||||
|
var h="-65"; |
||||||
|
if(b.enc=="0"){h="0" |
||||||
|
}if(b.enc=="1"){h="-33" |
||||||
|
}c.className="lock-icon"; |
||||||
|
c.style.backgroundPosition="-32px "+h+"px"; |
||||||
|
var f=e("div"); |
||||||
|
f.innerHTML=b.essid; |
||||||
|
var a=m('<label for="opt-'+b.essid+'"></label>').childNodes[0]; |
||||||
|
a.appendChild(g); |
||||||
|
a.appendChild(c); |
||||||
|
a.appendChild(i); |
||||||
|
a.appendChild(d); |
||||||
|
a.appendChild(f); |
||||||
|
return a |
||||||
|
}function getSelectedEssid(){var c=document.forms.wifiform.elements; |
||||||
|
for(var b=0; |
||||||
|
b<c.length; |
||||||
|
b++){if(c[b].type=="radio"&&c[b].checked){var a=c[b].value; |
||||||
|
if(a=="_hidden_ssid_"){a=$("#hidden-ssid").value |
||||||
|
}return a |
||||||
|
}}return currAp |
||||||
|
}var scanTimeout=null; |
||||||
|
var scanReqCnt=0; |
||||||
|
function scanResult(){if(scanReqCnt>60){return scanAPs() |
||||||
|
}scanReqCnt+=1; |
||||||
|
ajaxJson("GET","scan",function(c){currAp=getSelectedEssid(); |
||||||
|
if(c.result.inProgress=="0"&&c.result.APs.length>0){$("#aps").innerHTML=""; |
||||||
|
var d=0; |
||||||
|
for(var b=0; |
||||||
|
b<c.result.APs.length; |
||||||
|
b++){if(c.result.APs[b].essid==""&&c.result.APs[b].rssi==0){continue |
||||||
|
}$("#aps").appendChild(createInputForAp(c.result.APs[b])); |
||||||
|
d=d+1 |
||||||
|
}showNotification("Scan found "+d+" networks"); |
||||||
|
var a=$("#connect-button"); |
||||||
|
a.className=a.className.replace(" pure-button-disabled",""); |
||||||
|
if(scanTimeout!=null){clearTimeout(scanTimeout) |
||||||
|
}scanTimeout=window.setTimeout(scanAPs,20000) |
||||||
|
}else{window.setTimeout(scanResult,1000) |
||||||
|
}},function(b,a){window.setTimeout(scanResult,5000) |
||||||
|
}) |
||||||
|
}function scanAPs(){if(blockScan){scanTimeout=window.setTimeout(scanAPs,1000); |
||||||
|
return |
||||||
|
}scanTimeout=null; |
||||||
|
scanReqCnt=0; |
||||||
|
ajaxReq("POST","scan",function(a){showNotification("Wifi scan started"); |
||||||
|
window.setTimeout(scanResult,1000) |
||||||
|
},function(b,a){if(b==400){showWarning("Cannot scan in AP mode"); |
||||||
|
$("#aps").innerHTML='Switch to <a href="#" onclick="changeWifiMode(3)">STA+AP mode</a> to scan.' |
||||||
|
}else{showWarning("Failed to scan: "+a) |
||||||
|
}}) |
||||||
|
}function getStatus(){ajaxJsonSpin("GET","connstatus",function(c){if(c.status=="idle"||c.status=="connecting"){$("#aps").innerHTML="Connecting..."; |
||||||
|
showNotification("Connecting..."); |
||||||
|
window.setTimeout(getStatus,1000) |
||||||
|
}else{if(c.status=="got IP address"){var a="Connected! Got IP "+c.ip; |
||||||
|
showNotification(a); |
||||||
|
showWifiInfo(c); |
||||||
|
blockScan=0; |
||||||
|
if(c.modechange=="yes"){var b="esp-link will switch to STA-only mode in a few seconds"; |
||||||
|
window.setTimeout(function(){showNotification(b) |
||||||
|
},4000) |
||||||
|
}$("#reconnect").removeAttribute("hidden"); |
||||||
|
$("#reconnect").innerHTML='If you are in the same network, go to <a href="http://'+c.ip+'/">'+c.ip+"</a>, else connect to network "+c.ssid+" first." |
||||||
|
}else{blockScan=0; |
||||||
|
showWarning("Connection failed: "+c.status+", "+c.reason); |
||||||
|
$("#aps").innerHTML='Check password and selected AP. <a href="wifi.tpl">Go Back</a>' |
||||||
|
}}},function(b,a){window.setTimeout(getStatus,2000) |
||||||
|
}) |
||||||
|
}function changeWifiMode(a){blockScan=1; |
||||||
|
hideWarning(); |
||||||
|
ajaxSpin("POST","setmode?mode="+a,function(b){showNotification("Mode changed"); |
||||||
|
window.setTimeout(getWifiInfo,100); |
||||||
|
blockScan=0; |
||||||
|
window.setTimeout(scanAPs,500); |
||||||
|
$("#aps").innerHTML='Scanning... <div class="spinner spinner-small"></div>' |
||||||
|
},function(c,b){showWarning("Error changing mode: "+b); |
||||||
|
window.setTimeout(getWifiInfo,100); |
||||||
|
blockScan=0 |
||||||
|
}) |
||||||
|
}function changeWifiAp(d){d.preventDefault(); |
||||||
|
var b=$("#wifi-passwd").value; |
||||||
|
var f=getSelectedEssid(); |
||||||
|
showNotification("Connecting to "+f); |
||||||
|
var c="connect?essid="+encodeURIComponent(f)+"&passwd="+encodeURIComponent(b); |
||||||
|
hideWarning(); |
||||||
|
$("#reconnect").setAttribute("hidden",""); |
||||||
|
$("#wifi-passwd").value=""; |
||||||
|
var a=$("#connect-button"); |
||||||
|
var g=a.className; |
||||||
|
a.className+=" pure-button-disabled"; |
||||||
|
blockScan=1; |
||||||
|
ajaxSpin("POST",c,function(h){$("#spinner").removeAttribute("hidden"); |
||||||
|
showNotification("Waiting for network change..."); |
||||||
|
window.scrollTo(0,0); |
||||||
|
window.setTimeout(getStatus,2000) |
||||||
|
},function(i,h){showWarning("Error switching network: "+h); |
||||||
|
a.className=g; |
||||||
|
window.setTimeout(scanAPs,1000) |
||||||
|
}) |
||||||
|
}function changeSpecial(c){c.preventDefault(); |
||||||
|
var b="special"; |
||||||
|
b+="?dhcp="+document.querySelector('input[name="dhcp"]:checked').value; |
||||||
|
b+="&staticip="+encodeURIComponent($("#wifi-staticip").value); |
||||||
|
b+="&netmask="+encodeURIComponent($("#wifi-netmask").value); |
||||||
|
b+="&gateway="+encodeURIComponent($("#wifi-gateway").value); |
||||||
|
hideWarning(); |
||||||
|
var a=$("#special-button"); |
||||||
|
addClass(a,"pure-button-disabled"); |
||||||
|
ajaxSpin("POST",b,function(d){removeClass(a,"pure-button-disabled") |
||||||
|
},function(f,d){showWarning("Error: "+d); |
||||||
|
removeClass(a,"pure-button-disabled"); |
||||||
|
getWifiInfo() |
||||||
|
}) |
||||||
|
}function doDhcp(){$("#dhcp-on").removeAttribute("hidden"); |
||||||
|
$("#dhcp-off").setAttribute("hidden","") |
||||||
|
}function doStatic(){$("#dhcp-off").removeAttribute("hidden"); |
||||||
|
$("#dhcp-on").setAttribute("hidden","") |
||||||
|
}; |
@ -0,0 +1,24 @@ |
|||||||
|
[platformio] |
||||||
|
env_default = esp12e |
||||||
|
|
||||||
|
[env:esp12e] |
||||||
|
platform = espressif8266 |
||||||
|
board = esp12e |
||||||
|
framework = esp8266-nonos-sdk |
||||||
|
monitor_speed = 115200 |
||||||
|
upload_resetmethod = ck |
||||||
|
;build_flags = -Wl,-Teagle.flash.1m0.ld |
||||||
|
build_flags = |
||||||
|
-Isrc/include -I. |
||||||
|
-DFIRMWARE_SIZE=503808 |
||||||
|
-DMCU_RESET_PIN=12 |
||||||
|
-DMCU_ISP_PIN=13 |
||||||
|
-DLED_CONN_PIN=0 |
||||||
|
-DLED_SERIAL_PIN=14 |
||||||
|
-DMQTT -DREST -DSOCKET -DWEBSERVER -DSYSLOG |
||||||
|
-DCHANGE_TO_STA=yes |
||||||
|
-DESP_HOSTNAME=esp-link-v3 |
||||||
|
|
||||||
|
upload_speed = 460800 |
||||||
|
#upload_speed = 230400 |
||||||
|
|
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGIFLASH_H |
#ifndef CGIFLASH_H |
||||||
#define CGIFLASH_H |
#define CGIFLASH_H |
||||||
|
|
||||||
#include "httpd.h" |
#include "httpd/httpd.h" |
||||||
|
|
||||||
int cgiReadFlash(HttpdConnData *connData); |
int cgiReadFlash(HttpdConnData *connData); |
||||||
int cgiGetFirmwareNext(HttpdConnData *connData); |
int cgiGetFirmwareNext(HttpdConnData *connData); |
@ -1,11 +1,11 @@ |
|||||||
|
|
||||||
#include <esp8266.h> |
#include <esp8266.h> |
||||||
#include "cgi.h" |
#include "cgi.h" |
||||||
#include "espfs.h" |
#include "espfs/espfs.h" |
||||||
#include "config.h" |
#include "config.h" |
||||||
#include "serled.h" |
#include "serial/serled.h" |
||||||
#include "status.h" |
#include "status.h" |
||||||
#include "serbridge.h" |
#include "serial/serbridge.h" |
||||||
|
|
||||||
#if 0 |
#if 0 |
||||||
static char *map_names[] = { |
static char *map_names[] = { |
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGIPINS_H |
#ifndef CGIPINS_H |
||||||
#define CGIPINS_H |
#define CGIPINS_H |
||||||
|
|
||||||
#include "httpd.h" |
#include "httpd/httpd.h" |
||||||
|
|
||||||
int cgiPins(HttpdConnData *connData); |
int cgiPins(HttpdConnData *connData); |
||||||
int8_t pin_reset, pin_isp, pin_conn, pin_ser; |
int8_t pin_reset, pin_isp, pin_conn, pin_ser; |
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGISERVICES_H |
#ifndef CGISERVICES_H |
||||||
#define CGISERVICES_H |
#define CGISERVICES_H |
||||||
|
|
||||||
#include "httpd.h" |
#include "httpd/httpd.h" |
||||||
|
|
||||||
int cgiSystemSet(HttpdConnData *connData); |
int cgiSystemSet(HttpdConnData *connData); |
||||||
int cgiSystemInfo(HttpdConnData *connData); |
int cgiSystemInfo(HttpdConnData *connData); |
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGITCP_H |
#ifndef CGITCP_H |
||||||
#define CGITCP_H |
#define CGITCP_H |
||||||
|
|
||||||
#include "httpd.h" |
#include "httpd/httpd.h" |
||||||
|
|
||||||
int cgiTcp(HttpdConnData *connData); |
int cgiTcp(HttpdConnData *connData); |
||||||
|
|
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGIWEBSERVER_H |
#ifndef CGIWEBSERVER_H |
||||||
#define CGIWEBSERVER_H |
#define CGIWEBSERVER_H |
||||||
|
|
||||||
#include <httpd.h> |
#include <httpd/httpd.h> |
||||||
|
|
||||||
int ICACHE_FLASH_ATTR cgiWebServerSetupUpload(HttpdConnData *connData); |
int ICACHE_FLASH_ATTR cgiWebServerSetupUpload(HttpdConnData *connData); |
||||||
|
|
@ -1,7 +1,7 @@ |
|||||||
#ifndef CGIWIFI_H |
#ifndef CGIWIFI_H |
||||||
#define CGIWIFI_H |
#define CGIWIFI_H |
||||||
|
|
||||||
#include "httpd.h" |
#include "httpd/httpd.h" |
||||||
|
|
||||||
enum { wifiIsDisconnected, wifiIsConnected, wifiGotIP }; |
enum { wifiIsDisconnected, wifiIsConnected, wifiGotIP }; |
||||||
typedef void(*WifiStateChangeCb)(uint8_t wifiStatus); |
typedef void(*WifiStateChangeCb)(uint8_t wifiStatus); |
@ -1,7 +1,7 @@ |
|||||||
#ifndef MULTIPART_H |
#ifndef MULTIPART_H |
||||||
#define MULTIPART_H |
#define MULTIPART_H |
||||||
|
|
||||||
#include <httpd.h> |
#include <httpd/httpd.h> |
||||||
|
|
||||||
typedef enum { |
typedef enum { |
||||||
FILE_UPLOAD_START, // multipart: uploading files started
|
FILE_UPLOAD_START, // multipart: uploading files started
|
@ -1,7 +1,7 @@ |
|||||||
// Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
|
// Copyright 2015 by Thorsten von Eicken, see LICENSE.txt
|
||||||
|
|
||||||
#include <esp8266.h> |
#include <esp8266.h> |
||||||
#include "uart.h" |
#include "serial/uart.h" |
||||||
#include "cgi.h" |
#include "cgi.h" |
||||||
#include "config.h" |
#include "config.h" |
||||||
#include "log.h" |
#include "log.h" |