diff --git a/esp-link/cgi.c b/esp-link/cgi.c index bd2a074..f2881cf 100644 --- a/esp-link/cgi.c +++ b/esp-link/cgi.c @@ -16,6 +16,7 @@ Some random cgi routines. #include #include "cgi.h" +#include "config.h" void ICACHE_FLASH_ATTR noCacheHeaders(HttpdConnData *connData, int code) { @@ -158,7 +159,8 @@ int ICACHE_FLASH_ATTR cgiMenu(HttpdConnData *connData) { "\"REST/MQTT\", \"/mqtt.html\"," #endif "\"Debug log\", \"/log.html\" ],\n" - " \"version\": \"%s\" }", esp_link_version); + " \"version\": \"%s\"," + "\"name\":\"%s\"}", esp_link_version, flashConfig.sys_name); httpdSend(connData, buff, -1); return HTTPD_CGI_DONE; } diff --git a/esp-link/cgimqtt.c b/esp-link/cgimqtt.c index d4f7100..627d679 100644 --- a/esp-link/cgimqtt.c +++ b/esp-link/cgimqtt.c @@ -11,6 +11,10 @@ static char *mqtt_states[] = { "disconnected", "reconnecting", "connecting", "connected", }; +char *mqttState(void) { + return mqtt_states[mqttClient.connState]; +} + // Cgi to return MQTT settings int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) { char buff[1024]; diff --git a/esp-link/cgimqtt.h b/esp-link/cgimqtt.h index ef58f38..b720fac 100644 --- a/esp-link/cgimqtt.h +++ b/esp-link/cgimqtt.h @@ -4,6 +4,7 @@ #include "httpd.h" int cgiMqtt(HttpdConnData *connData); +char *mqttState(void); #endif // CGIMQTT_H #endif // MQTT diff --git a/esp-link/config.c b/esp-link/config.c index eb70a0f..c2253dd 100644 --- a/esp-link/config.c +++ b/esp-link/config.c @@ -22,6 +22,7 @@ FlashConfig flashDefault = { 2, 1, // mqtt_timeout, mqtt_clean_session 1883, 60, // mqtt port, mqtt_keepalive "\0", "\0", "\0", "\0", "\0", // mqtt host, client_id, user, password, status-topic + "\0", "\0", // sys name, sys description }; typedef union { diff --git a/esp-link/config.h b/esp-link/config.h index 5a67058..b26f7b6 100644 --- a/esp-link/config.h +++ b/esp-link/config.h @@ -18,11 +18,12 @@ typedef struct { char api_key[48]; // RSSI submission API key (Grovestreams for now) uint8_t slip_enable, mqtt_enable, // SLIP protocol, MQTT client mqtt_status_enable, // MQTT status reporting - mqtt_timeout, // MQTT send timeout + mqtt_timeout, // MQTT send timeout mqtt_clean_session; // MQTT clean session uint16_t mqtt_port, mqtt_keepalive; // MQTT Host port, MQTT Keepalive timer char mqtt_host[32], mqtt_clientid[48], mqtt_username[32], mqtt_password[32]; char mqtt_status_topic[32]; + char sys_name[12], sys_descr[128]; // informal system name and description } FlashConfig; extern FlashConfig flashConfig; diff --git a/esp-link/main.c b/esp-link/main.c index a481c6d..9fab6a9 100644 --- a/esp-link/main.c +++ b/esp-link/main.c @@ -31,6 +31,9 @@ #include "log.h" #include +static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData); +static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData); + /* This is the main url->function dispatching data struct. In short, it's a struct with various URLs plus their handlers. The handlers can @@ -64,8 +67,9 @@ HttpdBuiltInUrl builtInUrls[] = { { "/wifi/connstatus", cgiWiFiConnStatus, NULL }, { "/wifi/setmode", cgiWiFiSetMode, NULL }, { "/wifi/special", cgiWiFiSpecial, NULL }, + { "/system/info", cgiSystemInfo, NULL }, + { "/system/update", cgiSystemSet, NULL }, { "/pins", cgiPins, NULL }, - { "/tcpclient", cgiTcp, NULL }, #ifdef MQTT { "/mqtt", cgiMqtt, NULL }, #endif @@ -97,6 +101,53 @@ static char *flash_maps[] = { "2MB:1024/1024", "4MB:1024/1024" }; +// Cgi to return various System information +static int ICACHE_FLASH_ATTR cgiSystemInfo(HttpdConnData *connData) { + char buff[1024]; + + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + uint8 part_id = system_upgrade_userbin_check(); + uint32_t fid = spi_flash_get_id(); + struct rst_info *rst_info = system_get_rst_info(); + + os_sprintf(buff, "{\"name\": \"%s\", \"reset cause\": \"%d=%s\", " + "\"size\": \"%s\"," "\"id\": \"0x%02lX 0x%04lX\"," "\"partition\": \"%s\"," + "\"slip\": \"%s\"," "\"mqtt\": \"%s/%s\"," "\"baud\": \"%ld\"," + "\"description\": \"%s\"" "}", + flashConfig.sys_name, rst_info->reason, rst_codes[rst_info->reason], + flash_maps[system_get_flash_size_map()], fid & 0xff, (fid&0xff00)|((fid>>16)&0xff), + part_id ? "user2.bin" : "user1.bin", + flashConfig.slip_enable ? "enabled" : "disabled", + flashConfig.mqtt_enable ? "enabled" : "disabled", + mqttState(), flashConfig.baud_rate, flashConfig.sys_descr + ); + + jsonHeader(connData, 200); + httpdSend(connData, buff, -1); + return HTTPD_CGI_DONE; +} + +// Cgi to update system info (name/description) +static int ICACHE_FLASH_ATTR cgiSystemSet(HttpdConnData *connData) { + if (connData->conn==NULL) return HTTPD_CGI_DONE; // Connection aborted. Clean up. + + int8_t status = 0; + status |= getStringArg(connData, "name", flashConfig.sys_name, sizeof(flashConfig.sys_name)); + status |= getStringArg(connData, "description", flashConfig.sys_descr, sizeof(flashConfig.sys_descr)); + if (status < 0) return HTTPD_CGI_DONE; // getStringArg has produced an error response + + if (configSave()) { + httpdStartResponse(connData, 204); + httpdEndHeaders(connData); + } else { + httpdStartResponse(connData, 500); + httpdEndHeaders(connData); + httpdSend(connData, "Failed to save config", -1); + } + return HTTPD_CGI_DONE; +} + extern void app_init(void); extern void mqtt_client_init(void); @@ -120,6 +171,7 @@ void user_init(void) { os_delay_us(10000L); os_printf("\n\n** %s\n", esp_link_version); os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*"); + if (flashConfig.sys_name[0] == 0) os_strcpy(flashConfig.sys_name, "nameme"); #if defined(STA_SSID) && defined(STA_PASS) int x = wifi_get_opmode() & 0x3; diff --git a/html/home.html b/html/home.html index e7454f9..ca31c58 100644 --- a/html/home.html +++ b/html/home.html @@ -8,21 +8,20 @@
-

