From 3c202a1f5090189282aa56e844bf8e7f476e30e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 23 Jul 2017 01:47:18 +0200 Subject: [PATCH] error indication via GET arg err=... --- CMakeLists.txt | 8 ++- html_orig/css/app.css | 19 +++--- html_orig/js/app.js | 51 ++++++++++++++ html_orig/jssrc/appcommon.js | 19 ++++++ html_orig/lang/en.php | 10 +-- html_orig/packjs.sh | 1 + html_orig/pages/_head.php | 5 ++ html_orig/pages/_tail.php | 4 ++ html_orig/sass/form/_form_layout.scss | 15 +++++ html_orig/sass/layout/_modal.scss | 9 +-- user/cgi_appcfg.c | 97 +++++++++++++++++++++++++++ user/cgi_appcfg.h | 9 +++ user/cgi_wifi.c | 12 ++-- 13 files changed, 235 insertions(+), 24 deletions(-) create mode 100644 user/cgi_appcfg.c create mode 100644 user/cgi_appcfg.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fa43d7..2701a1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,6 +93,8 @@ set(SOURCE_FILES user/io.h user/cgi_wifi.c user/cgi_wifi.h + user/cgi_appcfg.c + user/cgi_appcfg.h user/cgi_ping.c user/cgi_reset.c user/uart_driver.c @@ -113,7 +115,11 @@ set(SOURCE_FILES user/cgi_sockets.h user/ansi_parser_callbacks.c user/ansi_parser_callbacks.h - user/user_main.h user/wifimgr.c user/wifimgr.h user/persist.c user/persist.h) + user/user_main.h + user/wifimgr.c + user/wifimgr.h + user/persist.c + user/persist.h) include_directories(include) include_directories(user) diff --git a/html_orig/css/app.css b/html_orig/css/app.css index 79949aa..f425e9a 100644 --- a/html_orig/css/app.css +++ b/html_orig/css/app.css @@ -579,17 +579,12 @@ ul > * { .NotifyMsg { position: fixed; - bottom: 2.61792rem; + top: 1.618rem; + right: 2.61792rem; padding: 0.61805rem 1rem; - left: 50%; - -webkit-transform: translate(-50%, 0); - -moz-transform: translate(-50%, 0); - -ms-transform: translate(-50%, 0); - -o-transform: translate(-50%, 0); - transform: translate(-50%, 0); -webkit-font-smoothing: subpixel-antialiased; -webkit-transform: translateZ(0) scale(1, 1); - background: #37a349; + background: #3887d0; color: white; text-shadow: 0 0 2px black; box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.6); @@ -740,6 +735,12 @@ input[type="number"], input[type="password"], input[type="text"], textarea, sele input[type="number"] { width: 125px; } +.Box.errors .list { + color: crimson; + font-weight: bold; } +.Box.errors .lead { + color: white; } + form .Row { vertical-align: middle; margin: 12px auto; @@ -794,6 +795,8 @@ form .Row { user-select: none; white-space: nowrap; word-wrap: normal; } + form .Row label.error { + color: crimson; } form .Row input[type="range"] { width: 200px; } @media screen and (max-width: 544px) { diff --git a/html_orig/js/app.js b/html_orig/js/app.js index fc1db8c..204e008 100644 --- a/html_orig/js/app.js +++ b/html_orig/js/app.js @@ -852,6 +852,38 @@ function jsp() { window.Modal = modal; })(); +(function (nt) { + var sel = '#notif'; + + var hideTmeo1; // timeout to start hiding (transition) + var hideTmeo2; // timeout to add the hidden class + + nt.show = function (message, timeout) { + $(sel).html(message); + Modal.show(sel); + + clearTimeout(hideTmeo1); + clearTimeout(hideTmeo2); + + if (undef(timeout)) timeout = 2500; + + hideTmeo1 = setTimeout(nt.hide, timeout); + }; + + nt.hide = function () { + var $m = $(sel); + $m.removeClass('visible'); + hideTmeo2 = setTimeout(function () { + $m.addClass('hidden'); + }, 250); // transition time + }; + + nt.init = function() { + $(sel).on('click', function() { + nt.hide(this); + }); + }; +})(window.Notify = {}); /** Global generic init */ $.ready(function () { // Checkbox UI (checkbox CSS and hidden input with int value) @@ -915,7 +947,26 @@ $.ready(function () { e.preventDefault(); }); + var errAt = location.search.indexOf('err='); + if (errAt !== -1 && qs('.Box.errors')) { + var errs = location.search.substr(errAt+4).split(','); + var hres = []; + errs.forEach(function(er) { + var lbl = qs('label[for="'+er+'"]'); + if (lbl) { + lbl.classList.add('error'); + hres.push(lbl.childNodes[0].textContent.trim().replace(/: ?$/, '')); + } else { + hres.push(er); + } + }); + + qs('.Box.errors .list').innerHTML = hres.join(', '); + qs('.Box.errors').classList.remove('hidden'); + } + Modal.init(); + Notify.init(); }); $._loader = function(vis) { diff --git a/html_orig/jssrc/appcommon.js b/html_orig/jssrc/appcommon.js index a40faa6..ee4569c 100644 --- a/html_orig/jssrc/appcommon.js +++ b/html_orig/jssrc/appcommon.js @@ -61,7 +61,26 @@ $.ready(function () { e.preventDefault(); }); + var errAt = location.search.indexOf('err='); + if (errAt !== -1 && qs('.Box.errors')) { + var errs = location.search.substr(errAt+4).split(','); + var hres = []; + errs.forEach(function(er) { + var lbl = qs('label[for="'+er+'"]'); + if (lbl) { + lbl.classList.add('error'); + hres.push(lbl.childNodes[0].textContent.trim().replace(/: ?$/, '')); + } else { + hres.push(er); + } + }); + + qs('.Box.errors .list').innerHTML = hres.join(', '); + qs('.Box.errors').classList.remove('hidden'); + } + Modal.init(); + Notify.init(); }); $._loader = function(vis) { diff --git a/html_orig/lang/en.php b/html_orig/lang/en.php index 08bfd23..f866c36 100644 --- a/html_orig/lang/en.php +++ b/html_orig/lang/en.php @@ -13,11 +13,12 @@ return [ 'title.term' => 'Terminal', - 'net.ap' => 'Access Point DHCP Config', - 'net.sta' => 'Client IP Config', + 'net.ap' => 'DHCP Server', + 'net.sta' => 'DHCP Client', 'net.explain_sta' => ' - Those settings affect the built-in DHCP client. Switching it off + Those settings affect the built-in DHCP client used for + connecting to an external network. Switching DHCP (dynamic IP) off makes ESPTerm use the configured static IP. Please double-check those settings before submitting, setting them incorrectly may make it hard to access ESPTerm via the external network.', @@ -33,7 +34,7 @@ return [ 'net.ap_addr_ip' => 'Own IP address', 'net.ap_addr_mask' => 'Subnet mask', - 'net.sta_dhcp_enable' => 'Enable DHCP', + 'net.sta_dhcp_enable' => 'Use dynamic IP', 'net.sta_addr_ip' => 'ESPTerm static IP', 'net.sta_addr_mask' => 'Subnet mask', 'net.sta_addr_gw' => 'Gateway IP', @@ -77,4 +78,5 @@ return [ 'yes' => 'Yes', 'no' => 'No', 'confirm' => 'OK', + 'form_errors' => 'Validation errors for:', ]; diff --git a/html_orig/packjs.sh b/html_orig/packjs.sh index 53c9e69..f1652fd 100755 --- a/html_orig/packjs.sh +++ b/html_orig/packjs.sh @@ -5,5 +5,6 @@ echo "Packing js..." cat jssrc/chibi.js \ jssrc/utils.js \ jssrc/modal.js \ + jssrc/notif.js \ jssrc/appcommon.js \ jssrc/term.js > js/app.js diff --git a/html_orig/pages/_head.php b/html_orig/pages/_head.php index 3134c1c..a6d428d 100644 --- a/html_orig/pages/_head.php +++ b/html_orig/pages/_head.php @@ -23,4 +23,9 @@ if (strpos($_GET['BODYCLASS'], 'cfg') !== false) { Loading…

+ + + diff --git a/html_orig/pages/_tail.php b/html_orig/pages/_tail.php index 560c6a1..dfdca17 100644 --- a/html_orig/pages/_tail.php +++ b/html_orig/pages/_tail.php @@ -1,5 +1,9 @@ + + + + diff --git a/html_orig/sass/form/_form_layout.scss b/html_orig/sass/form/_form_layout.scss index c6aa39d..2f0d570 100755 --- a/html_orig/sass/form/_form_layout.scss +++ b/html_orig/sass/form/_form_layout.scss @@ -9,6 +9,17 @@ input[type="number"] { width: $form-field-w/2; } +.Box.errors { + .list { + color: crimson; + font-weight: bold; + } + + .lead { + color: white; + } +} + form .Row { vertical-align: middle; margin: 12px auto; @@ -89,6 +100,10 @@ form .Row { @include nowrap; } + label.error { + color: crimson; + } + //.checkbox-wrap { // display: inline-block; // width: $form-label-w; diff --git a/html_orig/sass/layout/_modal.scss b/html_orig/sass/layout/_modal.scss index 781d833..21bdab1 100755 --- a/html_orig/sass/layout/_modal.scss +++ b/html_orig/sass/layout/_modal.scss @@ -43,17 +43,18 @@ // "toast" .NotifyMsg { position: fixed; - bottom: dist(2); + top: dist(1); + right: dist(2); padding: dist(-1) dist(0); // center horizontally - left: 50%; - @include translate(-50%,0); + //left: 50%; + //@include translate(-50%,0); // hack to remove blur in chrome -webkit-font-smoothing: subpixel-antialiased; -webkit-transform: translateZ(0) scale(1.0, 1.0); - background: #37a349; + background: #3887d0; &.error { background: #d03e42; } diff --git a/user/cgi_appcfg.c b/user/cgi_appcfg.c new file mode 100644 index 0000000..87c1b73 --- /dev/null +++ b/user/cgi_appcfg.c @@ -0,0 +1,97 @@ +/* +Cgi/template routines for configuring non-wifi settings +*/ + +#include +#include "cgi_wifi.h" +#include "wifimgr.h" +#include "persist.h" + +// strcpy that adds 0 at the end of the buffer. Returns void. +#define strncpy_safe(dst, src, n) do { strncpy((char *)(dst), (char *)(src), (n)); (dst)[(n)-1]=0; } while (0) + +/** + * Universal CGI endpoint to set WiFi params. + * Note that some may cause a (delayed) restart. + */ +httpd_cgi_state ICACHE_FLASH_ATTR cgiAppCfgSet(HttpdConnData *connData) +{ + static ETSTimer timer; + + char buff[50]; + +#define REDIR_BASE_URL "/wifi?err=" + + char redir_url_buf[300]; + char *redir_url = redir_url_buf; + redir_url += sprintf(redir_url, REDIR_BASE_URL); + // we'll test if anything was printed by looking for \0 in failed_keys_buf + + if (connData->conn == NULL) { + //Connection aborted. Clean up. + return HTTPD_CGI_DONE; + } + +#define GET_ARG(key) (httpdFindArg(connData->getArgs, key, buff, sizeof(buff)) > 0) + + // TODO + if (GET_ARG("opmode")) { + dbg("Setting WiFi opmode to: %s", buff); + int mode = atoi(buff); + if (mode > NULL_MODE && mode < MAX_MODE) { + wificonf->opmode = (WIFI_MODE) mode; + } else { + warn("Bad opmode value \"%s\"", buff); + redir_url += sprintf(redir_url, "opmode,"); + } + } + + if (redir_url_buf[strlen(REDIR_BASE_URL)] == 0) { + // All was OK + info("Set WiFi params - success, applying in 1000 ms"); + + // Settings are applied only if all was OK + // + // This is so that options that consist of multiple keys sent together are not applied + // only partially if set wrong, which could lead to eg. user losing access and having + // to reset to defaults. + persist_store(); + + // Delayed settings apply, so the response page has a chance to load. + // If user connects via the Station IF, they may not even notice the connection reset. + os_timer_disarm(&timer); + os_timer_setfn(&timer, applyWifiSettingsLaterCb, NULL); + os_timer_arm(&timer, 1000, false); + + httpdRedirect(connData, "/wifi"); + } else { + warn("Some WiFi settings did not validate, asking for correction"); + // Some errors, appended to the URL as ?err= + httpdRedirect(connData, redir_url_buf); + } + return HTTPD_CGI_DONE; +} + + +//Template code for the WLAN page. +httpd_cgi_state ICACHE_FLASH_ATTR tplAppCfg(HttpdConnData *connData, char *token, void **arg) +{ + char buff[100]; + int x; + int connectStatus; + + if (token == NULL) { + // We're done + return HTTPD_CGI_DONE; + } + + strcpy(buff, ""); // fallback + + // TODO + if (streq(token, "opmode_name")) { + strcpy(buff, opmode2str(wificonf->opmode)); + } + + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} diff --git a/user/cgi_appcfg.h b/user/cgi_appcfg.h new file mode 100644 index 0000000..fe4fa79 --- /dev/null +++ b/user/cgi_appcfg.h @@ -0,0 +1,9 @@ +#ifndef CGIAPPCFG_H +#define CGIAPPCFG_H + +#include "httpd.h" + +httpd_cgi_state cgiAppCfgSet(HttpdConnData *connData); +httpd_cgi_state tplAppCfg(HttpdConnData *connData, char *token, void **arg); + +#endif diff --git a/user/cgi_wifi.c b/user/cgi_wifi.c index 2ec3306..31b1ed7 100644 --- a/user/cgi_wifi.c +++ b/user/cgi_wifi.c @@ -13,17 +13,13 @@ Cgi/template routines for the /wifi url. * File adapted and improved by Ondřej Hruška */ -// TODO convert to work with WiFi Manager -// TODO make changes write to wificonf and apply when a different CGI is run (/wifi/apply or something) -// TODO (connection will trigger this immediately, with some delayto show the connecting page. Then polling cna proceed as usual) - #include #include "cgi_wifi.h" #include "wifimgr.h" #include "persist.h" // strcpy that adds 0 at the end of the buffer. Returns void. -#define strncpy_safe(dst, src, n) do { strncpy((char *)(dst), (char *)(src), (n)); dst[(n)-1]=0; } while (0) +#define strncpy_safe(dst, src, n) do { strncpy((char *)(dst), (char *)(src), (n)); (dst)[(n)-1]=0; } while (0) /** WiFi access point data */ typedef struct { @@ -419,9 +415,11 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) char buff[50]; +#define REDIR_BASE_URL "/wifi?err=" + char redir_url_buf[300]; char *redir_url = redir_url_buf; - redir_url += sprintf(redir_url, "/wifi?err="); + redir_url += sprintf(redir_url, REDIR_BASE_URL); // we'll test if anything was printed by looking for \0 in failed_keys_buf if (connData->conn == NULL) { @@ -707,7 +705,7 @@ httpd_cgi_state ICACHE_FLASH_ATTR cgiWiFiSetParams(HttpdConnData *connData) } } - if (redir_url_buf[10] == 0) { + if (redir_url_buf[strlen(REDIR_BASE_URL)] == 0) { // All was OK info("Set WiFi params - success, applying in 1000 ms");