switched uC console to ajax with auto-refresh

pull/10/head
Thorsten von Eicken 10 years ago
parent 22815878f5
commit c2e56bed4a
  1. 85
      html/console.tpl
  2. 4
      html/style.css
  3. 81
      serial/console.c
  4. 1
      serial/console.h
  5. 72
      user/console.c
  6. 1
      user/user_main.c

@ -6,14 +6,89 @@
</div> </div>
<div class="content"> <div class="content">
<p>The Microcontroller console shows the last 1024 characters received from UART0, to which <p>The Microcontroller console shows the last 1024 characters
a microcontroller is typically attached.</p> received from UART0, to which a microcontroller is typically attached.</p>
<pre class="console"> <p>
%console% <a class="pure-button button-primary" href="#">Reset µC</a>
</pre> &nbsp;Baud:
<a href="#" class="pure-button">57600</a>
<a href="#" class="pure-button">115200</a>
<a href="#" class="pure-button">230400</a>
<a href="#" class="pure-button">460800</a>
</p>
<pre class="console" id="console"></pre>
</div> </div>
</div> </div>
</div> </div>
<script src="ui.js"></script> <script src="ui.js"></script>
<script type="text/javascript">
function loadJSON(url, okCb, errCb) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = handleEv;
function handleEv() {
try {
//console.log("handleEv", xhr.readyState);
if(xhr.readyState < 4) {
return;
}
if(xhr.status !== 200) {
//console.log("handleEv error cb");
errCb(xhr);
return;
}
// all is well
if(xhr.readyState === 4) {
//console.log("handleEv success cb");
okCb(xhr, JSON.parse(xhr.responseText));
}
} catch(e) {return;}
}
xhr.open('GET', url, true);
xhr.send('');
}
function fetchText(delay) {
el = document.getElementById("console");
if (el.textEnd == undefined) {
el.textEnd = 0;
el.innerHTML = "";
}
window.setTimeout(function() {
loadJSON("/console?start=" + el.textEnd, updateText, retryLoad);
}, delay);
}
function updateText(xhr, resp) {
el = document.getElementById("console");
delay = 3000;
if (el == null || resp == null) {
//console.log("updateText got null response? xhr=", xhr);
} else if (resp.len == 0) {
//console.log("updateText got no new text");
} else {
console.log("updateText got", resp.len, "chars at", resp.start);
if (resp.start > el.textEnd) {
el.innerHTML = el.innerHTML.concat("\r\n<missing lines\r\n");
}
el.innerHTML = el.innerHTML.concat(resp.text);
el.textEnd = resp.start + resp.len;
delay = 500;
}
fetchText(delay);
}
function retryLoad(xhr) {
fetchText(1000);
}
window.onload = function() {
fetchText(100);
}
</script>
</body></html> </body></html>

