You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
esp-link/serial/console.c

153 lines
3.9 KiB

#include <esp8266.h>
#include "uart.h"
#include "cgi.h"
#include "uart.h"
#include "serbridge.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);
}
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
}
int ICACHE_FLASH_ATTR
ajaxConsoleReset(HttpdConnData *connData) {
jsonHeader(connData, 200);
serbridgeReset();
return HTTPD_CGI_DONE;
}
int ICACHE_FLASH_ATTR
ajaxConsoleBaud(HttpdConnData *connData) {
char buff[2048];
int len;
len = httpdFindArg(connData->getArgs, "rate", buff, sizeof(buff));
if (len > 0) {
int rate = atoi(buff);
if (rate >= 9600 && rate <= 1000000) {
jsonHeader(connData, 200);
uart0_baud(rate);
return HTTPD_CGI_DONE;
}
}
jsonHeader(connData, 400);
return HTTPD_CGI_DONE;
}
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
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) {
*/
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;
}