added info about the new commands to help. also e]FRa is removed bc it is no longer useful for anything

pull/111/merge
Ondřej Hruška 7 years ago
parent 3f4b8a94f1
commit 4551ad6dbe
  1. 2
      html_orig/_debug_replacements.php
  2. 40
      html_orig/js/app.js
  3. 10
      html_orig/jssrc/appcommon.js
  4. 30
      html_orig/jssrc/term.js
  5. 10
      html_orig/pages/help.php
  6. 20
      html_orig/pages/term.php
  7. 8
      user/ansi_parser_callbacks.c
  8. 61
      user/cgi_sockets.c
  9. 3
      user/cgi_sockets.h
  10. 46
      user/screen.c
  11. 12
      user/screen.h

@ -11,7 +11,7 @@ return [
'%btn1%' => '1', '%btn1%' => '1',
'%btn2%' => '2', '%btn2%' => '2',
'%btn3%' => '3', '%btn3%' => '3',
'%btn4%' => '4', '%btn4%' => '',
'%btn5%' => '5', '%btn5%' => '5',
'%screenData%' => '  HELLOx NRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //, '%screenData%' => '  HELLOx NRE3',//'\u000b\u0001\u001b\u0001\u0001\u0001\u0001\u0001\f\u0005\u0001\u0010\u0003HELLOx\u0002\u000b\u0001\u0001N\u0001RE\u00023\u0001', //,

@ -1011,10 +1011,16 @@ $._loader = function(vis) {
$('#loader').toggleClass('show', vis); $('#loader').toggleClass('show', vis);
}; };
$.ready(function() { function showPage() {
setTimeout(function() {
$('#content').addClass('load'); $('#content').addClass('load');
}
$.ready(function() {
if (window.noAutoShow !== true) {
setTimeout(function () {
showPage();
}, 1); }, 1);
}
}); });
// Generated from PHP locale file // Generated from PHP locale file
var _tr = { var _tr = {
@ -1333,8 +1339,7 @@ var Screen = (function () {
var SEQ_SET_COLOR = 1; var SEQ_SET_COLOR = 1;
var SEQ_REPEAT = 2; var SEQ_REPEAT = 2;
/** Load screen content from a binary sequence (new) */ function _load_content(str) {
function load(str) {
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell; var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell;
if (!inited) _init(); if (!inited) _init();
@ -1402,6 +1407,31 @@ var Screen = (function () {
_drawAll(); _drawAll();
} }
function _load_labels(str) {
var pieces = str.split('|');
qs('h1').textContent = pieces[0];
qsa('#buttons button').forEach(function(x, i) {
var s = pieces[i+1].trim();
x.innerHTML = s.length >0 ? e(s) : " ";
x.style.opacity = s.length > 0 ? 1 : 0.2;
});
}
/** Load screen content from a binary sequence (new) */
function load(str) {
var content = str.substr(1);
switch(str.charAt(0)) {
case 'S':
_load_content(content);
break;
case 'T':
_load_labels(content);
break;
default:
console.warn("Bad data message type, ignoring.");
}
}
return { return {
load: load, // full load (string) load: load, // full load (string)
}; };
@ -1458,6 +1488,8 @@ var Conn = (function() {
if (status !== 200) location.reload(true); if (status !== 200) location.reload(true);
console.log("Data received!"); console.log("Data received!");
Screen.load(resp); Screen.load(resp);
showPage();
}); });
} }

@ -112,8 +112,14 @@ $._loader = function(vis) {
$('#loader').toggleClass('show', vis); $('#loader').toggleClass('show', vis);
}; };
$.ready(function() { function showPage() {
setTimeout(function() {
$('#content').addClass('load'); $('#content').addClass('load');
}
$.ready(function() {
if (window.noAutoShow !== true) {
setTimeout(function () {
showPage();
}, 1); }, 1);
}
}); });

@ -147,8 +147,7 @@ var Screen = (function () {
var SEQ_SET_COLOR = 1; var SEQ_SET_COLOR = 1;
var SEQ_REPEAT = 2; var SEQ_REPEAT = 2;
/** Load screen content from a binary sequence (new) */ function _load_content(str) {
function load(str) {
var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell; var i = 0, ci = 0, j, jc, num, num2, t = ' ', fg, bg, bold, cell;
if (!inited) _init(); if (!inited) _init();
@ -216,6 +215,31 @@ var Screen = (function () {
_drawAll(); _drawAll();
} }
function _load_labels(str) {
var pieces = str.split('|');
qs('h1').textContent = pieces[0];
qsa('#buttons button').forEach(function(x, i) {
var s = pieces[i+1].trim();
x.innerHTML = s.length >0 ? e(s) : " ";
x.style.opacity = s.length > 0 ? 1 : 0.2;
});
}
/** Load screen content from a binary sequence (new) */
function load(str) {
var content = str.substr(1);
switch(str.charAt(0)) {
case 'S':
_load_content(content);
break;
case 'T':
_load_labels(content);
break;
default:
console.warn("Bad data message type, ignoring.");
}
}
return { return {
load: load, // full load (string) load: load, // full load (string)
}; };
@ -272,6 +296,8 @@ var Conn = (function() {
if (status !== 200) location.reload(true); if (status !== 200) location.reload(true);
console.log("Data received!"); console.log("Data received!");
Screen.load(resp); Screen.load(resp);
showPage();
}); });
} }

@ -338,6 +338,16 @@
<td>--</td> <td>--</td>
<td>Query device status, replies with <code>\e[0n</code> "device is OK". Can be used to check if the UART works.</td> <td>Query device status, replies with <code>\e[0n</code> "device is OK". Can be used to check if the UART works.</td>
</tr> </tr>
<tr>
<td>\e]TITLE=…\a</td>
<td>Title text</td>
<td>Set terminal title. Avoid ", ', &lt; and &gt;. This is a custom ESPTerm OSC command.</td>
</tr>
<tr>
<td>\e]BTNn=…\a</td>
<td>1-5, label</td>
<td>Set button label. Avoid ", ', &lt; and &gt;. This is a custom ESPTerm OSC command.</td>
</tr>
<tr> <tr>
<td>ASCII 24 (18h)</td> <td>ASCII 24 (18h)</td>
<td></td> <td></td>

@ -8,17 +8,17 @@
}, 2000); }, 2000);
</script> </script>
<h1>%term_title%</h1> <h1></h1>
<div id="termwrap"> <div id="termwrap">
<div id="screen" class="theme-%theme%"></div> <div id="screen" class="theme-%theme%"></div>
<div id="buttons"> <div id="buttons">
<button data-n="1" class="btn-blue">%btn1%</button><!-- <button data-n="1" class="btn-blue"></button><!--
--><button data-n="2" class="btn-blue">%btn2%</button><!-- --><button data-n="2" class="btn-blue"></button><!--
--><button data-n="3" class="btn-blue">%btn3%</button><!-- --><button data-n="3" class="btn-blue"></button><!--
--><button data-n="4" class="btn-blue">%btn4%</button><!-- --><button data-n="4" class="btn-blue"></button><!--
--><button data-n="5" class="btn-blue">%btn5%</button> --><button data-n="5" class="btn-blue"></button>
</div> </div>
</div> </div>
@ -31,10 +31,14 @@
--><a href="<?= url('about') ?>">About</a> --><a href="<?= url('about') ?>">About</a>
</nav> </nav>
<!-- this avoids having to escape quotes for JSON -->
<span class="hidden" id="initial_data">T%term_title%|%btn1%|%btn2%|%btn3%|%btn4%|%btn5%</span>
<script> <script>
// TODO cleanup
try { try {
termInit(); window.noAutoShow = true;
termInit(); // the screen will be loaded via ajax
Screen.load(qs('#initial_data').textContent);
// auto-clear the input box // auto-clear the input box
$('#softkb-input').on('input', function(e) { $('#softkb-input').on('input', function(e) {

@ -276,14 +276,14 @@ void ICACHE_FLASH_ATTR
apars_handle_OSC_SetButton(int num, const char *buffer) apars_handle_OSC_SetButton(int num, const char *buffer)
{ {
strncpy(termconf_scratch.btn[num-1], buffer, TERM_BTN_LEN); strncpy(termconf_scratch.btn[num-1], buffer, TERM_BTN_LEN);
dbg("Term set BTN%d = %s", num, buffer); info("OSC: Set BTN%d = %s", num, buffer);
// TODO notify screen_notifyChange(CHANGE_LABELS);
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
apars_handle_OSC_SetTitle(const char *buffer) apars_handle_OSC_SetTitle(const char *buffer)
{ {
strncpy(termconf_scratch.title, buffer, TERM_TITLE_LEN); strncpy(termconf_scratch.title, buffer, TERM_TITLE_LEN);
dbg("Term set TITLE = %s", buffer); info("OSC: Set TITLE = %s", buffer);
// TODO notify screen_notifyChange(CHANGE_LABELS);
} }

@ -9,9 +9,28 @@
#define SOCK_BUF_LEN 2048 #define SOCK_BUF_LEN 2048
static char sock_buff[SOCK_BUF_LEN]; static char sock_buff[SOCK_BUF_LEN];
static void notifyTimCb(void *arg) { volatile bool notify_available = true;
static ETSTimer notifyTim;
static ETSTimer notifyTim2;
// we're trying to do a kind of mutex here, without the actual primitives
// this might glitch, very rarely.
// it's recommended to put some delay between setting labels and updating the screen.
static void ICACHE_FLASH_ATTR
notifyTimCb(void *arg) {
void *data = NULL; void *data = NULL;
if (!notify_available) {
// postpone a little
os_timer_disarm(&notifyTim);
os_timer_setfn(&notifyTim, notifyTimCb, NULL);
os_timer_arm(&notifyTim, 1, 0);
return;
}
notify_available = false;
for (int i = 0; i < 20; i++) { for (int i = 0; i < 20; i++) {
httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, &data); httpd_cgi_state cont = screenSerializeToBuffer(sock_buff, SOCK_BUF_LEN, &data);
int flg = 0; int flg = 0;
@ -21,21 +40,53 @@ static void notifyTimCb(void *arg) {
if (cont == HTTPD_CGI_DONE) break; if (cont == HTTPD_CGI_DONE) break;
} }
// cleanup
screenSerializeToBuffer(NULL, SOCK_BUF_LEN, &data); screenSerializeToBuffer(NULL, SOCK_BUF_LEN, &data);
notify_available = true;
}
static void ICACHE_FLASH_ATTR
notifyLabelsTimCb(void *arg)
{
if (!notify_available) {
// postpone a little
os_timer_disarm(&notifyTim2);
os_timer_setfn(&notifyTim2, notifyLabelsTimCb, NULL);
os_timer_arm(&notifyTim2, 1, 0);
return;
}
notify_available = false;
screenSerializeLabelsToBuffer(sock_buff, SOCK_BUF_LEN);
cgiWebsockBroadcast(URL_WS_UPDATE, sock_buff, (int) strlen(sock_buff), 0);
notify_available = true;
} }
static ETSTimer notifyTim;
/** /**
* Broadcast screen state to sockets. * Broadcast screen state to sockets.
* This is a callback for the Screen module, * This is a callback for the Screen module,
* called after each visible screen modification. * called after each visible screen modification.
*/ */
void ICACHE_FLASH_ATTR screen_notifyChange(void) void ICACHE_FLASH_ATTR screen_notifyChange(ScreenNotifyChangeTopic topic)
{ {
// this is not the most ideal/cleanest implementation
// PRs are welcome for a nicer update "queue" solution
if (topic == CHANGE_LABELS) {
// separate timer from content change timer, to avoid losing that update
os_timer_disarm(&notifyTim2);
os_timer_setfn(&notifyTim2, notifyLabelsTimCb, NULL);
os_timer_arm(&notifyTim2, SCREEN_NOTIFY_DELAY_MS, 0);
}
else if (topic == CHANGE_CONTENT) {
// throttle delay
os_timer_disarm(&notifyTim); os_timer_disarm(&notifyTim);
os_timer_setfn(&notifyTim, notifyTimCb, NULL); os_timer_setfn(&notifyTim, notifyTimCb, NULL);
os_timer_arm(&notifyTim, 20, 0); os_timer_arm(&notifyTim, SCREEN_NOTIFY_DELAY_MS, 0);
}
} }
/** Socket received a message */ /** Socket received a message */
@ -45,6 +96,8 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
// Add terminator if missing (seems to randomly happen) // Add terminator if missing (seems to randomly happen)
data[len] = 0; data[len] = 0;
// TODO re-implement those, use single byte markers and B2 encoding
dbg("Sock RX str: %s, len %d", data, len); dbg("Sock RX str: %s, len %d", data, len);
if (strstarts(data, "STR:")) { if (strstarts(data, "STR:")) {

@ -3,7 +3,10 @@
#define URL_WS_UPDATE "/term/update.ws" #define URL_WS_UPDATE "/term/update.ws"
#include "screen.h"
/** Update websocket connect callback */ /** Update websocket connect callback */
void updateSockConnect(Websock *ws); void updateSockConnect(Websock *ws);
void screen_notifyChange(ScreenNotifyChangeTopic topic);
#endif //CGI_SOCKETS_H #endif //CGI_SOCKETS_H

@ -96,7 +96,7 @@ static volatile int notifyLock = 0;
#define NOTIFY_DONE() do { \ #define NOTIFY_DONE() do { \
if (notifyLock > 0) notifyLock--; \ if (notifyLock > 0) notifyLock--; \
if (notifyLock == 0) screen_notifyChange(); \ if (notifyLock == 0) screen_notifyChange(CHANGE_CONTENT); \
} while(0) } while(0)
/** /**
@ -371,8 +371,8 @@ screen_cursor_move(int dy, int dx)
cursor.x += dx; cursor.x += dx;
cursor.y += dy; cursor.y += dy;
if (cursor.x >= W) cursor.x = W - 1; if (cursor.x >= (int)W) cursor.x = W - 1;
if (cursor.x < 0) cursor.x = 0; if (cursor.x < (int)0) cursor.x = 0;
if (cursor.y < 0) { if (cursor.y < 0) {
move = -cursor.y; move = -cursor.y;
@ -674,6 +674,25 @@ encode2B(u16 number, WordB2 *stru)
stru->lsb += 1; stru->lsb += 1;
} }
/**
* buffer should be at least 64+5*10+6 long (title + buttons + 6), ie. 120
* @param buffer
* @param buf_len
*/
void ICACHE_FLASH_ATTR
screenSerializeLabelsToBuffer(char *buffer, size_t buf_len)
{
// let's just assume it's long enough - called with the huge websocket buffer
sprintf(buffer, "T%s|%s|%s|%s|%s|%s",
termconf_scratch.title,
termconf_scratch.btn[0],
termconf_scratch.btn[1],
termconf_scratch.btn[2],
termconf_scratch.btn[3],
termconf_scratch.btn[4]
);
}
/** /**
* Serialize the screen to a data buffer. May need multiple calls if the buffer is insufficient in size. * Serialize the screen to a data buffer. May need multiple calls if the buffer is insufficient in size.
* *
@ -728,7 +747,7 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
, &w5); , &w5);
// H W X Y Attribs // H W X Y Attribs
bufprint("%c%c%c%c%c%c%c%c%c%c", w1.lsb, w1.msb, w2.lsb, w2.msb, w3.lsb, w3.msb, w4.lsb, w4.msb, w5.lsb, w5.msb); bufprint("S%c%c%c%c%c%c%c%c%c%c", w1.lsb, w1.msb, w2.lsb, w2.msb, w3.lsb, w3.msb, w4.lsb, w4.msb, w5.lsb, w5.msb);
} }
int i = ss->index; int i = ss->index;
@ -749,12 +768,6 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
if (repCnt == 0) { if (repCnt == 0) {
// No repeat // No repeat
// All this crap is needed because it's JSON and also
// embedded in HTML (hence the angle brackets)
// TODO use the encoding magic correctly
if (cell0->bold != ss->lastBold || cell0->fg != ss->lastFg || cell0->bg != ss->lastBg) { if (cell0->bold != ss->lastBold || cell0->fg != ss->lastFg || cell0->bg != ss->lastBg) {
encode2B((u16) ( encode2B((u16) (
cell0->fg | cell0->fg |
@ -771,19 +784,6 @@ screenSerializeToBuffer(char *buffer, size_t buf_len, void **data)
bufprint("%c", c); bufprint("%c", c);
} }
// TODO do correctly JSON encoding
//
// char c = cell0->c;
// if (c == '"' || c == '\\') {
// bufprint("\\%c", c);
// }
// else if (c == '<' || c == '>' || c == '\'' || c == '/' || c == '&') {
// bufprint("\\u00%02X", (int)c);
// }
// else {
// bufprint("%c", c);
// }
ss->lastFg = cell0->fg; ss->lastFg = cell0->fg;
ss->lastBg = cell0->bg; ss->lastBg = cell0->bg;
ss->lastBold = cell0->bold; ss->lastBold = cell0->bold;

@ -41,6 +41,13 @@
#define TERM_BTN_LEN 10 #define TERM_BTN_LEN 10
#define TERM_TITLE_LEN 64 #define TERM_TITLE_LEN 64
typedef enum {
CHANGE_CONTENT,
CHANGE_LABELS,
} ScreenNotifyChangeTopic;
#define SCREEN_NOTIFY_DELAY_MS 20
typedef struct { typedef struct {
u32 width; u32 width;
u32 height; u32 height;
@ -91,6 +98,9 @@ typedef uint8_t Color;
httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data); httpd_cgi_state screenSerializeToBuffer(char *buffer, size_t buf_len, void **data);
void screenSerializeLabelsToBuffer(char *buffer, size_t buf_len);
typedef struct { typedef struct {
u8 lsb; u8 lsb;
u8 msb; u8 msb;
@ -187,6 +197,6 @@ void screen_putchar(const char *ch);
void screen_dd(void); void screen_dd(void);
#endif #endif
extern void screen_notifyChange(void); extern void screen_notifyChange(ScreenNotifyChangeTopic topic);
#endif // SCREEN_H #endif // SCREEN_H

Loading…
Cancel
Save