@ -68,6 +68,10 @@ body {
color: #888; color: #888;
} }
.button-primary {
background-color: #99f;
}
/* Text console */ /* Text console */
pre.console { pre.console {
background-color: #663300; background-color: #663300;

@ -6,27 +6,34 @@
// Microcontroller console capturing the last 1024 characters received on the uart so // Microcontroller console capturing the last 1024 characters received on the uart so
// they can be shown on a web page // they can be shown on a web page
// Buffer to hold concole contents.
// Invariants:
// - console_rd==console_wr <=> buffer empty
// - *console_rd == next char to read
// - *console_wr == next char to write
// - 0 <= console_xx < BUF_MAX
// - (console_wr+1)%BUF_MAX) == console_rd <=> buffer full
#define BUF_MAX (1024) #define BUF_MAX (1024)
static char console_buf[BUF_MAX]; static char console_buf[BUF_MAX];
static int console_wr, console_rd; static int console_wr, console_rd;
static int console_pos; // offset since reset of console_rd position static int console_pos; // offset since reset of buffer
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
console_write(char c) { console_write(char c) {
int wr = (console_wr+1)%BUF_MAX; console_buf[console_wr] = c;
if (wr == console_rd) { console_wr = (console_wr+1) % BUF_MAX;
if (console_wr == console_rd) {
// full, we write anyway and loose the oldest char
console_rd = (console_rd+1) % BUF_MAX; // full, eat first char console_rd = (console_rd+1) % BUF_MAX; // full, eat first char
console_pos++; console_pos++;
} }
console_buf[console_wr] = c;
console_wr = wr;
} }
// return previous character in console, 0 if at start // return previous character in console, 0 if at start
static char ICACHE_FLASH_ATTR static char ICACHE_FLASH_ATTR
console_prev(void) { console_prev(void) {
if (console_wr == console_rd) return 0; if (console_wr == console_rd) return 0;
return console_buf[(console_wr+1+BUF_MAX)%BUF_MAX]; return console_buf[(console_wr-1+BUF_MAX)%BUF_MAX];
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
@ -35,22 +42,76 @@ console_write_char(char c) {
console_write(c); console_write(c);
} }
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
}
int ICACHE_FLASH_ATTR
ajaxConsole(HttpdConnData *connData) {
char buff[2048];
int len; // length of text in buff
int console_len = (console_wr+BUF_MAX-console_rd) % BUF_MAX; // num chars in console_buf
int start = 0; // offset onto console_wr to start sending out chars
jsonHeader(connData, 200);
// figure out where to start in buffer based on URI param
len = httpdFindArg(connData->getArgs, "start", buff, sizeof(buff));
if (len > 0) {
start = atoi(buff);
if (start < console_pos) {
start = 0;
} else if (start >= console_pos+console_len) {
start = console_len;
} else {
start = start - console_pos;
}
}
// start outputting
len = os_sprintf(buff, "{\"len\":%d, \"start\":%d, \"text\": \"",
console_len-start, console_pos+start);
int rd = (console_rd+start) % BUF_MAX;
while (len < 2040 && rd != console_wr) {
uint8_t c = console_buf[rd];
if (c == '\\' || c == '"') {
buff[len++] = '\\';
buff[len++] = c;
} else if (c < ' ') {
len += os_sprintf(buff+len, "\\u%04x", c);
} else {
buff[len++] = c;
}
rd = (rd + 1) % BUF_MAX;
}
os_strcpy(buff+len, "\"}"); len+=2;
httpdSend(connData, buff, len);
return HTTPD_CGI_DONE;
}
//===== Display a web page with the console //===== Display a web page with the console
int ICACHE_FLASH_ATTR int ICACHE_FLASH_ATTR
tplConsole(HttpdConnData *connData, char *token, void **arg) { tplConsole(HttpdConnData *connData, char *token, void **arg) {
if (token==NULL) return HTTPD_CGI_DONE; if (token==NULL) return HTTPD_CGI_DONE;
char buff[256];
/*
if (os_strcmp(token, "console") == 0) { if (os_strcmp(token, "console") == 0) {
if (console_wr > console_rd) { if (console_wr > console_rd) {
httpdSend(connData, console_buf+console_rd, console_wr-console_rd); httpdSend(connData, console_buf+console_rd, console_wr-console_rd);
} else if (console_rd != console_wr) { } else if (console_rd != console_wr) {
httpdSend(connData, console_buf+console_rd, BUF_MAX-console_rd); httpdSend(connData, console_buf+console_rd, BUF_MAX-console_rd);
httpdSend(connData, console_buf, console_wr); httpdSend(connData, console_buf, console_wr);
} else {
httpdSend(connData, "<buffer empty>", -1);
} }
} else if (os_strcmp(token, "topnav")==0) { } else if (os_strcmp(token, "head")==0) {
printNav(buff); */
httpdSend(connData, buff, -1); if (os_strcmp(token, "head")==0) {
printHead(connData);
} else { } else {
httpdSend(connData, "Unknown\n", -1); httpdSend(connData, "Unknown\n", -1);
} }

@ -5,6 +5,7 @@
void consoleInit(void); void consoleInit(void);
void ICACHE_FLASH_ATTR console_write_char(char c); void ICACHE_FLASH_ATTR console_write_char(char c);
int ajaxConsole(HttpdConnData *connData);
int tplConsole(HttpdConnData *connData, char *token, void **arg); int tplConsole(HttpdConnData *connData, char *token, void **arg);
#endif #endif

@ -1,72 +0,0 @@
#include <esp8266.h>
#include "uart.h"
#include "cgi.h"
#include "console.h"
// Microcontroller console capturing the last 1024 characters received on the uart so
// they can be shown on a web page
// Buffer to hold concole contents.
// Invariants:
// - console_rd==console_wr <=> buffer empty
// - *console_rd == next char to read
// - *console_wr == next char to write
// - 0 <= console_xx < BUF_MAX
// - (console_wr+1)%BUF_MAX) == console_rd <=> buffer full
#define BUF_MAX (1024)
static char console_buf[BUF_MAX];
static int console_wr, console_rd;
static int console_pos; // offset since reset of buffer
static void ICACHE_FLASH_ATTR
console_write(char c) {
console_buf[console_wr] = c;
console_wr = (console_wr+1) % BUF_MAX;
if (console_wr == console_rd) {
// full, we write anyway and loose the oldest char
console_rd = (console_rd+1) % BUF_MAX; // full, eat first char
console_pos++;
}
}
// return previous character in console, 0 if at start
static char ICACHE_FLASH_ATTR
console_prev(void) {
if (console_wr == console_rd) return 0;
return console_buf[(console_wr-1+BUF_MAX)%BUF_MAX];
}
void ICACHE_FLASH_ATTR
console_write_char(char c) {
if (c == '\n' && console_prev() != '\r') console_write('\r');
console_write(c);
}
//===== Display a web page with the console
int ICACHE_FLASH_ATTR
tplConsole(HttpdConnData *connData, char *token, void **arg) {
if (token==NULL) return HTTPD_CGI_DONE;
if (os_strcmp(token, "console") == 0) {
if (console_wr > console_rd) {
httpdSend(connData, console_buf+console_rd, console_wr-console_rd);
} else if (console_rd != console_wr) {
httpdSend(connData, console_buf+console_rd, BUF_MAX-console_rd);
httpdSend(connData, console_buf, console_wr);
} else {
httpdSend(connData, "<buffer empty>", -1);
}
} else if (os_strcmp(token, "head")==0) {
printHead(connData);
} else {
httpdSend(connData, "Unknown\n", -1);
}
return HTTPD_CGI_DONE;
}
void ICACHE_FLASH_ATTR consoleInit() {
console_wr = 0;
console_rd = 0;
}

@ -68,6 +68,7 @@ HttpdBuiltInUrl builtInUrls[]={
{"/help.tpl", cgiEspFsTemplate, tplCounter}, {"/help.tpl", cgiEspFsTemplate, tplCounter},
{"/log.tpl", cgiEspFsTemplate, tplLog}, {"/log.tpl", cgiEspFsTemplate, tplLog},
{"/console.tpl", cgiEspFsTemplate, tplConsole}, {"/console.tpl", cgiEspFsTemplate, tplConsole},
{"/console", ajaxConsole, NULL},
//Routines to make the /wifi URL and everything beneath it work. //Routines to make the /wifi URL and everything beneath it work.

Loading…
Cancel
Save