The JeeLabs esp-link firmware bridges the ESP8266 serial port to Wifi and can +

The JeeLabs esp-link firmware bridges the ESP8266 + serial port to Wifi and can program microcontrollers over the serial port, in particular Arduinos, AVRs, and - NXP's LPC800 and other ARM processors.

-

Program an Arduino/AVR using avrdude using a command - line similar to:

-
/home/arduino-1.0.5/hardware/tools/avrdude \
+ NXP's LPC800 and other ARM processors. Typical avrdude command line to + program an Arduino:

+
/home/arduino/hardware/tools/avrdude \
  -DV -patmega328p -Pnet:esp-link.local:23 -carduino -b115200 -U \
-   -C /home/arduino-1.0.5/hardware/tools/avrdude.conf flash:w:my_sketch.hex:i +   -C /home/arduino/hardware/tools/avrdude.conf flash:w:my_sketch.hex:i

where -Pnet:esp-link.local:23 tells avrdude to connect to port 23 of esp-link. - You can substitute the IP address of your esp-link for esp-link.local if necessary.

-

Please refer to + You can substitute the IP address of your esp-link for esp-link.local if necessary. + Please refer to the online README - for up-to-date help and to the forthcoming - JeeLabs blog for an intro to the codebase.

+ for up-to-date help.

