From d29fa0423fdb2bc026c00d5e8c59f4a9d1740978 Mon Sep 17 00:00:00 2001 From: Thorsten von Eicken Date: Sun, 14 Jun 2015 01:22:01 -0700 Subject: [PATCH] finished UI refactoring to ajax --- html/console.js | 15 ++- html/console.tpl | 2 +- html/log.tpl | 22 ++++- html/style.css | 6 ++ html/ui.js | 43 ++++++-- html/wifi/wifi.tpl | 147 +++++++++++++++++----------- httpd/auth.c | 6 +- httpd/httpd.c | 32 +++--- httpd/httpd.h | 3 +- httpd/httpdespfs.c | 58 ++++++----- include/espmissingincludes.h | 4 +- user/cgiwifi.c | 183 +++++++++++++++++++---------------- user/log.c | 19 ++-- user/user_main.c | 4 +- 14 files changed, 336 insertions(+), 208 deletions(-) diff --git a/html/console.js b/html/console.js index 4205738..355c797 100644 --- a/html/console.js +++ b/html/console.js @@ -1,11 +1,16 @@ -function fetchText(delay) { +function fetchText(delay, repeat) { el = $("#console"); if (el.textEnd == undefined) { el.textEnd = 0; el.innerHTML = ""; } window.setTimeout(function() { - ajaxJson('GET', console_url + "?start=" + el.textEnd, updateText, retryLoad); + ajaxJson('GET', console_url + "?start=" + el.textEnd, + function(resp) { + var dly = updateText(resp); + if (repeat) fetchText(dly, repeat); + }, + function() { retryLoad(repeat); }); }, delay); } @@ -22,9 +27,9 @@ function updateText(resp) { el.textEnd = resp.start + resp.len; delay = 500; } - fetchText(delay); + return delay; } -function retryLoad() { - fetchText(1000); +function retryLoad(repeat) { + fetchText(1000, repeat); } diff --git a/html/console.tpl b/html/console.tpl index 2486b9f..e45bb63 100644 --- a/html/console.tpl +++ b/html/console.tpl @@ -34,7 +34,7 @@ } window.onload = function() { - fetchText(100); + fetchText(100, true); $("#reset-button").addEventListener("click", function(e) { e.preventDefault(); diff --git a/html/log.tpl b/html/log.tpl index d72d368..3003168 100644 --- a/html/log.tpl +++ b/html/log.tpl @@ -4,9 +4,18 @@
-

The debug log shows the 1024 last characters printed by the esp-link software itself to - its own debug log.

-

+      
+
+

+ Refresh +

+
+

+ The debug log shows the 1024 last characters printed by the esp-link software itself to + its own debug log. +

+
+

     
@@ -16,7 +25,12 @@ diff --git a/html/style.css b/html/style.css index ca798cc..6198f73 100644 --- a/html/style.css +++ b/html/style.css @@ -296,6 +296,12 @@ pre.console a { border-top: 10px solid rgba(204, 51, 0, 0.8); border-radius: 100%; } +.spinner-small { + display: inline-block; + height: 1em; + width: 1em; + border-width: 4px; +} @-webkit-keyframes rotation { from { diff --git a/html/ui.js b/html/ui.js index 9593fd9..488e2c7 100644 --- a/html/ui.js +++ b/html/ui.js @@ -1,6 +1,5 @@ // fill out menu items (function() { - console.log("Filling out menu with", menu.length, "items"); html = ""; for (var i=0; i= 200 && xhr.status < 300) { + console.log("XHR done:", method, url, "->", xhr.status); ok_cb(xhr.responseText); } else { - err_cb(xhr.status, xhr.statusText); + console.log("XHR ERR :", method, url, "->", xhr.status, xhr.responseText); + err_cb(xhr.status, xhr.responseText); } } - xhr.send(); + console.log("XHR send:", method, url); + try { + xhr.send(); + } catch(err) { + console.log("XHR EXC :", method, url, "->", err); + err_cb(599, err); + } +} + +function dispatchJson(resp, ok_cb, err_cb) { + var j; + try { j = JSON.parse(resp); } + catch(err) { + console.log("JSON parse error: " + err + ". In: " + resp); + err_cb(500, "JSON parse error: " + err); + return; + } + ok_cb(j); } function ajaxJson(method, url, ok_cb, err_cb) { - ajaxReq(method, url, function(resp) { ok_cb(JSON.parse(resp)); }, err_cb); + ajaxReq(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); } function ajaxSpin(method, url, ok_cb, err_cb) { $("#spinner").removeAttribute('hidden'); - console.log("starting spinner"); ajaxReq(method, url, function(resp) { $("#spinner").setAttribute('hidden', ''); ok_cb(resp); }, function(status, statusText) { $("#spinner").setAttribute('hidden', ''); - showWarning("Request error: " + statusText); + showWarning("Error: " + statusText); err_cb(status, statusText); }); } function ajaxJsonSpin(method, url, ok_cb, err_cb) { - ajaxSpin(method, url, function(resp) { ok_cb(JSON.parse(resp)); }, err_cb); + ajaxSpin(method, url, function(resp) { dispatchJson(resp, ok_cb, err_cb); }, err_cb); } diff --git a/html/wifi/wifi.tpl b/html/wifi/wifi.tpl index f3d4f57..b0531d6 100644 --- a/html/wifi/wifi.tpl +++ b/html/wifi/wifi.tpl @@ -6,23 +6,27 @@

Wifi State

- +
+
+ +

Wifi Association

+
To connect to a WiFi network, please select one of the detected networks, enter the password, and hit the connect button... -
Scanning...
+
Scanning...
@@ -83,95 +87,128 @@ function getSelectedEssid() { return currAp; } -var scan_xhr = j(); -function scanAPs() { - scan_xhr.open("GET", "wifiscan"); - scan_xhr.onreadystatechange = function() { - if (scan_xhr.readyState == 4 && scan_xhr.status >= 200 && scan_xhr.status < 300) { - var data = JSON.parse(scan_xhr.responseText); +var scanTimeout = null; + +function scanResult() { + ajaxJson('GET', "scan", function(data) { currAp = getSelectedEssid(); if (data.result.inProgress == "0" && data.result.APs.length > 1) { $("#aps").innerHTML = ""; + var n = 0; for (var i=0; i= 200 && xhr.status < 300) { - var data = JSON.parse(xhr.responseText); - Object.keys(data).forEach(function(v) { - el = document.getElementById("wifi-" + v); - if (el != null) el.innerHTML = data[v]; - }); - currAp = data.ssid; - } else { - window.setTimeout(getWifiInfo, 1000); - } - } - xhr.send(); + ajaxJson('GET', "info", showWifiInfo, + function(s, st) { window.setTimeout(getWifiInfo, 1000); }); } function getStatus() { - var xhr = j(); - xhr.open("GET", "connstatus"); - xhr.onreadystatechange = function() { - if (xhr.readyState != 4) { return; } - if (xhr.status >= 200 && xhr.status < 300) { - var data = JSON.parse(xhr.responseText); + ajaxJsonSpin("GET", "connstatus", function(data) { if (data.status == "idle" || data.status == "connecting") { $("#aps").innerHTML = "Connecting..."; + showNotification("Connecting..."); window.setTimeout(getStatus, 1000); } else if (data.status == "got IP address") { - $("#aps").innerHTML="Connected! Got IP "+data.ip+ ".
" + - "If you're in the same network, you can access it
here.
ESP Link will switch to STA-only mode in a few seconds."; + var txt = "Connected! Got IP "+data.ip; + showNotification(txt); + showWifiInfo(data); + + var txt2 = "ESP Link will switch to STA-only mode in a few seconds"; + window.setTimeout(function() { showNotification(txt2); }, 4000); + + $("#reconnect").removeAttribute("hidden"); + $("#reconnect").innerHTML = + "If you are in the same network, go to "+data.ip+", else connect to network "+data.ssid+" first."; } else { - $("#aps").innerHTML="Oops: " + data.status + ". Reason: " + data.reason + - "
Check password and selected AP.
Go Back"; + showWarning("Connection failed: " + data.status + ", " + data.reason); + $("#aps").innerHTML = + "Check password and selected AP. Go Back"; } - } else { + }, function(s, st) { + //showWarning("Can't get status: " + st); window.setTimeout(getStatus, 2000); - } - } - xhr.send(); + }); +} + +function changeWifiMode(m) { + hideWarning(); + ajaxSpin("POST", "setmode?mode=" + m, function(resp) { + showNotification("Mode changed"); + window.setTimeout(getWifiInfo, 100); + }, function(s, st) { + showWarning("Error changing mode: " + st); + window.setTimeout(getWifiInfo, 100); + }); } function changeWifiAp(e) { e.preventDefault(); - var xhr = j(); var passwd = $("#wifi-passwd").value; var essid = getSelectedEssid(); console.log("Posting form", "essid=" + essid, "pwd="+passwd); - xhr.open("POST", "connect"); - xhr.onreadystatechange = function() { - if (xhr.readyState != 4) { return; } - if (xhr.status >= 200 && xhr.status < 300) { + showNotification("Connecting to " + essid); + var url = "connect?essid="+encodeURIComponent(essid)+"&passwd="+encodeURIComponent(passwd); + + hideWarning(); + $("#reconnect").setAttribute("hidden", ""); + $("#wifi-passwd").value = ""; + var cb = $("#connect-button"); + var cn = cb.className; + cb.className += ' pure-button-disabled'; + ajaxSpin("POST", url, function(resp) { + $("#spinner").removeAttribute('hidden'); // hack + showNotification("Waiting for network change..."); + window.scrollTo(0, 0); window.setTimeout(getStatus, 2000); - } else { + }, function(s, st) { + showWarning("Error switching network: "+st); + cb.className = cn; window.setTimeout(scanAPs, 1000); - } - } - xhr.setRequestHeader("Content-type", "application/x-form-urlencoded"); - xhr.send("essid="+encodeURIComponent(essid)+"&passwd="+encodeURIComponent(passwd)); + }); } window.onload=function(e) { getWifiInfo(); $("#wifiform").onsubmit = changeWifiAp; - window.setTimeout(scanAPs, 500); + scanTimeout = window.setTimeout(scanAPs, 500); }; diff --git a/httpd/auth.c b/httpd/auth.c index 1e247a0..df14175 100644 --- a/httpd/auth.c +++ b/httpd/auth.c @@ -5,9 +5,9 @@ HTTP auth implementation. Only does basic authentication for now. /* * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): - * Jeroen Domburg 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. + * Jeroen Domburg 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. * ---------------------------------------------------------------------------- */ diff --git a/httpd/httpd.c b/httpd/httpd.c index b63923b..e265f93 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -93,6 +93,10 @@ static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) { //Retires a connection for re-use static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) { + uint32 dt = conn->startTime; + if (dt > 0) dt = (system_get_time() - dt)/1000; + os_printf("Closed %p, took %ums, heap=%ld\n", conn->conn, dt, + (unsigned long)system_get_free_heap_size()); if (conn->post->buff!=NULL) os_free(conn->post->buff); conn->post->buff=NULL; conn->cgi=NULL; @@ -192,7 +196,8 @@ int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *re void ICACHE_FLASH_ATTR httpdStartResponse(HttpdConnData *conn, int code) { char buff[128]; int l; - l=os_sprintf(buff, "HTTP/1.0 %d OK\r\nServer: esp8266-httpd/"HTTPDVER"\r\nConnection: close\r\n", code); + char *status = code < 400 ? "OK" : "ERROR"; + l = os_sprintf(buff, "HTTP/1.0 %d %s\r\nServer: esp-link\r\nConnection: close\r\n", code, status); httpdSend(conn, buff, l); } @@ -215,7 +220,7 @@ void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn) { void ICACHE_FLASH_ATTR httpdRedirect(HttpdConnData *conn, char *newUrl) { char buff[1024]; int l; - l=os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-httpd/"HTTPDVER"\r\nConnection: close\r\nLocation: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl); + l=os_sprintf(buff, "HTTP/1.0 302 Found\r\nServer: esp8266-link\r\nConnection: close\r\nLocation: %s\r\n\r\nRedirecting to %s\r\n", newUrl, newUrl); httpdSend(conn, buff, l); } @@ -372,7 +377,12 @@ static void ICACHE_FLASH_ATTR httpdParseHeader(char *h, HttpdConnData *conn) { if (e==NULL) return; //wtf? *e=0; //terminate url part - os_printf("%s %s\n", HTTPD_METHOD_GET?"GET":"POST", conn->url); + os_printf("%s %s (%p) %d.%d.%d.%d:%d\n", + conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", + conn->url, conn->conn, + conn->conn->proto.tcp->remote_ip[0], conn->conn->proto.tcp->remote_ip[1], + conn->conn->proto.tcp->remote_ip[2], conn->conn->proto.tcp->remote_ip[3], + conn->conn->proto.tcp->remote_port); //Parse out the URL part before the GET parameters. conn->getArgs=(char*)os_strstr(conn->url, "?"); if (conn->getArgs!=0) { @@ -471,13 +481,6 @@ static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short } } -static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { - HttpdConnData *conn=httpdFindConnData(arg); - os_printf("ReconCb\n"); - if (conn==NULL) return; - //Yeah... No idea what to do here. ToDo: figure something out. -} - static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { //The esp sdk passes through wrong arg here, namely the one of the *listening* socket. //That is why we can't use (HttpdConnData)arg->sock here. @@ -490,7 +493,6 @@ static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { //is then used for something else, and we can use that to capture *most* of the //disconnect cases. if (connData[i].conn->state==ESPCONN_NONE || connData[i].conn->state>=ESPCONN_CLOSE) { - connData[i].conn=NULL; if (connData[i].cgi!=NULL) connData[i].cgi(&connData[i]); //flush cgi data httpdRetireConn(&connData[i]); } @@ -498,6 +500,13 @@ static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { } } +// Callback indicating a failure in the connection. "Recon" is probably intended in the sense +// of "you need to reconnect". Sigh... +static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { + os_printf("Connection %p died, err=%d\n", arg, err); + httpdDisconCb(arg); // no different from close... +} + static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { struct espconn *conn=arg; @@ -518,6 +527,7 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { connData[i].post->buffLen=0; connData[i].post->received=0; connData[i].post->len=-1; + connData[i].startTime = system_get_time(); espconn_regist_recvcb(conn, httpdRecvCb); espconn_regist_reconcb(conn, httpdReconCb); diff --git a/httpd/httpd.h b/httpd/httpd.h index 95611bd..adab463 100644 --- a/httpd/httpd.h +++ b/httpd/httpd.h @@ -21,6 +21,7 @@ typedef int (* cgiSendCallback)(HttpdConnData *connData); //A struct describing a http connection. This gets passed to cgi functions. struct HttpdConnData { struct espconn *conn; + uint32 startTime; char requestType; char *url; char *getArgs; @@ -62,4 +63,4 @@ void ICACHE_FLASH_ATTR httpdEndHeaders(HttpdConnData *conn); int ICACHE_FLASH_ATTR httpdGetHeader(HttpdConnData *conn, char *header, char *ret, int retLen); int ICACHE_FLASH_ATTR httpdSend(HttpdConnData *conn, const char *data, int len); -#endif \ No newline at end of file +#endif diff --git a/httpd/httpdespfs.c b/httpd/httpdespfs.c index e24252d..861e995 100644 --- a/httpd/httpdespfs.c +++ b/httpd/httpdespfs.c @@ -108,34 +108,40 @@ int ICACHE_FLASH_ATTR cgiEspFsHtml(HttpdConnData *connData) { os_strcpy(buff, "Header file 'head.tpl' not found\n"); os_printf(buff); status = 500; - } else { - // read file and return it - int len = espFsRead(file, buff, sizeof(buff)); - if (len == sizeof(buff)) { - os_strcpy(buff, "Header file 'head.tpl' too large!\n"); - os_printf(buff); - status = 500; - } - // open the real file for next time around - file = espFsOpen(connData->url); - if (file == NULL) { - os_strcpy(buff, connData->url); - os_strcat(buff, " not found\n"); - os_printf(buff); - status = 404; - } else { - connData->cgiData = file; - httpdStartResponse(connData, 200); - httpdHeader(connData, "Content-Type", "text/html; charset=UTF-8"); - httpdEndHeaders(connData); - httpdSend(connData, buff, len); - printGlobalJSON(connData); - return HTTPD_CGI_MORE; - } + goto error; } - // error response + + // read file and return it + int len = espFsRead(file, buff, sizeof(buff)); + espFsClose(file); + if (len == sizeof(buff)) { + os_sprintf(buff, "Header file 'head.tpl' too large (%d>%d)!\n", len, sizeof(buff)); + os_printf(buff); + status = 500; + goto error; + } + + // before returning, open the real file for next time around + file = espFsOpen(connData->url); + if (file == NULL) { + os_strcpy(buff, connData->url); + os_strcat(buff, " not found\n"); + os_printf(buff); + status = 404; + goto error; + } + + connData->cgiData = file; + httpdStartResponse(connData, status); + httpdHeader(connData, "Content-Type", "text/html; charset=UTF-8"); + httpdEndHeaders(connData); + httpdSend(connData, buff, len); + printGlobalJSON(connData); + return HTTPD_CGI_MORE; + +error: // error response httpdStartResponse(connData, status); - httpdHeader(connData, "text/plain", "text/html; charset=UTF-8"); + httpdHeader(connData, "Content-Type", "text/html; charset=UTF-8"); httpdEndHeaders(connData); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; diff --git a/include/espmissingincludes.h b/include/espmissingincludes.h index 77fc7e0..47bc1c1 100644 --- a/include/espmissingincludes.h +++ b/include/espmissingincludes.h @@ -6,9 +6,11 @@ #include //Missing function prototypes in include folders. Gcc will warn on these if we don't define 'em anywhere. -//MOST OF THESE ARE GUESSED! but they seem to swork and shut up the compiler. +//MOST OF THESE ARE GUESSED! but they seem to work and shut up the compiler. typedef struct espconn espconn; +bool wifi_station_set_hostname(char *); + int atoi(const char *nptr); void ets_install_putc1(void *routine); // necessary for #define os_xxx -> ets_xxx diff --git a/user/cgiwifi.c b/user/cgiwifi.c index d4b6109..8410bb9 100644 --- a/user/cgiwifi.c +++ b/user/cgiwifi.c @@ -159,59 +159,56 @@ void ICACHE_FLASH_ATTR wifiScanDoneCb(void *arg, STATUS status) { cgiWifiAps.scanInProgress=0; } -//Routine to start a WiFi access point scan. -static void ICACHE_FLASH_ATTR wifiStartScan() { -// int x; - if (cgiWifiAps.scanInProgress) return; - cgiWifiAps.scanInProgress=1; +static ETSTimer scanTimer; +static void ICACHE_FLASH_ATTR scanStartCb(void *arg) { + os_printf("Starting a scan\n"); wifi_station_scan(NULL, wifiScanDoneCb); } -//This CGI is called from the bit of AJAX-code in wifi.tpl. It will initiate a -//scan for access points and if available will return the result of an earlier scan. -//The result is embedded in a bit of JSON parsed by the javascript in wifi.tpl. -int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { - int pos=(int)connData->cgiData; - int len; - char buff[1024]; - - if (!cgiWifiAps.scanInProgress && pos!=0) { - //Fill in json code for an access point - if (pos-1ssid, cgiWifiAps.apData[pos-1]->rssi, - cgiWifiAps.apData[pos-1]->enc, (pos-1==cgiWifiAps.noAps-1)?"":","); - httpdSend(connData, buff, len); - } - pos++; - if ((pos-1)>=cgiWifiAps.noAps) { - len=os_sprintf(buff, "]\n}\n}\n"); - httpdSend(connData, buff, len); - //Also start a new scan. - wifiStartScan(); - return HTTPD_CGI_DONE; - } else { - connData->cgiData=(void*)pos; - return HTTPD_CGI_MORE; - } +static int ICACHE_FLASH_ATTR cgiWiFiStartScan(HttpdConnData *connData) { + jsonHeader(connData, 200); + if (!cgiWifiAps.scanInProgress) { + cgiWifiAps.scanInProgress = 1; + os_timer_disarm(&scanTimer); + os_timer_setfn(&scanTimer, scanStartCb, NULL); + os_timer_arm(&scanTimer, 1000, 0); } + return HTTPD_CGI_DONE; +} - httpdStartResponse(connData, 200); - httpdHeader(connData, "Content-Type", "text/json"); - httpdEndHeaders(connData); +static int ICACHE_FLASH_ATTR cgiWiFiGetScan(HttpdConnData *connData) { + char buff[2048]; + int len; + + jsonHeader(connData, 200); if (cgiWifiAps.scanInProgress==1) { //We're still scanning. Tell Javascript code that. - len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); + len = os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"1\"\n }\n}\n"); httpdSend(connData, buff, len); return HTTPD_CGI_DONE; + } + + len = os_sprintf(buff, "{\"result\": {\"inProgress\": \"0\", \"APs\": [\n"); + for (int pos=0; posssid, cgiWifiAps.apData[pos]->rssi, + cgiWifiAps.apData[pos]->enc, (pos==cgiWifiAps.noAps-1)?"":","); + } + len += os_sprintf(buff+len, "]}}\n"); + //os_printf("Sending %d bytes: %s\n", len, buff); + httpdSend(connData, buff, len); + return HTTPD_CGI_DONE; +} + +int ICACHE_FLASH_ATTR cgiWiFiScan(HttpdConnData *connData) { + if (connData->requestType == HTTPD_METHOD_GET) { + return cgiWiFiGetScan(connData); + } else if (connData->requestType == HTTPD_METHOD_POST) { + return cgiWiFiStartScan(connData); } else { - //We have a scan result. Pass it on. - len=os_sprintf(buff, "{\n \"result\": { \n\"inProgress\": \"0\", \n\"APs\": [\n"); - httpdSend(connData, buff, len); - if (cgiWifiAps.apData==NULL) cgiWifiAps.noAps=0; - connData->cgiData=(void *)1; - return HTTPD_CGI_MORE; + jsonHeader(connData, 404); + return HTTPD_CGI_DONE; } } @@ -295,10 +292,10 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { return HTTPD_CGI_DONE; } - int el = httpdFindArg(connData->post->buff, "essid", essid, sizeof(essid)); - int pl = httpdFindArg(connData->post->buff, "passwd", passwd, sizeof(passwd)); + int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid)); + int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd)); - if (el > 0 && pl > 0) { + if (el > 0 && pl >= 0) { //Set to 0 if you want to disable the actual reconnecting bit #ifndef DEMO_MODE os_strncpy((char*)stconf.ssid, essid, 32); @@ -313,6 +310,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) { jsonHeader(connData, 200); } else { jsonHeader(connData, 400); + httpdSend(connData, "Cannot parse ssid or password", -1); } return HTTPD_CGI_DONE; } @@ -323,7 +321,7 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { char buff[1024]; if (connData->conn==NULL) { - //Connection aborted. Clean up. + // Connection aborted. Clean up. return HTTPD_CGI_DONE; } @@ -348,29 +346,72 @@ int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) { return HTTPD_CGI_DONE; } -char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", +static char *connStatuses[] = { "idle", "connecting", "wrong password", "AP not found", "failed", "got IP address" }; +static char *wifiWarn[] = { 0, + "Switch to STA+AP mode", + "Can't scan in this mode! Switch to STA+AP mode", + "Switch to STA mode", +}; + +// print various Wifi information into json buffer +int ICACHE_FLASH_ATTR printWifiInfo(char *buff) { + int len; + + struct station_config stconf; + wifi_station_get_config(&stconf); + + uint8_t op = wifi_get_opmode() & 0x3; + char *mode = wifiMode[op]; + char *status = "unknown"; + int st = wifi_station_get_connect_status(); + if (st > 0 && st < sizeof(connStatuses)) status = connStatuses[st]; + int p = wifi_get_phy_mode(); + char *phy = wifiPhy[p&3]; + char *warn = wifiWarn[op]; + sint8 rssi = wifi_station_get_rssi(); + if (rssi > 0) rssi = 0; + uint8 mac_addr[6]; + wifi_get_macaddr(0, mac_addr); + + len = os_sprintf(buff, + "\"mode\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " + "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"passwd\": \"%s\", " + "\"mac\":\"%02x:%02x:%02x:%02x:%02x:%02x\"", + mode, (char*)stconf.ssid, status, phy, rssi, warn, (char*)stconf.password, + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + + struct ip_info info; + if (wifi_get_ip_info(0, &info)) { + len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", + (info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff, + (info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff); + } else { + len += os_sprintf(buff+len, ", \"ip\": \"-none-\""); + } + + return len; +} + int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { char buff[1024]; int len; - struct ip_info info; int st=wifi_station_get_connect_status(); jsonHeader(connData, 200); - len = os_sprintf(buff, "{\"status\": \"%s\"", + len = os_sprintf(buff, "{\"status\": \"%s\", ", st > 0 && st < sizeof(connStatuses) ? connStatuses[st] : "unknown"); + len += printWifiInfo(buff+len); + len += os_sprintf(buff+len, ", "); + if (wifiReason != 0) { - len += os_sprintf(buff+len, ", \"reason\": \"%s\"", wifiGetReason()); + len += os_sprintf(buff+len, "\"reason\": \"%s\", ", wifiGetReason()); } if (st == STATION_GOT_IP) { - wifi_get_ip_info(0, &info); - len+=os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", - (info.ip.addr>>0)&0xff, (info.ip.addr>>8)&0xff, - (info.ip.addr>>16)&0xff, (info.ip.addr>>24)&0xff); if (wifi_get_opmode() != 1) { //Reset into AP-only mode sooner. os_timer_disarm(&resetTimer); @@ -379,56 +420,34 @@ int ICACHE_FLASH_ATTR cgiWiFiConnStatus(HttpdConnData *connData) { } } - len+=os_sprintf(buff+len, "}\n"); + len += os_sprintf(buff+len, "\"x\":0}\n"); - buff[len] = 0; os_printf(" -> %s\n", buff); httpdSend(connData, buff, len); return HTTPD_CGI_DONE; } -static char *wifiWarn[] = { 0, - "Switch to STA+AP mode", - "Can't scan in this mode! Switch to STA+AP mode", - "Switch to STA mode", -}; - // Cgi to return various Wifi information int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) { char buff[1024]; - int len; if (connData->conn==NULL) { return HTTPD_CGI_DONE; // Connection aborted } - struct station_config stconf; - wifi_station_get_config(&stconf); - - uint8_t op = wifi_get_opmode() & 0x3; - char *mode = wifiMode[op]; - char *status = "unknown"; - int st = wifi_station_get_connect_status(); - if (st > 0 && st < sizeof(connStatuses)) status = connStatuses[st]; - int p = wifi_get_phy_mode(); - char *phy = wifiPhy[p&3]; - char *warn = wifiWarn[op]; - sint8 rssi = wifi_station_get_rssi(); - if (rssi > 0) rssi = 0; - - len = os_sprintf(buff, - "{\"mode\": \"%s\", \"ssid\": \"%s\", \"status\": \"%s\", \"phy\": \"%s\", " - "\"rssi\": \"%ddB\", \"warn\": \"%s\", \"passwd\": \"%s\"}", - mode, (char*)stconf.ssid, status, phy, rssi, warn, (char*)stconf.password); + os_strcpy(buff, "{"); + printWifiInfo(buff+1); + os_strcat(buff, "}"); jsonHeader(connData, 200); - httpdSend(connData, buff, len); + httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } // Init the wireless, which consists of setting a timer if we expect to connect to an AP // so we can revert to STA+AP mode if we can't connect. void ICACHE_FLASH_ATTR wifiInit() { + //wifi_station_set_hostname("esp-link"); int x = wifi_get_opmode() & 0x3; os_printf("Wifi init, mode=%s\n", wifiMode[x]); wifi_set_phy_mode(2); diff --git a/user/log.c b/user/log.c index edddafb..5c77737 100644 --- a/user/log.c +++ b/user/log.c @@ -7,8 +7,8 @@ // The web log has a 1KB circular in-memory buffer which os_printf prints into and // the HTTP handler simply displays the buffer content on a web page. -// see consolse.c for invariants (same here) -#define BUF_MAX (1024) +// see console.c for invariants (same here) +#define BUF_MAX (1400) static char log_buf[BUF_MAX]; static int log_wr, log_rd; static int log_pos; @@ -18,9 +18,9 @@ static bool log_newline; // at start of a new line void ICACHE_FLASH_ATTR log_uart(bool enable) { if (!enable && !log_no_uart) { - os_printf("Turning OFF uart log\n"); + //os_printf("Turning OFF uart log\n"); os_delay_us(4*1000L); // time for uart to flush - log_no_uart = !enable; + //log_no_uart = !enable; } else if (enable && log_no_uart) { log_no_uart = !enable; os_printf("Turning ON uart log\n"); @@ -54,12 +54,17 @@ log_write_char(char c) { // Uart output unless disabled if (!log_no_uart) { if (log_newline) { - uart0_write_char('>'); - uart0_write_char(' '); + char buff[16]; + int l = os_sprintf(buff, "%6d> ", (system_get_time()/1000)%1000000); + for (int i=0; i