Removed example project junk & added UART drivers
This commit is contained in:
@@ -1,96 +1,2 @@
|
||||
# esp-httpd README #
|
||||
|
||||
This is the demonstration project for the small but powerful libesphttpd webserver
|
||||
for ESP8266(EX) chips. It is an example of how to make a module that can have
|
||||
the AP it connects to configured over a webbrowser. It also illustrates multiple
|
||||
flash layouts and some OTA update functionality.
|
||||
|
||||
## ABOUT THE WEBSERVER ##
|
||||
|
||||
The Good (aka: what's awesome)
|
||||
- Supports multiple connections, for eg simultaneous html/css/js/images downloading
|
||||
- Static files stored in flash, in an (optionally compressed) RO filesystem
|
||||
- Pluggable using external cgi routines
|
||||
- Simple template engine for mixed c and html things
|
||||
- Usable as an embedded library - should be easy to drop into your existing projects
|
||||
- Includes websocket support
|
||||
|
||||
The Bad (aka: what can be improved)
|
||||
- Not built for speediness, although it's reasonable fast.
|
||||
- Built according to what I remember of the HTTP protocol, not according to the
|
||||
RFCs. Should work with most modern browsers, though.
|
||||
- No support for https.
|
||||
|
||||
The Ugly (aka: bugs, misbehaviour)
|
||||
- Possible buffer overflows (usually not remotely exploitable) due to no os_snprintf
|
||||
This can be theoretically remedied by either Espressif including an os_snprintf in
|
||||
their libs or by using some alternate printf lib, like elm-chans xprintf
|
||||
|
||||
## SOURCE OF THIS CODE ##
|
||||
The official esphttpd repo lives at http://git.spritesserver.nl/esphttpd.git/ and
|
||||
http://git.spritesserver.nl/libesphttpd.git/ . If you're a fan of Github, you can also
|
||||
peruse the official mirror at https://github.com/Spritetm/esphttpd and https://github.com/Spritetm/libesphttpd . If
|
||||
you want to discuss this code, there is a subforum at esp8266.com: http://www.esp8266.com/viewforum.php?f=34 .
|
||||
|
||||
|
||||
## ABOUT THE EXAMPLE ##
|
||||
|
||||
When you flash the example into an ESP8266(EX) module, you get a small webserver with a few example
|
||||
pages. If you've already connected your module to your WLAN before, it'll keep those settings. When
|
||||
you haven't or the settings are wrong, keep GPIO0 for >5 seconds. The module will reboot into
|
||||
its STA+AP mode. Connect a computer to the newly formed access point and browse to
|
||||
http://192.168.4.1/wifi in order to connect the module to your WiFi network. The example also
|
||||
allows you to control a LED that's connected to GPIO2.
|
||||
|
||||
## BUILDING EVERYTHING ##
|
||||
|
||||
For this, you need an environment that can compile ESP8266 firmware. Environments for this still
|
||||
are in flux at the moment, but I'm using esp-open-sdk: https://github.com/pfalcon/esp-open-sdk .
|
||||
You probably also need an UNIX-like system; I'm working on Debian Linux myself.
|
||||
|
||||
To manage the paths to all this, you can source a small shell fragment into your current session. For
|
||||
example, I source a file with these contents:
|
||||
|
||||
export PATH=${PWD}/esp-open-sdk/xtensa-lx106-elf/bin:$PATH
|
||||
export SDK_BASE=${PWD}/esp-open-sdk/sdk
|
||||
export ESPTOOL=${PWD}/esptool/esptool.py
|
||||
export ESPPORT=/dev/ttyUSB0
|
||||
export ESPBAUD=460800
|
||||
|
||||
Actual setup of the SDK and toolchain is out of the scope of this document, so I hope this helps you
|
||||
enough to set up your own if you haven't already.
|
||||
|
||||
If you have that, you can clone out the source code:
|
||||
git clone http://git.spritesserver.nl/esphttpd.git/
|
||||
|
||||
This project makes use of heatshrink, which is a git submodule. To fetch the code:
|
||||
|
||||
cd esphttpd
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
Now, build the code:
|
||||
|
||||
make
|
||||
|
||||
Depending on the way you built it, esp-open-sdk sometimes patches Espressifs SDK, needing a slightly different
|
||||
compiling process. If this is needed, you will get errors during compiling complaining about uint8_t being
|
||||
undeclared. If this happens, try building like this:
|
||||
|
||||
make USE_OPENSDK=yes
|
||||
|
||||
You can also edit the Makefile to change this more permanently.
|
||||
|
||||
After the compile process, flash the code happens in 2 steps. First the code itself gets flashed. Reset the module into bootloader
|
||||
mode and enter 'make flash'.
|
||||
|
||||
The 2nd step is to pack the static files the webserver will serve and flash that. Reset the module into
|
||||
bootloader mode again and enter `make htmlflash`.
|
||||
|
||||
You should have a working webserver now.
|
||||
|
||||
## WRITING CODE FOR THE WEBSERVER ##
|
||||
|
||||
Please see the README.md of the libesphttpd project for the programming manual.
|
||||
|
||||
|
||||
# esp-vt100-firmware
|
||||
ESP8266 Remote Terminal project
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
yuicompressor html_orig/style.css > html/style.css
|
||||
yuicompressor html_orig/script.js > html/script.js
|
||||
minify --type=html html_orig/index.html -o html/index.html
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 48 KiB |
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
var t=function(a,b){return function(c,d){return a.replace(/#{([^}]*)}/g,function(a,f){return Function("x","with(x)return "+f).call(c,d||b||{})})}},s=function(a,b){return b?{get:function(c){return a[c]&&b.parse(a[c])},set:function(c,d){a[c]=b.stringify(d)}}:{}}(this.localStorage||{},JSON),p=function(a,b,c,d){c=c||document;d=c[b="on"+b];a=c[b]=function(e){d=d&&d(e=e||c.event);return(a=a&&b(e))?b:d};c=this},m=function(a,b,c){b=document;c=b.createElement("p");c.innerHTML=a;for(a=b.createDocumentFragment();b=
|
||||
c.firstChild;)a.appendChild(b);return a},$=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},j=function(a){for(a=0;a<4;a++)try{return a?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][a]+".XMLHTTP"):new XMLHttpRequest}catch(b){}};
|
||||
@@ -1,82 +0,0 @@
|
||||
<html>
|
||||
<head><title>Upgrade firmware</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script type="text/javascript" src="140medley.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var xhr=j();
|
||||
|
||||
function doReboot() {
|
||||
//Grab the /flash/reboot url in order to reboot into the new firmware.
|
||||
xhr.open("GET", "reboot");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
//Reload the window after 5 seconds.
|
||||
window.setTimeout(function() {
|
||||
location.reload(true);
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
//Sets the progress bar to a specific level. Amt is between 0 and 1.
|
||||
function setProgress(amt) {
|
||||
$("#progressbarinner").style.width=String(amt*200)+"px";
|
||||
}
|
||||
|
||||
//Called when the submit button is called.
|
||||
function doUpgrade() {
|
||||
//Grab the file, see if it's a real file.
|
||||
var f=$("#file").files[0];
|
||||
if (typeof f=='undefined') {
|
||||
$("#remark").innerHTML="Can't read file!";
|
||||
return
|
||||
}
|
||||
xhr.open("POST", "upload");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
setProgress(1);
|
||||
if (xhr.responseText!="") {
|
||||
$("#remark").innerHTML="Error: "+xhr.responseText;
|
||||
} else {
|
||||
$("#remark").innerHTML="Uploading done. Rebooting.";
|
||||
doReboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
//If the webbrowser enables it, make progress bar show progress.
|
||||
if (typeof xhr.upload.onprogress != 'undefined') {
|
||||
xhr.upload.onprogress=function(e) {
|
||||
setProgress(e.loaded / e.total);
|
||||
}
|
||||
}
|
||||
//Upload the file
|
||||
xhr.send(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
window.onload=function(e) {
|
||||
//Grab the initial remark telling user which userx.bin file to upload.
|
||||
xhr.open("GET", "next");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
var txt="Please upload "+xhr.responseText+" or ota file.";
|
||||
$("#remark").innerHTML=txt;
|
||||
setProgress(0);
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<h1>Update firmware</h1>
|
||||
<div id="remark">Loading...</div>
|
||||
<input type="file" id="file" />
|
||||
<input type="submit" value="Upgrade!" onclick="doUpgrade()" />
|
||||
<div id="progressbar"><div id="progressbarinner"></div></div>
|
||||
</body>
|
||||
@@ -1,34 +0,0 @@
|
||||
|
||||
body {
|
||||
background-color: #404040;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: #d0d0FF;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #000000;
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
#progressbar {
|
||||
margin: 10px;
|
||||
padding: 0;
|
||||
border: 1px solid #000000;
|
||||
height: 20px;
|
||||
width: 200px;
|
||||
background-color: #808080;
|
||||
}
|
||||
|
||||
#progressbarinner {
|
||||
width: 10px;
|
||||
height: 20px;
|
||||
border: none;
|
||||
background-color: #00ff00;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<!doctype html><meta charset=utf-8><title>ESP8266 Remote Terminal</title><meta name=viewport content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"><link rel=stylesheet href=style.css><script src=script.js></script><header>ESP8266 Remote Terminal</header><div id=screen></div><div id=buttons><button>1</button><button>2</button><button>3</button><button>4</button></div><script>init()</script>
|
||||
@@ -1,28 +0,0 @@
|
||||
<html>
|
||||
<head><title>Esp8266 web server</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<h1>It Works</h1>
|
||||
<p>
|
||||
If you see this, it means the tiny li'l website in your ESP8266 does actually work. Fyi, this page has
|
||||
been loaded <b>%counter%</b> times.
|
||||
<ul>
|
||||
<li>If you haven't connected this device to your WLAN network now, you can <a href="/wifi">do so.</a></li>
|
||||
<li>You can also control the <a href="led.tpl">LED</a>.</li>
|
||||
<li>If you have a firmware upgrade file and the module is compiled for firmware upgrades, you
|
||||
can <a href="flash/index.html">upgrade the firmware</a> of this module.</li>
|
||||
<li>Esphttpd now also supports <a href="websocket/index.html">websockets</a>.</li>
|
||||
<li>Test esphttpd using the built-in <a href="test/">test suite</a></li>
|
||||
<li>And because I can, here's a link to my <a href="http://spritesmods.com/?f=esphttpd">website</a></ul>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>And because we're on the Internets now, here are the required pictures of cats:<br />
|
||||
<img src="cats/cross-eyed-cat.jpg"><br />
|
||||
<img src="cats/junge-katze-iv.jpg"><br />
|
||||
<img src="cats/kitten-loves-toy.jpg"><br />
|
||||
</p>
|
||||
</div>
|
||||
</body></html>
|
||||
@@ -1,15 +0,0 @@
|
||||
<html><head><title>Test</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<h1>The LED</h1>
|
||||
<p>
|
||||
If there's a LED connected to GPIO2, it's now %ledstate%. You can change that using the buttons below.
|
||||
</p>
|
||||
<form method="post" action="led.cgi">
|
||||
<input type="submit" name="led" value="1">
|
||||
<input type="submit" name="led" value="0">
|
||||
</form>
|
||||
</div>
|
||||
</body></html>
|
||||
@@ -0,0 +1 @@
|
||||
var $=function(d,c){d=d.match(/^(\W)?(.*)/);return(c||document)["getElement"+(d[1]?d[1]=="#"?"ById":"sByClassName":"sByTagName")](d[2])};var m=function(e,d,f){d=document;f=d.createElement("p");f.innerHTML=e;e=d.createDocumentFragment();while(d=f.firstChild){e.appendChild(d)}return e};(function(){function a(r){return document.createElement(r)}var b=26,k=10;var l={a:false,x:0,y:0,suppress:false,hidden:false};var o=[];var g=["#111213","#CC0000","#4E9A06","#C4A000","#3465A4","#75507B","#06989A","#D3D7CF","#555753","#EF2929","#8AE234","#FCE94F","#729FCF","#AD7FA8","#34E2E2","#EEEEEC"];function p(){o.forEach(function(r,s){r.t=" ";r.fg=7;r.bg=0;d(r)})}function c(s,r){return o[s*b+r]}function i(){return c(l.y,l.x)}function q(r){l.hidden=!r;l.a&=r;d(i(),l.a)}function f(s,r){l.suppress=true;d(i(),false);l.x=r;l.y=s;l.suppress=false;d(i(),l.a)}function d(s,r){var v=s.e,t,u;t=r?s.bg:s.fg;u=r?s.fg:s.bg;v.innerText=(s.t+" ")[0];v.style.color=e(t);v.style.backgroundColor=e(u);v.style.fontWeight=t>7?"bold":"normal"}function h(){o.forEach(function(s,t){var r=l.a&&(t==l.y*b+l.x);d(s,r)})}function j(s){if(s.length!=b*k*3){throw"Bad data format."}for(var t=0;t<b*k;t++){var r=o[t];r.t=s[t*3];r.fg=parseInt(s[t*3+1],16);r.bg=parseInt(s[t*3+2],16)}h()}function e(r){var r=parseInt(r);if(r<0||r>15){r=0}return g[r]}function n(){var u,t=$("#screen");for(var s=0;s<b*k;s++){u=a("span");if((s>0)&&(s%b==0)){t.appendChild(a("br"))}t.appendChild(u);var r={t:" ",fg:7,bg:0,e:u};o.push(r);d(r)}setInterval(function(){l.a=!l.a;if(l.hidden){l.a=false}if(!l.suppress){d(i(),l.a)}},500)}window.Term={init:n,load:j,setCursor:f,enableCursor:q,clear:p}})();(function(){var g="ws://"+window.location.host+"/ws/update.cgi";var d;function c(i){console.log("CONNECTED")}function b(i){console.error("SOCKET CLOSED")}function f(i){console.log("Message received!",i.data)}function e(i){console.error(i.data)}function a(i){d.send(i)}function h(){d=new WebSocket(g);d.onopen=c;d.onclose=b;d.onmessage=f;d.onerror=e;console.log("Opening socket.")}window.Conn={ws:null,init:h}})();function init(){Term.init();Conn.init()};
|
||||
+1
-17
@@ -1,17 +1 @@
|
||||
|
||||
body {
|
||||
background-color: #404040;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: #d0d0FF;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #000000;
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
html,body{background:#48505f;color:#eee;font-family:monospace;font-size:16pt;text-align:center}header{font-weight:bold;font-size:14pt;padding:6px;display:block}#screen{display:block;white-space:nowrap;background:#111213;border-radius:3px;padding:6px;box-shadow:inset 0 0 5px black;display:inline-block}#screen span{white-space:pre}#buttons{margin-top:10px}button{margin:0 2px;padding:10px 0;width:22%;max-width:80px;cursor:pointer}
|
||||
@@ -1,9 +0,0 @@
|
||||
<html><head><title>Webserver test</title></head>
|
||||
<link rel="stylesheet" type="text/css" href="../wifi/style.css">
|
||||
<script type="text/javascript" src="../wifi/140medley.min.js"></script>
|
||||
<script type="text/javascript" src="test.js"></script>
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="log">Initializing test...</div>
|
||||
</div>
|
||||
</body>
|
||||
@@ -1,205 +0,0 @@
|
||||
|
||||
/*
|
||||
Code to test the webserver. This depends on:
|
||||
- The cat images being available, for concurrent espfs testing
|
||||
- the test.cgi script available, for generic data mangling tests
|
||||
|
||||
|
||||
This test does a max of 4 requests in parallel. The nonos SDK supports a max of
|
||||
5 connections; the default libesphttpd setting is 4 sockets at a time. Unfortunately,
|
||||
the nonos sdk just closes all sockets opened after the available sockets are opened,
|
||||
instead of queueing them until a socket frees up.
|
||||
*/
|
||||
|
||||
|
||||
function log(line) {
|
||||
$("#log").insertAdjacentHTML('beforeend', line+'<br />');
|
||||
}
|
||||
|
||||
|
||||
//Load an image multiple times in parallel
|
||||
function testParLdImg(url, ct, doneFn) {
|
||||
var im=[];
|
||||
var state={"loaded":0, "count":ct, "doneFn": doneFn, "error":false};
|
||||
for (var x=0; x<ct; x++) {
|
||||
im[x]=new Image();
|
||||
im[x].onload=function(no) {
|
||||
log("File "+no+" loaded successfully.");
|
||||
this.loaded++;
|
||||
if (this.loaded==this.count) this.doneFn(!this.error);
|
||||
}.bind(state, x);
|
||||
im[x].onerror=function(no) {
|
||||
log("Error loading image "+no+"!");
|
||||
this.loaded++;
|
||||
this.error++;
|
||||
if (this.loaded==this.count) this.doneFn(!this.error);
|
||||
}.bind(state, x);
|
||||
im[x].src=url+"?"+Math.floor(Math.random()*100000).toString();
|
||||
}
|
||||
}
|
||||
|
||||
function testDownloadCgi(len, doneFn) {
|
||||
var xhr=j();
|
||||
var state={"len":len, "doneFn":doneFn, "ts": Date.now()};
|
||||
xhr.open("GET", "test.cgi?len="+len+"&nocache="+Math.floor(Math.random()*100000).toString());
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
if (xhr.response.length==this.len) {
|
||||
log("Downloaded "+this.len+" bytes successfully.");
|
||||
this.doneFn(true);
|
||||
} else {
|
||||
log("Downloaded "+xhr.response.length+" bytes successfully, but needed "+this.len+"!");
|
||||
this.doneFn(false);
|
||||
}
|
||||
} else if (xhr.readyState==4) {
|
||||
log("Failed! Error "+xhr.status);
|
||||
this.doneFn(false);
|
||||
}
|
||||
}.bind(state);
|
||||
//If the webbrowser enables it, show progress.
|
||||
if (typeof xhr.onprogress != 'undefined') {
|
||||
xhr.onprogress=function(e) {
|
||||
if (Date.now()>this.ts+2000) {
|
||||
log("..."+Math.floor(e.loaded*100/this.len).toString()+"%");
|
||||
this.ts=Date.now();
|
||||
}
|
||||
}.bind(state);
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
|
||||
function testUploadCgi(len, doneFn) {
|
||||
var xhr=j();
|
||||
var state={"len":len, "doneFn":doneFn, "ts": Date.now()};
|
||||
var data="";
|
||||
for (var x=0; x<len; x++) data+="X";
|
||||
xhr.open("POST", "test.cgi");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
var ulen=parseInt(xhr.responseText);
|
||||
if (ulen==this.len) {
|
||||
log("Uploaded "+this.len+" bytes successfully.");
|
||||
this.doneFn(true);
|
||||
} else {
|
||||
log("Webserver received "+ulen+" bytes successfully, but sent "+this.len+"!");
|
||||
this.doneFn(false);
|
||||
}
|
||||
} else if (xhr.readyState==4) {
|
||||
log("Failed! Error "+xhr.status);
|
||||
this.doneFn(false);
|
||||
}
|
||||
}.bind(state);
|
||||
//If the webbrowser enables it, show progress.
|
||||
if (typeof xhr.upload.onprogress != 'undefined') {
|
||||
xhr.upload.onprogress=function(e) {
|
||||
if (Date.now()>this.ts+2000) {
|
||||
log("..."+Math.floor(e.loaded*100/e.total).toString()+"%");
|
||||
this.ts=Date.now();
|
||||
}
|
||||
}.bind(state);
|
||||
}
|
||||
//Upload the file
|
||||
xhr.send(data);
|
||||
}
|
||||
|
||||
function hammerNext(state, xhr) {
|
||||
if (state.done==state.count) {
|
||||
state.doneFn(!state.error);
|
||||
}
|
||||
if (state.started==state.count) return;
|
||||
xhr.open("GET", "test.cgi?len="+state.len+"&nocache="+Math.floor(Math.random()*100000).toString());
|
||||
xhr.onreadystatechange=function(xhr) {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
if (xhr.response.length==this.len) {
|
||||
state.done++;
|
||||
hammerNext(this, xhr);
|
||||
} else {
|
||||
log("Downloaded "+xhr.response.length+" bytes successfully, but needed "+this.len+"!");
|
||||
state.done++;
|
||||
hammerNext(this, xhr);
|
||||
}
|
||||
} else if (xhr.readyState==4) {
|
||||
log("Failed! Error "+xhr.status);
|
||||
state.done++;
|
||||
hammerNext(this, xhr);
|
||||
}
|
||||
}.bind(state, xhr);
|
||||
//If the webbrowser enables it, show progress.
|
||||
if (typeof xhr.onprogress != 'undefined') {
|
||||
xhr.onprogress=function(e) {
|
||||
if (Date.now()>this.ts+2000) {
|
||||
log("..."+state.done+"/"+state.count);
|
||||
this.ts=Date.now();
|
||||
}
|
||||
}.bind(state);
|
||||
}
|
||||
state.started++;
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function testHammer(count, par, len, doneFn) {
|
||||
var state={"count":count, "started":0, "done":0, "par":par, "len":len, "doneFn":doneFn, "ts": Date.now(), "error":false};
|
||||
var xhr=[];
|
||||
for (var i=0; i<par; i++) {
|
||||
xhr[i]=j();
|
||||
hammerNext(state, xhr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var tstState=0;
|
||||
var successCnt=0;
|
||||
|
||||
function nextTest(lastOk) {
|
||||
if (tstState!=0) {
|
||||
if (lastOk) {
|
||||
log("<b>Success!</b>");
|
||||
successCnt++;
|
||||
} else {
|
||||
log("<b>Test failed!</b>");
|
||||
}
|
||||
}
|
||||
tstState++;
|
||||
if (tstState==1) {
|
||||
log("Testing parallel load of espfs files...");
|
||||
testParLdImg("../cats/kitten-loves-toy.jpg", 3, nextTest);
|
||||
} else if (tstState==2) {
|
||||
log("Testing GET request of 32K...");
|
||||
testDownloadCgi(32*1024, nextTest);
|
||||
} else if (tstState==3) {
|
||||
log("Testing GET request of 128K...");
|
||||
testDownloadCgi(128*1024, nextTest);
|
||||
} else if (tstState==4) {
|
||||
log("Testing GET request of 512K...");
|
||||
testDownloadCgi(512*1024, nextTest);
|
||||
} else if (tstState==5) {
|
||||
log("Testing POST request of 512 bytes...");
|
||||
testUploadCgi(512, nextTest);
|
||||
} else if (tstState==6) {
|
||||
log("Testing POST request of 16K bytes...");
|
||||
testUploadCgi(16*1024, nextTest);
|
||||
} else if (tstState==7) {
|
||||
log("Testing POST request of 512K bytes...");
|
||||
testUploadCgi(512*1024, nextTest);
|
||||
} else if (tstState==8) {
|
||||
log("Hammering webserver with 500 requests of size 512...");
|
||||
testHammer(500, 3, 512, nextTest);
|
||||
} else if (tstState==9) {
|
||||
log("Hammering webserver with 500 requests of size 2048...");
|
||||
testHammer(500, 3, 2048, nextTest);
|
||||
} else {
|
||||
log("Tests done! "+successCnt+" out of "+(tstState-1)+" tests were successful.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
window.onload=function(e) {
|
||||
log("Starting tests.");
|
||||
nextTest(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<meta charset="utf-8" />
|
||||
|
||||
<title>WebSocket Test</title>
|
||||
|
||||
<script language="javascript" type="text/javascript">
|
||||
|
||||
var wsUri = "ws://"+window.location.host+"/websocket/ws.cgi";
|
||||
var output;
|
||||
|
||||
function init()
|
||||
{
|
||||
output = document.getElementById("output");
|
||||
testWebSocket();
|
||||
}
|
||||
|
||||
function testWebSocket()
|
||||
{
|
||||
websocket = new WebSocket(wsUri);
|
||||
websocket.onopen = function(evt) { onOpen(evt) };
|
||||
websocket.onclose = function(evt) { onClose(evt) };
|
||||
websocket.onmessage = function(evt) { onMessage(evt) };
|
||||
websocket.onerror = function(evt) { onError(evt) };
|
||||
}
|
||||
|
||||
function onOpen(evt)
|
||||
{
|
||||
writeToScreen("CONNECTED");
|
||||
doSend("WebSocket rocks");
|
||||
}
|
||||
|
||||
function onClose(evt)
|
||||
{
|
||||
writeToScreen("DISCONNECTED");
|
||||
}
|
||||
|
||||
function onMessage(evt)
|
||||
{
|
||||
writeToScreen('<span style="color: blue;">RECEIVED: ' + evt.data+'</span>');
|
||||
// websocket.close();
|
||||
}
|
||||
|
||||
function onError(evt)
|
||||
{
|
||||
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
|
||||
}
|
||||
|
||||
function doSend(message)
|
||||
{
|
||||
writeToScreen("SENT: " + message);
|
||||
websocket.send(message);
|
||||
}
|
||||
|
||||
function writeToScreen(message)
|
||||
{
|
||||
var pre = document.createElement("p");
|
||||
pre.style.wordWrap = "break-word";
|
||||
pre.innerHTML = message;
|
||||
output.appendChild(pre);
|
||||
}
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
|
||||
</script>
|
||||
|
||||
<h2>WebSocket Test</h2>
|
||||
|
||||
<div id="output"></div>
|
||||
Vendored
-2
@@ -1,2 +0,0 @@
|
||||
var t=function(a,b){return function(c,d){return a.replace(/#{([^}]*)}/g,function(a,f){return Function("x","with(x)return "+f).call(c,d||b||{})})}},s=function(a,b){return b?{get:function(c){return a[c]&&b.parse(a[c])},set:function(c,d){a[c]=b.stringify(d)}}:{}}(this.localStorage||{},JSON),p=function(a,b,c,d){c=c||document;d=c[b="on"+b];a=c[b]=function(e){d=d&&d(e=e||c.event);return(a=a&&b(e))?b:d};c=this},m=function(a,b,c){b=document;c=b.createElement("p");c.innerHTML=a;for(a=b.createDocumentFragment();b=
|
||||
c.firstChild;)a.appendChild(b);return a},$=function(a,b){a=a.match(/^(\W)?(.*)/);return(b||document)["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2])},j=function(a){for(a=0;a<4;a++)try{return a?new ActiveXObject([,"Msxml2","Msxml3","Microsoft"][a]+".XMLHTTP"):new XMLHttpRequest}catch(b){}};
|
||||
@@ -1,43 +0,0 @@
|
||||
<html><head><title>Connecting...</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script type="text/javascript" src="140medley.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var xhr=j();
|
||||
|
||||
|
||||
function getStatus() {
|
||||
xhr.open("GET", "connstatus.cgi");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
var data=JSON.parse(xhr.responseText);
|
||||
if (data.status=="idle") {
|
||||
$("#status").innerHTML="Preparing to connect...";
|
||||
window.setTimeout(getStatus, 1000);
|
||||
} else if (data.status=="success") {
|
||||
$("#status").innerHTML="Connected! Got IP "+data.ip+". If you're in the same network, you can access it <a href=\"http://"+data.ip+"/\">here</a>.";
|
||||
} else if (data.status=="working") {
|
||||
$("#status").innerHTML="Trying to connect to selected access point...";
|
||||
window.setTimeout(getStatus, 1000);
|
||||
} else if (data.status=="fail") {
|
||||
$("#status").innerHTML="Connection failed. Check password and selected AP.<br /><a href=\"wifi.tpl\">Go Back</a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
window.onload=function(e) {
|
||||
getStatus();
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<h2>Connecting to AP...</h2>
|
||||
<p>Status:<br />
|
||||
<div id="status">...</div>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 914 B |
@@ -1,24 +0,0 @@
|
||||
|
||||
body {
|
||||
background-color: #404040;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#main {
|
||||
background-color: #d0d0FF;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid #000000;
|
||||
width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.icon {
|
||||
background-image: url("icons.png");
|
||||
background-color: transparent;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: inline-block;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
<html><head><title>WiFi connection</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script type="text/javascript" src="140medley.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var xhr=j();
|
||||
var currAp="%currSsid%";
|
||||
|
||||
function createInputForAp(ap) {
|
||||
if (ap.essid=="" && ap.rssi==0) return;
|
||||
var div=document.createElement("div");
|
||||
div.id="apdiv";
|
||||
var rssi=document.createElement("div");
|
||||
var rssiVal=-Math.floor(ap.rssi/51)*32;
|
||||
rssi.className="icon";
|
||||
rssi.style.backgroundPosition="0px "+rssiVal+"px";
|
||||
var encrypt=document.createElement("div");
|
||||
var encVal="-64"; //assume wpa/wpa2
|
||||
if (ap.enc=="0") encVal="0"; //open
|
||||
if (ap.enc=="1") encVal="-32"; //wep
|
||||
encrypt.className="icon";
|
||||
encrypt.style.backgroundPosition="-32px "+encVal+"px";
|
||||
var input=document.createElement("input");
|
||||
input.type="radio";
|
||||
input.name="essid";
|
||||
input.value=ap.essid;
|
||||
if (currAp==ap.essid) input.checked="1";
|
||||
input.id="opt-"+ap.essid;
|
||||
var label=document.createElement("label");
|
||||
label.htmlFor="opt-"+ap.essid;
|
||||
label.textContent=ap.essid;
|
||||
div.appendChild(input);
|
||||
div.appendChild(rssi);
|
||||
div.appendChild(encrypt);
|
||||
div.appendChild(label);
|
||||
return div;
|
||||
}
|
||||
|
||||
function getSelectedEssid() {
|
||||
var e=document.forms.wifiform.elements;
|
||||
for (var i=0; i<e.length; i++) {
|
||||
if (e[i].type=="radio" && e[i].checked) return e[i].value;
|
||||
}
|
||||
return currAp;
|
||||
}
|
||||
|
||||
|
||||
function scanAPs() {
|
||||
xhr.open("GET", "wifiscan.cgi");
|
||||
xhr.onreadystatechange=function() {
|
||||
if (xhr.readyState==4 && xhr.status>=200 && xhr.status<300) {
|
||||
var data=JSON.parse(xhr.responseText);
|
||||
currAp=getSelectedEssid();
|
||||
if (data.result.inProgress=="0" && data.result.APs.length>1) {
|
||||
$("#aps").innerHTML="";
|
||||
for (var i=0; i<data.result.APs.length; i++) {
|
||||
if (data.result.APs[i].essid=="" && data.result.APs[i].rssi==0) continue;
|
||||
$("#aps").appendChild(createInputForAp(data.result.APs[i]));
|
||||
}
|
||||
window.setTimeout(scanAPs, 20000);
|
||||
} else {
|
||||
window.setTimeout(scanAPs, 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
|
||||
window.onload=function(e) {
|
||||
scanAPs();
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main">
|
||||
<p>
|
||||
Current WiFi mode: %WiFiMode%
|
||||
</p>
|
||||
<p>
|
||||
Note: %WiFiapwarn%
|
||||
</p>
|
||||
<form name="wifiform" action="connect.cgi" method="post">
|
||||
<p>
|
||||
To connect to a WiFi network, please select one of the detected networks...<br>
|
||||
<div id="aps">Scanning...</div>
|
||||
<br>
|
||||
WiFi password, if applicable: <br />
|
||||
<input type="text" name="passwd" val="%WiFiPasswd%"> <br />
|
||||
<input type="submit" name="connect" value="Connect!">
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<title>ESP8266 Remote Terminal</title>
|
||||
<meta name="viewport" content="width=device-width,shrink-to-fit=no,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<script src="script.js"></script>
|
||||
|
||||
<!-- Katedra mereni FEL, 2017 -->
|
||||
<!-- TODO GitHub link -->
|
||||
|
||||
<header>ESP8266 Remote Terminal</header>
|
||||
|
||||
<div id="screen"></div>
|
||||
|
||||
<div id="buttons">
|
||||
<button>1</button><button>2</button><button>3</button><button>4</button>
|
||||
</div>
|
||||
|
||||
<script>init()</script>
|
||||
@@ -0,0 +1,271 @@
|
||||
//region Libs / utils
|
||||
|
||||
/*
|
||||
* 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.
|
||||
)
|
||||
};
|
||||
|
||||
/*
|
||||
* Create DOM element
|
||||
*
|
||||
* Usage:
|
||||
* var el = m('<h1>Hello</h1>');
|
||||
* document.body.appendChild(el);
|
||||
*
|
||||
*
|
||||
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
* Version 2, December 2004
|
||||
*
|
||||
* 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.
|
||||
};
|
||||
|
||||
//endregion
|
||||
|
||||
|
||||
//
|
||||
// Terminal class
|
||||
//
|
||||
(function () {
|
||||
function make(e) {return document.createElement(e)}
|
||||
|
||||
var W = 26, H = 10; //26, 10
|
||||
var cursor = {a: false, x: 0, y: 0, suppress: false, hidden: false};
|
||||
var screen = [];
|
||||
|
||||
/** Colors table */
|
||||
var CLR = [// dark gray #2E3436
|
||||
// 0 black, 1 red, 2 green, 3 yellow
|
||||
// 4 blue, 5 mag, 6 cyan, 7 white
|
||||
'#111213','#CC0000','#4E9A06','#C4A000',
|
||||
'#3465A4','#75507B','#06989A','#D3D7CF',
|
||||
// BRIGHT
|
||||
// 8 black, 9 red, 10 green, 11 yellow
|
||||
// 12 blue, 13 mag, 14 cyan, 15 white
|
||||
'#555753','#EF2929','#8AE234','#FCE94F',
|
||||
'#729FCF','#AD7FA8','#34E2E2','#EEEEEC'
|
||||
];
|
||||
|
||||
/** Clear screen */
|
||||
function cls() {
|
||||
screen.forEach(function(cell, i) {
|
||||
cell.t = ' ';
|
||||
cell.fg = 7;
|
||||
cell.bg = 0;
|
||||
blit(cell);
|
||||
});
|
||||
}
|
||||
|
||||
/** Set text and color at XY */
|
||||
function cellAt(y, x) {
|
||||
return screen[y*W+x];
|
||||
}
|
||||
|
||||
/** Get cell under cursor */
|
||||
function cursorCell() {
|
||||
return cellAt(cursor.y, cursor.x);
|
||||
}
|
||||
|
||||
/** Enable or disable cursor visibility */
|
||||
function cursorEnable(enable) {
|
||||
cursor.hidden = !enable;
|
||||
cursor.a &= enable;
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
|
||||
/** Safely move cursor */
|
||||
function cursorSet(y, x) {
|
||||
// Hide and prevent from showing up during the move
|
||||
cursor.suppress = true;
|
||||
blit(cursorCell(), false);
|
||||
|
||||
cursor.x = x;
|
||||
cursor.y = y;
|
||||
|
||||
// Show again
|
||||
cursor.suppress = false;
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
|
||||
/** Update cell on display. inv = invert (for cursor) */
|
||||
function blit(cell, inv) {
|
||||
var e = cell.e, fg, bg;
|
||||
// Colors
|
||||
fg = inv ? cell.bg : cell.fg;
|
||||
bg = inv ? cell.fg : cell.bg;
|
||||
// Update
|
||||
e.innerText = (cell.t+' ')[0];
|
||||
e.style.color = colorHex(fg);
|
||||
e.style.backgroundColor = colorHex(bg);
|
||||
e.style.fontWeight = fg > 7 ? 'bold' : 'normal';
|
||||
}
|
||||
|
||||
/** Show entire screen */
|
||||
function blitAll() {
|
||||
screen.forEach(function(cell, i) {
|
||||
/* Invert if under cursor & cursor active */
|
||||
var inv = cursor.a && (i == cursor.y*W+cursor.x);
|
||||
blit(cell, inv);
|
||||
});
|
||||
}
|
||||
|
||||
/** Load screen content from a 'binary' sequence */
|
||||
function load(seq) {
|
||||
if (seq.length != W*H*3) throw "Bad data format.";
|
||||
|
||||
// primitive format with 3 chars per cell: letter, fg [hex], bg [hex]
|
||||
for (var i = 0; i < W * H; i++) {
|
||||
var cell = screen[i];
|
||||
cell.t = seq[i*3];
|
||||
cell.fg = parseInt(seq[i*3+1], 16);
|
||||
cell.bg = parseInt(seq[i*3+2], 16);
|
||||
}
|
||||
|
||||
blitAll();
|
||||
}
|
||||
|
||||
/** Parse color */
|
||||
function colorHex(c) {
|
||||
var c = parseInt(c);
|
||||
if (c < 0 || c > 15) c = 0;
|
||||
return CLR[c];
|
||||
}
|
||||
|
||||
/** Init the terminal */
|
||||
function init() {
|
||||
/* Build screen & show */
|
||||
var e, scr = $('#screen');
|
||||
for(var i = 0; i < W*H; i++) {
|
||||
e = make('span');
|
||||
|
||||
/* End of line */
|
||||
if ((i > 0) && (i % W == 0)) {
|
||||
scr.appendChild(make('br'));
|
||||
}
|
||||
/* The cell */
|
||||
scr.appendChild(e);
|
||||
|
||||
var cell = {t: ' ', fg: 7, bg: 0, e: e};
|
||||
screen.push(cell);
|
||||
blit(cell);
|
||||
}
|
||||
|
||||
/* Cursor blinking */
|
||||
setInterval(function() {
|
||||
cursor.a = !cursor.a;
|
||||
if (cursor.hidden) {
|
||||
cursor.a = false;
|
||||
}
|
||||
|
||||
if (!cursor.suppress) {
|
||||
blit(cursorCell(), cursor.a);
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// publish
|
||||
window.Term = {
|
||||
init: init,
|
||||
load: load,
|
||||
setCursor: cursorSet,
|
||||
enableCursor: cursorEnable,
|
||||
clear: cls,
|
||||
};
|
||||
})();
|
||||
|
||||
//
|
||||
// Connection class
|
||||
//
|
||||
(function() {
|
||||
var wsUri = "ws://"+window.location.host+"/ws/update.cgi";
|
||||
var ws;
|
||||
|
||||
function onOpen(evt) {
|
||||
console.log("CONNECTED");
|
||||
}
|
||||
|
||||
function onClose(evt) {
|
||||
console.error("SOCKET CLOSED");
|
||||
}
|
||||
|
||||
function onMessage(evt) {
|
||||
console.log("Message received!", evt.data);
|
||||
// TODO process
|
||||
}
|
||||
|
||||
function onError(evt) {
|
||||
console.error(evt.data);
|
||||
}
|
||||
|
||||
function doSend(message) {
|
||||
ws.send(message);
|
||||
}
|
||||
|
||||
function init() {
|
||||
ws = new WebSocket(wsUri);
|
||||
ws.onopen = onOpen;
|
||||
ws.onclose = onClose
|
||||
ws.onmessage = onMessage;
|
||||
ws.onerror = onError;
|
||||
|
||||
console.log("Opening socket.");
|
||||
}
|
||||
|
||||
window.Conn = {
|
||||
ws: null,
|
||||
init: init,
|
||||
};
|
||||
})();
|
||||
|
||||
function init() {
|
||||
Term.init();
|
||||
Conn.init();
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
html, body {
|
||||
background: #48505F;
|
||||
color: #eee;
|
||||
font-family: monospace;
|
||||
font-size: 16pt;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
header {
|
||||
font-weight: bold;
|
||||
font-size: 14pt;
|
||||
padding: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#screen {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
background: #111213;
|
||||
border-radius: 3px;
|
||||
padding: 6px;
|
||||
box-shadow: inset 0 0 5px black;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#screen span {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#buttons {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0 2px;
|
||||
padding: 10px 0;
|
||||
width: 22%;
|
||||
max-width: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <c_types.h>
|
||||
|
||||
// copied from nodemcu source
|
||||
extern uint32_t system_get_time();
|
||||
extern uint32_t platform_tmr_exists(uint32_t t);
|
||||
extern uint32_t system_rtc_clock_cali_proc();
|
||||
extern uint32_t system_get_rtc_time();
|
||||
extern void system_restart();
|
||||
extern void system_soft_wdt_feed();
|
||||
|
||||
// https://github.com/mziwisky/esp8266-dev/blob/master/esphttpd/include/espmissingincludes.h
|
||||
extern int ets_str2macaddr(void *, void *);
|
||||
extern void ets_update_cpu_frequency(int freqmhz);
|
||||
extern int os_printf_plus(const char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
//extern uint8 wifi_get_opmode(void);
|
||||
extern void ets_bzero(void *s, size_t n);
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
Cgi routines as used by the tests in the html/test subdirectory.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <esp8266.h>
|
||||
#include "cgi-test.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
int sendPos;
|
||||
} TestbedState;
|
||||
|
||||
|
||||
httpd_cgi_state ICACHE_FLASH_ATTR cgiTestbed(HttpdConnData *connData) {
|
||||
char buff[1024];
|
||||
int first=0;
|
||||
int l, x;
|
||||
TestbedState *state=(TestbedState*)connData->cgiData;
|
||||
|
||||
if (connData->conn==NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
if (state) free(state);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
if (state==NULL) {
|
||||
//First call
|
||||
state=malloc(sizeof(TestbedState));
|
||||
memset(state, 0, sizeof(state));
|
||||
connData->cgiData=state;
|
||||
first=1;
|
||||
}
|
||||
|
||||
if (connData->requestType==HTTPD_METHOD_GET) {
|
||||
if (first) {
|
||||
httpdStartResponse(connData, 200);
|
||||
httpdHeader(connData, "content-type", "application/data");
|
||||
httpdEndHeaders(connData);
|
||||
l=httpdFindArg(connData->getArgs, "len", buff, sizeof(buff));
|
||||
state->len=1024;
|
||||
if (l!=-1) state->len=atoi(buff);
|
||||
state->sendPos=0;
|
||||
return HTTPD_CGI_MORE;
|
||||
} else {
|
||||
l=sizeof(buff);
|
||||
if (l>(state->len-state->sendPos)) l=(state->len-state->sendPos);
|
||||
//Fill with semi-random data
|
||||
for (x=0; x<l; x++) buff[x]=((x^(state->sendPos>>10))&0x1F)+'0';
|
||||
httpdSend(connData, buff, l);
|
||||
state->sendPos+=l;
|
||||
printf("Test: Uploaded %d/%d bytes\n", state->sendPos, state->len);
|
||||
if (state->len<=state->sendPos) {
|
||||
if (state) free(state);
|
||||
return HTTPD_CGI_DONE;
|
||||
} else {
|
||||
return HTTPD_CGI_MORE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (connData->requestType==HTTPD_METHOD_POST) {
|
||||
if (connData->post->len!=connData->post->received) {
|
||||
//Still receiving data. Ignore this.
|
||||
printf("Test: got %d/%d bytes\n", connData->post->received, connData->post->len);
|
||||
return HTTPD_CGI_MORE;
|
||||
} else {
|
||||
httpdStartResponse(connData, 200);
|
||||
httpdHeader(connData, "content-type", "text/plain");
|
||||
httpdEndHeaders(connData);
|
||||
l=sprintf(buff, "%d", connData->post->received);
|
||||
httpdSend(connData, buff, l);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
}
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#ifndef CGI_TEST_H
|
||||
#define CGI_TEST_H
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
httpd_cgi_state cgiTestbed(HttpdConnData *connData);
|
||||
|
||||
#endif
|
||||
-76
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
Some random cgi routines. Used in the LED example and the page that returns the entire
|
||||
flash as a binary. Also handles the hit counter on the main page.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <esp8266.h>
|
||||
#include "cgi.h"
|
||||
#include "io.h"
|
||||
|
||||
|
||||
//cause I can't be bothered to write an ioGetLed()
|
||||
static char currLedState=0;
|
||||
|
||||
//Cgi that turns the LED on or off according to the 'led' param in the POST data
|
||||
httpd_cgi_state ICACHE_FLASH_ATTR cgiLed(HttpdConnData *connData) {
|
||||
int len;
|
||||
char buff[1024];
|
||||
|
||||
if (connData->conn==NULL) {
|
||||
//Connection aborted. Clean up.
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
len=httpdFindArg(connData->post->buff, "led", buff, sizeof(buff));
|
||||
if (len!=0) {
|
||||
currLedState=atoi(buff);
|
||||
ioLed(currLedState);
|
||||
}
|
||||
|
||||
httpdRedirect(connData, "led.tpl");
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Template code for the led page.
|
||||
httpd_cgi_state ICACHE_FLASH_ATTR tplLed(HttpdConnData *connData, char *token, void **arg) {
|
||||
char buff[128];
|
||||
if (token==NULL) return HTTPD_CGI_DONE;
|
||||
|
||||
os_strcpy(buff, "Unknown");
|
||||
if (os_strcmp(token, "ledstate")==0) {
|
||||
if (currLedState) {
|
||||
os_strcpy(buff, "on");
|
||||
} else {
|
||||
os_strcpy(buff, "off");
|
||||
}
|
||||
}
|
||||
httpdSend(connData, buff, -1);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
|
||||
static long hitCounter=0;
|
||||
|
||||
//Template code for the counter on the index page.
|
||||
httpd_cgi_state ICACHE_FLASH_ATTR tplCounter(HttpdConnData *connData, char *token, void **arg) {
|
||||
char buff[128];
|
||||
if (token==NULL) return HTTPD_CGI_DONE;
|
||||
|
||||
if (os_strcmp(token, "counter")==0) {
|
||||
hitCounter++;
|
||||
os_sprintf(buff, "%ld", hitCounter);
|
||||
}
|
||||
httpdSend(connData, buff, -1);
|
||||
return HTTPD_CGI_DONE;
|
||||
}
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
#ifndef CGI_H
|
||||
#define CGI_H
|
||||
|
||||
#include "httpd.h"
|
||||
|
||||
httpd_cgi_state cgiLed(HttpdConnData *connData);
|
||||
httpd_cgi_state tplLed(HttpdConnData *connData, char *token, void **arg);
|
||||
httpd_cgi_state tplCounter(HttpdConnData *connData, char *token, void **arg);
|
||||
|
||||
#endif
|
||||
@@ -14,6 +14,8 @@
|
||||
#define LEDGPIO 2
|
||||
#define BTNGPIO 0
|
||||
|
||||
static bool enable_ap_button = false;
|
||||
|
||||
static ETSTimer resetBtntimer;
|
||||
|
||||
void ICACHE_FLASH_ATTR ioLed(int ena) {
|
||||
@@ -27,25 +29,34 @@ void ICACHE_FLASH_ATTR ioLed(int ena) {
|
||||
|
||||
static void ICACHE_FLASH_ATTR resetBtnTimerCb(void *arg) {
|
||||
static int resetCnt=0;
|
||||
if (!GPIO_INPUT_GET(BTNGPIO)) {
|
||||
if (enable_ap_button && !GPIO_INPUT_GET(BTNGPIO)) {
|
||||
resetCnt++;
|
||||
} else {
|
||||
if (resetCnt>=6) { //3 sec pressed
|
||||
wifi_station_disconnect();
|
||||
wifi_set_opmode(0x3); //reset to AP+STA mode
|
||||
os_printf("Reset to AP mode. Restarting system...\n");
|
||||
wifi_set_opmode(STATIONAP_MODE); //reset to AP+STA mode
|
||||
info("Reset to AP mode from GPIO0, Restarting system...");
|
||||
system_restart();
|
||||
}
|
||||
resetCnt=0;
|
||||
}
|
||||
}
|
||||
|
||||
void ioInit() {
|
||||
void ICACHE_FLASH_ATTR ioInit() {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
|
||||
gpio_output_set(0, 0, (1<<LEDGPIO), (1<<BTNGPIO));
|
||||
os_timer_disarm(&resetBtntimer);
|
||||
os_timer_setfn(&resetBtntimer, resetBtnTimerCb, NULL);
|
||||
os_timer_arm(&resetBtntimer, 500, 1);
|
||||
|
||||
// One way to enter AP mode - hold GPIO0 low.
|
||||
if (GPIO_INPUT_GET(BTNGPIO) == 0) {
|
||||
// starting "in BOOT mode" - do not install the AP reset timer
|
||||
warn("GPIO0 stuck low - AP reset button disabled.\n");
|
||||
} else {
|
||||
enable_ap_button = true;
|
||||
dbg("Note: Hold GPIO0 low for reset to AP mode.\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
|
||||
void ICACHE_FLASH_ATTR ioLed(int ena);
|
||||
void ioLed(int ena);
|
||||
void ioInit(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <esp8266.h>
|
||||
#include "uart_driver.h"
|
||||
#include "uart_handler.h"
|
||||
|
||||
// Here the bitrates are defined
|
||||
#define UART0_BAUD BIT_RATE_115200
|
||||
#define UART1_BAUD BIT_RATE_115200
|
||||
|
||||
/**
|
||||
* Init the serial ports
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR serialInit(void)
|
||||
{
|
||||
UART_Init(UART0_BAUD, UART1_BAUD);
|
||||
UART_SetPrintPort(UART0);
|
||||
UART_SetupAsyncReceiver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a byte received from UART.
|
||||
* Might do some buffering here maybe
|
||||
*
|
||||
* @param c
|
||||
*/
|
||||
void ICACHE_FLASH_ATTR UART_HandleRxByte(char c)
|
||||
{
|
||||
printf("'%c',", c);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef SERIAL_H
|
||||
#define SERIAL_H
|
||||
|
||||
/** Init the uarts */
|
||||
void serialInit(void);
|
||||
|
||||
void UART_HandleRxByte(char c);
|
||||
|
||||
#endif //SERIAL_H
|
||||
@@ -1,47 +0,0 @@
|
||||
//Stupid bit of code that does the bare minimum to make os_printf work.
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <esp8266.h>
|
||||
#include <uart_hw.h>
|
||||
|
||||
static void ICACHE_FLASH_ATTR stdoutUartTxd(char c) {
|
||||
//Wait until there is room in the FIFO
|
||||
while (((READ_PERI_REG(UART_STATUS(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
|
||||
//Send the character
|
||||
WRITE_PERI_REG(UART_FIFO(0), c);
|
||||
}
|
||||
|
||||
static void ICACHE_FLASH_ATTR stdoutPutchar(char c) {
|
||||
//convert \n -> \r\n
|
||||
if (c=='\n') stdoutUartTxd('\r');
|
||||
stdoutUartTxd(c);
|
||||
}
|
||||
|
||||
|
||||
void stdoutInit() {
|
||||
//Enable TxD pin
|
||||
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
|
||||
|
||||
//Set baud rate and other serial parameters to 115200,n,8,1
|
||||
uart_div_modify(0, UART_CLK_FREQ/BIT_RATE_115200);
|
||||
WRITE_PERI_REG(UART_CONF0(0), (STICK_PARITY_DIS)|(ONE_STOP_BIT << UART_STOP_BIT_NUM_S)| \
|
||||
(EIGHT_BITS << UART_BIT_NUM_S));
|
||||
|
||||
//Reset tx & rx fifo
|
||||
SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST|UART_TXFIFO_RST);
|
||||
//Clear pending interrupts
|
||||
WRITE_PERI_REG(UART_INT_CLR(0), 0xffff);
|
||||
|
||||
//Install our own putchar handler
|
||||
os_install_putc1((void *)stdoutPutchar);
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#ifndef STDOUT_H
|
||||
#define STDOUT_H
|
||||
|
||||
void stdoutInit();
|
||||
|
||||
#endif
|
||||
Executable
+249
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Driver file for ESP8266 UART, works with the SDK.
|
||||
*/
|
||||
|
||||
#include "uart_driver.h"
|
||||
|
||||
#include <esp8266.h>
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "os_type.h"
|
||||
|
||||
#include "ets_sys_extra.h"
|
||||
#include "uart_register.h"
|
||||
|
||||
//========================================================
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len)
|
||||
{
|
||||
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num)
|
||||
{
|
||||
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK);
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetParity(UARTn uart_no, UartParityMode Parity_mode)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN);
|
||||
if (Parity_mode == PARITY_NONE) {
|
||||
} else {
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetBaudrate(UARTn uart_no, uint32 baud_rate)
|
||||
{
|
||||
uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
|
||||
{
|
||||
if (flow_ctrl & USART_HWFlow_RTS) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
|
||||
SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S);
|
||||
SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
|
||||
}
|
||||
|
||||
if (flow_ctrl & USART_HWFlow_CTS) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow control enabled
|
||||
{
|
||||
uint32 t_s = system_get_time();
|
||||
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)) {
|
||||
|
||||
if ((system_get_time() - t_s) > time_out_us) {
|
||||
break;
|
||||
}
|
||||
|
||||
system_soft_wdt_feed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ICACHE_FLASH_ATTR UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us)
|
||||
{
|
||||
uint32 t_start = system_get_time();
|
||||
uint8 tx_fifo_len;
|
||||
|
||||
while (1) {
|
||||
tx_fifo_len = UART_TxQueLen(uart_no);
|
||||
|
||||
// TODO If using output circbuf, check if empty
|
||||
|
||||
if (tx_fifo_len == 0) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (system_get_time() - t_start > time_out_us) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
system_soft_wdt_feed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_ResetFifo(UARTn uart_no)
|
||||
{
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask)
|
||||
{
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetIntrEna(UARTn uart_no, uint32 ena_mask)
|
||||
{
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void u0_putc_crlf(char c)
|
||||
{
|
||||
UART_WriteCharCRLF(UART0, (u8)c, UART_TIMEOUT_US);
|
||||
}
|
||||
|
||||
|
||||
LOCAL void u1_putc_crlf(char c)
|
||||
{
|
||||
UART_WriteCharCRLF(UART1, (u8)c, UART_TIMEOUT_US);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_SetPrintPort(UARTn uart_no)
|
||||
{
|
||||
if (uart_no == UART0) {
|
||||
os_install_putc1((void *)u0_putc_crlf);
|
||||
} else {
|
||||
os_install_putc1((void *)u1_putc_crlf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -------------- Custom UART functions -------------------------
|
||||
|
||||
// !!! write handlers are not ICACHE_FLASH_ATTR -> can be used in IRQ !!!
|
||||
|
||||
/**
|
||||
* @brief Write a char to UART.
|
||||
* @param uart_no
|
||||
* @param c
|
||||
* @param timeout_us - how long to max wait for space in FIFO.
|
||||
* @return write success
|
||||
*/
|
||||
STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us)
|
||||
{
|
||||
if (timeout_us == 0) {
|
||||
timeout_us = UART_TIMEOUT_US;
|
||||
}
|
||||
|
||||
|
||||
uint32 t_s = system_get_time();
|
||||
|
||||
while ((system_get_time() - t_s) < timeout_us) {
|
||||
uint8 fifo_cnt = UART_TxQueLen(uart_no);
|
||||
|
||||
if (fifo_cnt < UART_TX_FULL_THRESH_VAL) {
|
||||
WRITE_PERI_REG(UART_FIFO(uart_no), c);
|
||||
return OK;
|
||||
}
|
||||
|
||||
system_soft_wdt_feed();
|
||||
}
|
||||
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write a char to UART, translating LF to CRLF and discarding CR.
|
||||
* @param uart_no
|
||||
* @param c
|
||||
* @param timeout_us - how long to max wait for space in FIFO.
|
||||
* @return write success
|
||||
*/
|
||||
STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us)
|
||||
{
|
||||
STATUS st;
|
||||
|
||||
if (c == '\r') {
|
||||
return OK;
|
||||
} else if (c == '\n') {
|
||||
|
||||
st = UART_WriteChar(uart_no, '\r', timeout_us);
|
||||
if (st != OK) return st;
|
||||
|
||||
st = UART_WriteChar(uart_no, '\n', timeout_us);
|
||||
return st;
|
||||
|
||||
} else {
|
||||
return UART_WriteChar(uart_no, c, timeout_us);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a string to UART.
|
||||
* @param uart_no
|
||||
* @param str
|
||||
* @param timeout_us - how long to max wait for space in FIFO.
|
||||
* @return write success
|
||||
*/
|
||||
STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us)
|
||||
{
|
||||
while (*str) {
|
||||
STATUS suc = UART_WriteChar(uart_no, (u8) * str++, timeout_us);
|
||||
if (suc != OK) return suc;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Send a buffer
|
||||
* @param uart_no
|
||||
* @param buffer - buffer to send
|
||||
* @param len - buffer size
|
||||
* @param timeout_us - how long to max wait for space in FIFO.
|
||||
* @return write success
|
||||
*/
|
||||
STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
STATUS suc = UART_WriteChar(uart_no, (u8) * buffer++, timeout_us);
|
||||
if (suc != OK) return suc;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
Executable
+201
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* Low level UART peripheral support functions
|
||||
*/
|
||||
|
||||
/*
|
||||
* File : uart.h
|
||||
* Copyright (C) 2013 - 2016, Espressif Systems
|
||||
* Copyright (C) 2016, Ondřej Hruška (cleaning, modif.)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 3 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef UART_APP_H
|
||||
#define UART_APP_H
|
||||
|
||||
#include "uart_register.h"
|
||||
|
||||
#include "eagle_soc.h"
|
||||
#include "c_types.h"
|
||||
|
||||
|
||||
// ===========
|
||||
|
||||
// timeout for sending / receiving a char (default)
|
||||
#define UART_TIMEOUT_US 5000
|
||||
|
||||
#define UART_TX_FULL_THRESH_VAL (UART_FIFO_LEN - 2) // if more than this many bytes in queue, don't write more
|
||||
#define UART_TX_EMPTY_THRESH_VAL 16
|
||||
|
||||
// ===========
|
||||
|
||||
|
||||
typedef enum {
|
||||
UART0 = 0,
|
||||
UART1 = 1
|
||||
} UARTn;
|
||||
|
||||
|
||||
typedef enum {
|
||||
FIVE_BITS = 0x0,
|
||||
SIX_BITS = 0x1,
|
||||
SEVEN_BITS = 0x2,
|
||||
EIGHT_BITS = 0x3
|
||||
} UartBitsNum4Char;
|
||||
|
||||
|
||||
typedef enum {
|
||||
ONE_STOP_BIT = 0x1,
|
||||
ONE_HALF_STOP_BIT = 0x2,
|
||||
TWO_STOP_BIT = 0x3
|
||||
} UartStopBitsNum;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PARITY_NONE = 0x2,
|
||||
PARITY_ODD = 1,
|
||||
PARITY_EVEN = 0
|
||||
} UartParityMode;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PARITY_DIS = 0,
|
||||
PARITY_EN = 1
|
||||
} UartExistParity;
|
||||
|
||||
|
||||
typedef enum {
|
||||
UART_None_Inverse = 0x0,
|
||||
UART_Rxd_Inverse = UART_RXD_INV,
|
||||
UART_CTS_Inverse = UART_CTS_INV,
|
||||
UART_Txd_Inverse = UART_TXD_INV,
|
||||
UART_RTS_Inverse = UART_RTS_INV,
|
||||
} UART_LineLevelInverse;
|
||||
|
||||
|
||||
typedef enum {
|
||||
BIT_RATE_300 = 300,
|
||||
BIT_RATE_600 = 600,
|
||||
BIT_RATE_1200 = 1200,
|
||||
BIT_RATE_2400 = 2400,
|
||||
BIT_RATE_4800 = 4800,
|
||||
BIT_RATE_9600 = 9600,
|
||||
BIT_RATE_19200 = 19200,
|
||||
BIT_RATE_38400 = 38400,
|
||||
BIT_RATE_57600 = 57600,
|
||||
BIT_RATE_74880 = 74880,
|
||||
BIT_RATE_115200 = 115200,
|
||||
BIT_RATE_230400 = 230400,
|
||||
BIT_RATE_460800 = 460800,
|
||||
BIT_RATE_921600 = 921600,
|
||||
BIT_RATE_1843200 = 1843200,
|
||||
BIT_RATE_3686400 = 3686400,
|
||||
} UartBautRate;
|
||||
|
||||
|
||||
typedef enum {
|
||||
NONE_CTRL,
|
||||
HARDWARE_CTRL,
|
||||
XON_XOFF_CTRL
|
||||
} UartFlowCtrl;
|
||||
|
||||
|
||||
typedef enum {
|
||||
USART_HWFlow_None = 0x0,
|
||||
USART_HWFlow_RTS = 0x1,
|
||||
USART_HWFlow_CTS = 0x2,
|
||||
USART_HWFlow_CTS_RTS = 0x3
|
||||
} UART_HwFlowCtrl;
|
||||
|
||||
|
||||
typedef enum {
|
||||
EMPTY,
|
||||
UNDER_WRITE,
|
||||
WRITE_OVER
|
||||
} RcvMsgBuffState;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32 RcvBuffSize;
|
||||
uint8 *pRcvMsgBuff;
|
||||
uint8 *pWritePos;
|
||||
uint8 *pReadPos;
|
||||
uint8 TrigLvl; //JLU: may need to pad
|
||||
RcvMsgBuffState BuffState;
|
||||
} RcvMsgBuff;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32 TrxBuffSize;
|
||||
uint8 *pTrxBuff;
|
||||
} TrxMsgBuff;
|
||||
|
||||
|
||||
typedef enum {
|
||||
BAUD_RATE_DET,
|
||||
WAIT_SYNC_FRM,
|
||||
SRCH_MSG_HEAD,
|
||||
RCV_MSG_BODY,
|
||||
RCV_ESC_CHAR,
|
||||
} RcvMsgState;
|
||||
|
||||
|
||||
typedef struct {
|
||||
UartBautRate baut_rate;
|
||||
UartBitsNum4Char data_bits;
|
||||
UartExistParity exist_parity;
|
||||
UartParityMode parity;
|
||||
UartStopBitsNum stop_bits;
|
||||
UartFlowCtrl flow_ctrl;
|
||||
RcvMsgBuff rcv_buff;
|
||||
TrxMsgBuff trx_buff;
|
||||
RcvMsgState rcv_state;
|
||||
int received;
|
||||
int buff_uart_no; //indicate which uart use tx/rx buffer
|
||||
} UartDevice;
|
||||
|
||||
// UartDev is defined and initialized in rom code.
|
||||
extern UartDevice UartDev;
|
||||
|
||||
|
||||
//==============================================
|
||||
|
||||
// FIFO used count
|
||||
#define UART_TxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT)
|
||||
#define UART_RxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
|
||||
|
||||
STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us);
|
||||
STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us);
|
||||
STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us);
|
||||
STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us);
|
||||
|
||||
//==============================================
|
||||
|
||||
void UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len);
|
||||
void UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num);
|
||||
void UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask);
|
||||
void UART_SetParity(UARTn uart_no, UartParityMode Parity_mode);
|
||||
void UART_SetBaudrate(UARTn uart_no, uint32 baud_rate);
|
||||
void UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh);
|
||||
void UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us); //do not use if tx flow control enabled
|
||||
void UART_ResetFifo(UARTn uart_no);
|
||||
void UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask);
|
||||
void UART_SetIntrEna(UARTn uart_no, uint32 ena_mask);
|
||||
void UART_SetPrintPort(UARTn uart_no);
|
||||
bool UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us);
|
||||
|
||||
//==============================================
|
||||
|
||||
#endif
|
||||
|
||||
Executable
+185
@@ -0,0 +1,185 @@
|
||||
//Stupid bit of code that does the bare minimum to make os_printf work.
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* Jeroen Domburg <jeroen@spritesmods.com> wrote this file. As long as you retain
|
||||
* this notice you can do whatever you want with this stuff. If we meet some day,
|
||||
* and you think this stuff is worth it, you can buy me a beer in return.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <esp8266.h>
|
||||
#include "uart_driver.h"
|
||||
#include "uart_handler.h"
|
||||
|
||||
// messy irq/task based UART handling below
|
||||
|
||||
static void uart0_rx_intr_handler(void *para);
|
||||
static void uart_recvTask(os_event_t *events);
|
||||
|
||||
#define uart_recvTaskPrio 1
|
||||
#define uart_recvTaskQueueLen 10
|
||||
static os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
|
||||
|
||||
/** Clear the fifos */
|
||||
void ICACHE_FLASH_ATTR clear_rxtx(int uart_no)
|
||||
{
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Configure UART 115200-8-N-1
|
||||
* @param uart_no
|
||||
*/
|
||||
static void ICACHE_FLASH_ATTR my_uart_init(UARTn uart_no, uint32 baud)
|
||||
{
|
||||
UART_SetParity(uart_no, PARITY_NONE);
|
||||
UART_SetStopBits(uart_no, ONE_STOP_BIT);
|
||||
UART_SetWordLength(uart_no, EIGHT_BITS);
|
||||
UART_SetBaudrate(uart_no, baud);
|
||||
UART_ResetFifo(uart_no);
|
||||
}
|
||||
|
||||
|
||||
/** Configure basic UART func and pins */
|
||||
void ICACHE_FLASH_ATTR UART_Init(uint32_t baud0, uint32_t baud1)
|
||||
{
|
||||
// U0TXD
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
|
||||
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
|
||||
|
||||
// U0RXD
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
|
||||
|
||||
// U1TXD (GPIO2)
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
|
||||
|
||||
// Configure the UART peripherals
|
||||
my_uart_init(UART0, baud0); // main
|
||||
my_uart_init(UART1, baud1); // debug (output only)
|
||||
}
|
||||
|
||||
/** Configure Rx on UART0 */
|
||||
void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void)
|
||||
{
|
||||
// Start the Rx reading task
|
||||
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen);
|
||||
// set handler
|
||||
ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
|
||||
|
||||
// fifo threshold config
|
||||
uint32_t conf = ((100 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
|
||||
conf |= ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
|
||||
// timeout config
|
||||
conf |= ((0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
|
||||
conf |= UART_RX_TOUT_EN; // enable timeout
|
||||
WRITE_PERI_REG(UART_CONF1(UART0), conf);
|
||||
|
||||
// enable TOUT and ERR irqs
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA);
|
||||
/* clear interrupt flags */
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), 0xffff);
|
||||
/* enable RX interrupts */
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_OVF_INT_ENA);
|
||||
|
||||
// Enable IRQ in Extensa
|
||||
ETS_UART_INTR_ENABLE();
|
||||
}
|
||||
|
||||
|
||||
// ---- async receive stuff ----
|
||||
|
||||
|
||||
void uart_rx_intr_disable(uint8 uart_no)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
|
||||
}
|
||||
|
||||
|
||||
void uart_rx_intr_enable(uint8 uart_no)
|
||||
{
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief get number of bytes in UART tx fifo
|
||||
* @param UART number
|
||||
*/
|
||||
#define UART_GetRxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR UART_PollRx(void)
|
||||
{
|
||||
uint8 fifo_len = UART_GetRxFifoCount(UART0);
|
||||
|
||||
for (uint8 idx = 0; idx < fifo_len; idx++) {
|
||||
uint8 d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
|
||||
UART_HandleRxByte(d_tmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events)
|
||||
{
|
||||
if (events->sig == 0) {
|
||||
UART_PollRx();
|
||||
|
||||
// clear irq flags
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
|
||||
// enable rx irq again
|
||||
uart_rx_intr_enable(UART0);
|
||||
} else if (events->sig == 1) {
|
||||
// ???
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart0_rx_intr_handler
|
||||
* Description : Internal used function
|
||||
* UART0 interrupt handler, add self handle code inside
|
||||
* Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
static void
|
||||
uart0_rx_intr_handler(void *para)
|
||||
{
|
||||
(void)para;
|
||||
|
||||
uint32_t status_reg = READ_PERI_REG(UART_INT_ST(UART0));
|
||||
|
||||
if (status_reg & UART_FRM_ERR_INT_ST) {
|
||||
// Framing Error
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_FRM_ERR_INT_CLR);
|
||||
}
|
||||
|
||||
if (status_reg & UART_RXFIFO_FULL_INT_ST) {
|
||||
// RX fifo full
|
||||
uart_rx_intr_disable(UART0);
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
|
||||
|
||||
// run handler
|
||||
system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
|
||||
}
|
||||
|
||||
if (status_reg & UART_RXFIFO_TOUT_INT_ST) {
|
||||
// Fifo timeout
|
||||
uart_rx_intr_disable(UART0);
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
|
||||
|
||||
// run handler
|
||||
system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
|
||||
}
|
||||
|
||||
if (status_reg & UART_TXFIFO_EMPTY_INT_ST) {
|
||||
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||
}
|
||||
|
||||
if (status_reg & UART_RXFIFO_OVF_INT_ST) {
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_OVF_INT_CLR);
|
||||
}
|
||||
}
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* UART init & async rx module.
|
||||
*
|
||||
* Call UART_Init(), UART_SetupAsyncReceiver() and
|
||||
* define UART_HandleRxByte() somewhere in application code.
|
||||
*
|
||||
* Call UART_PollRx() to allow rx in a blocking handler.
|
||||
*/
|
||||
|
||||
#ifndef UART_HANDLER_H
|
||||
#define UART_HANDLER_H
|
||||
|
||||
#include <esp8266.h>
|
||||
|
||||
/** Configure basic UART func and pins */
|
||||
void UART_Init(uint32_t baud0, uint32_t baud1);
|
||||
|
||||
/** Configure Rx on UART0 */
|
||||
void UART_SetupAsyncReceiver(void);
|
||||
|
||||
/** User must provide this func for handling received bytes */
|
||||
extern void UART_HandleRxByte(char c);
|
||||
|
||||
/** poll uart while waiting for something */
|
||||
void UART_PollRx(void);
|
||||
|
||||
#endif
|
||||
+47
-113
@@ -7,84 +7,26 @@
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
This is example code for the esphttpd library. It's a small-ish demo showing off
|
||||
the server, including WiFi connection management capabilities, some IO and
|
||||
some pictures of cats.
|
||||
/**
|
||||
* This is the ESP8266 Remote Terminal project main file.
|
||||
*/
|
||||
|
||||
#include <esp8266.h>
|
||||
#include "httpd.h"
|
||||
#include <httpdespfs.h>
|
||||
#include <cgiwebsocket.h>
|
||||
#include <captdns.h>
|
||||
#include <espfs.h>
|
||||
#include <webpages-espfs.h>
|
||||
#include "serial.h"
|
||||
#include "io.h"
|
||||
#include "httpdespfs.h"
|
||||
#include "cgi.h"
|
||||
#include "cgiwifi.h"
|
||||
#include "cgiflash.h"
|
||||
#include "stdout.h"
|
||||
#include "auth.h"
|
||||
#include "espfs.h"
|
||||
#include "captdns.h"
|
||||
#include "webpages-espfs.h"
|
||||
#include "cgiwebsocket.h"
|
||||
#include "cgi-test.h"
|
||||
|
||||
//The example can print out the heap use every 3 seconds. You can use this to catch memory leaks.
|
||||
//#define SHOW_HEAP_USE
|
||||
#define FIRMWARE_VERSION "0.1"
|
||||
|
||||
//Function that tells the authentication system what users/passwords live on the system.
|
||||
//This is disabled in the default build; if you want to try it, enable the authBasic line in
|
||||
//the builtInUrls below.
|
||||
int myPassFn(HttpdConnData *connData, int no, char *user, int userLen, char *pass, int passLen) {
|
||||
if (no==0) {
|
||||
os_strcpy(user, "admin");
|
||||
os_strcpy(pass, "s3cr3t");
|
||||
return 1;
|
||||
//Add more users this way. Check against incrementing no for each user added.
|
||||
// } else if (no==1) {
|
||||
// os_strcpy(user, "user1");
|
||||
// os_strcpy(pass, "something");
|
||||
// return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#define SHOW_HEAP_USE 1
|
||||
|
||||
static ETSTimer websockTimer;
|
||||
|
||||
//Broadcast the uptime in seconds every second over connected websockets
|
||||
static void ICACHE_FLASH_ATTR websockTimerCb(void *arg) {
|
||||
static int ctr=0;
|
||||
char buff[128];
|
||||
ctr++;
|
||||
os_sprintf(buff, "Up for %d minutes %d seconds!\n", ctr/60, ctr%60);
|
||||
cgiWebsockBroadcast("/websocket/ws.cgi", buff, os_strlen(buff), WEBSOCK_FLAG_NONE);
|
||||
}
|
||||
|
||||
//On reception of a message, send "You sent: " plus whatever the other side sent
|
||||
void myWebsocketRecv(Websock *ws, char *data, int len, int flags) {
|
||||
int i;
|
||||
char buff[128];
|
||||
os_sprintf(buff, "You sent: ");
|
||||
for (i=0; i<len; i++) buff[i+10]=data[i];
|
||||
buff[i+10]=0;
|
||||
cgiWebsocketSend(ws, buff, os_strlen(buff), WEBSOCK_FLAG_NONE);
|
||||
}
|
||||
|
||||
//Websocket connected. Install reception handler and send welcome message.
|
||||
void myWebsocketConnect(Websock *ws) {
|
||||
ws->recvCb=myWebsocketRecv;
|
||||
cgiWebsocketSend(ws, "Hi, Websocket!", 14, WEBSOCK_FLAG_NONE);
|
||||
}
|
||||
|
||||
//On reception of a message, echo it back verbatim
|
||||
void myEchoWebsocketRecv(Websock *ws, char *data, int len, int flags) {
|
||||
os_printf("EchoWs: echo, len=%d\n", len);
|
||||
cgiWebsocketSend(ws, data, len, flags);
|
||||
}
|
||||
|
||||
//Echo websocket connected. Install reception handler.
|
||||
void myEchoWebsocketConnect(Websock *ws) {
|
||||
os_printf("EchoWs: connect\n");
|
||||
ws->recvCb=myEchoWebsocketRecv;
|
||||
// NOOP
|
||||
}
|
||||
|
||||
|
||||
@@ -108,47 +50,14 @@ CgiUploadFlashDef uploadParams={
|
||||
#define INCLUDE_FLASH_FNS
|
||||
#endif
|
||||
|
||||
/*
|
||||
This is the main url->function dispatching data struct.
|
||||
In short, it's a struct with various URLs plus their handlers. The handlers can
|
||||
be 'standard' CGI functions you wrote, or 'special' CGIs requiring an argument.
|
||||
They can also be auth-functions. An asterisk will match any url starting with
|
||||
everything before the asterisks; "*" matches everything. The list will be
|
||||
handled top-down, so make sure to put more specific rules above the more
|
||||
general ones. Authorization things (like authBasic) act as a 'barrier' and
|
||||
should be placed above the URLs they protect.
|
||||
*/
|
||||
/** Routes */
|
||||
HttpdBuiltInUrl builtInUrls[]={
|
||||
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"), // redirect func for the captive portal
|
||||
ROUTE_REDIRECT("/", "/index.tpl"),
|
||||
ROUTE_TPL("/led.tpl", tplLed),
|
||||
ROUTE_TPL("/index.tpl", tplCounter),
|
||||
ROUTE_CGI("/led.cgi", cgiLed),
|
||||
#ifdef INCLUDE_FLASH_FNS
|
||||
ROUTE_CGI_ARG("/flash/next", cgiGetFirmwareNext, &uploadParams),
|
||||
ROUTE_CGI_ARG("/flash/upload", cgiUploadFirmware, &uploadParams),
|
||||
#endif
|
||||
ROUTE_CGI("/flash/reboot", cgiRebootFirmware),
|
||||
// redirect func for the captive portal
|
||||
ROUTE_CGI_ARG("*", cgiRedirectApClientToHostname, "esp8266.nonet"),
|
||||
|
||||
//Routines to make the /wifi URL and everything beneath it work.
|
||||
ROUTE_WS("/ws/update.cgi", myWebsocketConnect),
|
||||
|
||||
//Enable the line below to protect the WiFi configuration with an username/password combo.
|
||||
// ROUTE_AUTH("/wifi/*", myPassFn),
|
||||
|
||||
ROUTE_REDIRECT("/wifi", "/wifi/wifi.tpl"),
|
||||
ROUTE_REDIRECT("/wifi/", "/wifi/wifi.tpl"),
|
||||
ROUTE_CGI("/wifi/wifiscan.cgi", cgiWiFiScan),
|
||||
ROUTE_TPL("/wifi/wifi.tpl", tplWlan),
|
||||
ROUTE_CGI("/wifi/connect.cgi", cgiWiFiConnect),
|
||||
ROUTE_CGI("/wifi/connstatus.cgi", cgiWiFiConnStatus),
|
||||
ROUTE_CGI("/wifi/setmode.cgi", cgiWiFiSetMode),
|
||||
|
||||
ROUTE_WS("/websocket/ws.cgi", myWebsocketConnect),
|
||||
ROUTE_WS("/websocket/echo.cgi", myEchoWebsocketConnect),
|
||||
|
||||
ROUTE_REDIRECT("/test", "/test/index.html"),
|
||||
ROUTE_REDIRECT("/test/", "/test/index.html"),
|
||||
ROUTE_CGI("/test/test.cgi", cgiTestbed),
|
||||
// TODO add funcs for WiFi management (when web UI is added)
|
||||
|
||||
ROUTE_FILESYSTEM(),
|
||||
ROUTE_END(),
|
||||
@@ -159,15 +68,28 @@ HttpdBuiltInUrl builtInUrls[]={
|
||||
static ETSTimer prHeapTimer;
|
||||
|
||||
static void ICACHE_FLASH_ATTR prHeapTimerCb(void *arg) {
|
||||
static int led = 0;
|
||||
os_printf("Heap: %ld\n", (unsigned long)system_get_free_heap_size());
|
||||
|
||||
cgiWebsockBroadcast("/ws/update.cgi", "HELLO", 5, WEBSOCK_FLAG_NONE);
|
||||
|
||||
ioLed(led);
|
||||
led = !led;
|
||||
}
|
||||
#endif
|
||||
|
||||
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
|
||||
void user_init(void) {
|
||||
stdoutInit();
|
||||
ioInit();
|
||||
serialInit();
|
||||
|
||||
banner("ESP8266 Remote Terminal");
|
||||
banner_info("Version "FIRMWARE_VERSION", built "__DATE__" at "__TIME__);
|
||||
dbg("!!! TODO (c) and GitHub link here !!!");
|
||||
|
||||
//stdoutInit();
|
||||
|
||||
captdnsInit();
|
||||
ioInit();
|
||||
|
||||
// 0x40200000 is the base address for spi flash memory mapping, ESPFS_POS is the position
|
||||
// where image is written in flash that is defined in Makefile.
|
||||
@@ -176,18 +98,30 @@ void user_init(void) {
|
||||
#else
|
||||
espFsInit((void*)(webpages_espfs_start));
|
||||
#endif
|
||||
|
||||
httpdInit(builtInUrls, 80);
|
||||
|
||||
#ifdef SHOW_HEAP_USE
|
||||
os_timer_disarm(&prHeapTimer);
|
||||
os_timer_setfn(&prHeapTimer, prHeapTimerCb, NULL);
|
||||
os_timer_arm(&prHeapTimer, 3000, 1);
|
||||
#endif
|
||||
os_timer_disarm(&websockTimer);
|
||||
os_timer_setfn(&websockTimer, websockTimerCb, NULL);
|
||||
os_timer_arm(&websockTimer, 1000, 1);
|
||||
os_printf("\nReady\n");
|
||||
|
||||
info("System ready!");
|
||||
}
|
||||
|
||||
// ---- unused funcs removed from sdk to save space ---
|
||||
|
||||
void user_rf_pre_init() {
|
||||
//Not needed, but some SDK versions want this defined.
|
||||
}
|
||||
|
||||
// вызывается из phy_chip_v6.o
|
||||
void ICACHE_FLASH_ATTR chip_v6_set_sense(void) {
|
||||
// ret.n
|
||||
}
|
||||
|
||||
// вызывается из phy_chip_v6.o
|
||||
int ICACHE_FLASH_ATTR chip_v6_unset_chanfreq(void) {
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user