@@ -37,7 +36,22 @@ Wifi status Wifi address Configured hostname - + +
+
+

Esp-link summary

+
+ + + + + + + + + +
@@ -56,8 +70,11 @@ diff --git a/html/style.css b/html/style.css index eba050f..59e2c3e 100644 --- a/html/style.css +++ b/html/style.css @@ -3,10 +3,14 @@ html, button, input, select, textarea, .pure-g [class *= "pure-u"] { font-family: sans-serif; } -input[type="text"], input[type="password"] { +input[type="text"], input[type="password"], textarea { width: 100%; } +input[type="text"]:disabled, textarea:disabled { + cursor: pointer; +} + input[type=checkbox] { float: left; margin: .35em 0.4em; diff --git a/html/ui.js b/html/ui.js index 16d6e7f..9085cdc 100644 --- a/html/ui.js +++ b/html/ui.js @@ -226,6 +226,7 @@ onLoad(function() {
\ \  esp-link\ +
\ \
\
\ @@ -258,6 +259,9 @@ onLoad(function() { v = $("#version"); if (v != null) { v.innerHTML = data.version; } + + n = $("#sysname"); + if (n != null) { n.innerHTML = data.name; } }, function() { setTimeout(getMenu, 1000); }); }; getMenu(); @@ -285,6 +289,51 @@ function getWifiInfo() { function(s, st) { window.setTimeout(getWifiInfo, 1000); }); } +//===== System info + +function showSystemInfo(data) { + Object.keys(data).forEach(function(v) { + el = $("#system-" + v); + if (el != null) { + if (el.nodeName === "INPUT") el.value = data[v]; + else el.innerHTML = data[v]; + } + }); + $("#system-spinner").setAttribute("hidden", ""); + $("#system-table").removeAttribute("hidden"); + currAp = data.ssid; +} + +function getSystemInfo() { + ajaxJson('GET', "/system/info", showSystemInfo, + function(s, st) { window.setTimeout(getSystemInfo, 1000); }); +} + +function enableInput(el) { + el.disabled = false; + el.select(); + return false; +} +function submitInput(klass, id, v) { + console.log("Submit POST /"+klass+"/update?"+id+"="+v); + $("#"+klass+"-"+id).disabled = true; + ajaxSpin("POST", "/"+klass+"/update?"+id+"="+v, function() { + showNotification(id + " changed to " + v); + }, function() { + showWarning(id + " change failed"); + }); + return false; +} +function makeAjaxInput(klass, field) { + var el = $("#"+klass+"-"+field); + bnd(el.parentElement, "click", function(){return enableInput(el);}); + bnd(el, "blur", function(){return submitInput(klass,field,el.value);}); + bnd(el, "keyup", function(ev){ + if ((ev||window.event).keyCode==13) return submitInput(klass,field,el.value); + }); +} + + //===== Notifications function showWarning(text) { diff --git a/httpd/httpd.c b/httpd/httpd.c index e0345d7..c5815a6 100644 --- a/httpd/httpd.c +++ b/httpd/httpd.c @@ -17,6 +17,8 @@ Esp8266 http server - core routines #include #include "httpd.h" +#define HTTPD_DBG + //Max length of request head #define MAX_HEAD_LEN 1024 @@ -394,9 +396,13 @@ static void ICACHE_FLASH_ATTR httpdProcessRequest(HttpdConnData *conn) { if (conn->post) conn->post->len = 0; // skip any remaining receives return; } - else if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) { + else { + if (!(r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED)) { + os_printf("%shandler for %s returned invalid result %d\n", connStr, conn->url, r); + } //URL doesn't want to handle the request: either the data isn't found or there's no //need to generate a login screen. + conn->cgi = NULL; // force lookup again i++; //look at next url the next iteration of the loop. } }