added no-cache headers; shrunk favicon; minimal support for static ip & hostname

pull/25/head
Thorsten von Eicken 10 years ago
parent 228a3ff0f0
commit d679340035
  1. 3
      Makefile
  2. 40
      html/console.tpl
  3. BIN
      html/favicon.ico
  4. 6
      html/style.css
  5. 41
      html/ui.js
  6. 46
      html/wifi/wifi.tpl
  7. 12
      httpd/httpd.c
  8. 15
      serial/console.c
  9. 4
      user/cgi.c
  10. 113
      user/cgiwifi.c
  11. 1
      user/cgiwifi.h
  12. 2
      user/log.c
  13. 28
      user/user_main.c

@ -199,12 +199,13 @@ echo_version:
$(TARGET_OUT): $(APP_AR) $(LD_SCRIPT)
$(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
@echo Dump: $(OBJDP) -x $(TARGET_OUT)
# $(OBJDP) -x $(TARGET_OUT) | egrep '(espfs_img)'
$(USER1_OUT): $(APP_AR) $(LD_SCRIPT1)
$(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) -T$(LD_SCRIPT1) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@
@echo Dump : $(OBJDP) -x $(USER1_OUT)
@echo Disass: $(OBJDP) -d -l -x $(USER1_OUT)
# $(Q) $(OBJDP) -x $(TARGET_OUT) | egrep espfs_img
$(USER2_OUT): $(APP_AR) $(LD_SCRIPT2)

@ -5,14 +5,12 @@
<div class="content">
<p>The Microcontroller console shows the last 1024 characters
received from UART0, to which a microcontroller is typically attached.</p>
received from UART0, to which a microcontroller is typically attached.
The UART is configured for 8 bits, no parity, 1 stop bit (8N1).</p>
<p>
<a id="reset-button" class="pure-button button-primary" href="#">Reset µC</a>
&nbsp;Baud:
<a id="57600-button" href="#" class="pure-button">57600</a>
<a id="115200-button" href="#" class="pure-button">115200</a>
<a id="230400-button" href="#" class="pure-button">230400</a>
<a id="460800-button" href="#" class="pure-button">460800</a>
<span id="baud-btns"></span>
</p>
<pre class="console" id="console"></pre>
</div>
@ -23,11 +21,26 @@
<script type="text/javascript">console_url = "/console/text"</script>
<script src="console.js"></script>
<script type="text/javascript">
var rates = [57600, 115200, 230400, 460800];
function showRate(rate) {
rates.forEach(function(r) {
var el = $("#"+r+"-button");
el.className = el.className.replace(" button-selected", "");
});
var el = $("#"+rate+"-button");
if (el != null) el.className += " button-selected";
}
function baudButton(baud) {
$("#baud-btns").appendChild(m(
' <a id="'+baud+'-button" href="#" class="pure-button">'+baud+'</a>'));
$("#"+baud+"-button").addEventListener("click", function(e) {
e.preventDefault();
ajaxSpin('GET', "/console/baud?rate="+baud,
function(resp) { showNotification("" + baud + " baud set"); },
ajaxSpin('POST', "/console/baud?rate="+baud,
function(resp) { showNotification("" + baud + " baud set"); showRate(baud); },
function(s, st) { showWarning("Error setting baud rate: ", st); }
);
});
@ -39,15 +52,18 @@
$("#reset-button").addEventListener("click", function(e) {
e.preventDefault();
$("#console").innerHTML = "";
ajaxSpin('GET', "/console/reset",
ajaxSpin('POST', "/console/reset",
function(resp) { showNotification("uC reset"); },
function(s, st) { showWarning("Error resetting uC"); }
);
});
baudButton(57600);
baudButton(115200);
baudButton(230400);
baudButton(460800);
rates.forEach(function(r) { baudButton(r); });
ajaxJson('GET', "/console/baud",
function(data) { showRate(data.rate); },
function(s, st) { showNotification(st); }
);
}
</script>
</body></html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 766 B

@ -122,9 +122,15 @@ div.tt {
color: #888;
}
form button {
margin-top: 0.5em;
}
.button-primary {
background-color: #99f;
}
.button-selected {
background-color: #fc6;
}
/* Text console */
pre.console {

@ -10,31 +10,29 @@
if (v != null) { v.innerHTML = version; }
}());
function addClass(el, cl) {
el.className += ' ' + cl;
}
function removeClass(el, cl) {
var cls = el.className.split(/\s+/),
l = cls.length;
for (var i=0; i<l; i++) {
if (cls[i] === cl) cls.splice(i, 1);
}
el.className = cls.join(' ');
return cls.length != l
}
function toggleClass(el, cl) {
if (!removeClass(el, cl)) addClass(el, cl);
}
(function (window, document) {
var layout = document.getElementById('layout'),
menu = document.getElementById('menu'),
menuLink = document.getElementById('menuLink');
function toggleClass(element, className) {
var classes = element.className.split(/\s+/),
length = classes.length,
i = 0;
for(; i < length; i++) {
if (classes[i] === className) {
classes.splice(i, 1);
break;
}
}
// The className is not found
if (length === classes.length) {
classes.push(className);
}
element.className = classes.join(' ');
}
menuLink.onclick = function (e) {
var active = 'active';
@ -51,7 +49,10 @@
function showWifiInfo(data) {
Object.keys(data).forEach(function(v) {
el = $("#wifi-" + v);
if (el != null) el.innerHTML = data[v];
if (el != null) {
if (el.nodeName === "INPUT") el.value = data[v];
else el.innerHTML = data[v];
}
});
$("#wifi-spinner").setAttribute("hidden", "");
$("#wifi-table").removeAttribute("hidden");

@ -3,7 +3,8 @@
<h1>Wifi Configuration</h1>
</div>
<div class="content pure-g">
<div class="content">
<div class="pure-g">
<div class="pure-u-12-24"><div class="card">
<h1>Wifi State</h2>
<div id="wifi-spinner" class="spinner spinner-small"></div>
@ -22,7 +23,6 @@
<h1>Wifi Association</h2>
<p id="reconnect" style="color: #600" hidden></p>
<form action="#" id="wifiform" class="pure-form pure-form-stacked">
<!--form name="wifiform" action="connect.cgi" method="post"-->
<legend>To connect to a WiFi network, please select one of the detected networks,
enter the password, and hit the connect button...</legend>
<label>Network SSID</label>
@ -33,6 +33,25 @@
</form>
</div></div>
</div>
<div class="pure-g">
<div class="pure-u-12-24"><div class="card">
<h1>Special Settings</h2>
<form action="#" id="specform" class="pure-form pure-form-stacked">
<legend>Special settings, use with care! If the Static IP field is empty
then DHCP will be used, else DHCP will be off.</legend>
<label>Hostname used when requesting DHCP lease</label>
<input id="wifi-hostname" type="text" name="hostname">
<label>Static IP address, blank to use DHCP</label>
<input id="wifi-staticip" type="text" name="staticip">
<label>Netmask (for static IP)</label>
<input id="wifi-netmask" type="text" name="netmask">
<label>Gateway (for static IP)</label>
<input id="wifi-gateway" type="text" name="gateway">
<button id="special-button" type="submit" class="pure-button button-primary">Change!</button>
</form>
</div></div>
</div>
</div>
</div>
</div>
@ -184,7 +203,6 @@ function changeWifiAp(e) {
e.preventDefault();
var passwd = $("#wifi-passwd").value;
var essid = getSelectedEssid();
console.log("Posting form", "essid=" + essid, "pwd="+passwd);
showNotification("Connecting to " + essid);
var url = "connect?essid="+encodeURIComponent(essid)+"&passwd="+encodeURIComponent(passwd);
@ -207,9 +225,31 @@ function changeWifiAp(e) {
});
}
function changeSpecial(e) {
e.preventDefault();
var url = "special";
url += "?hostname=" + encodeURIComponent($("#wifi-hostname").value);
url += "&staticip=" + encodeURIComponent($("#wifi-staticip").value);
url += "&netmask=" + encodeURIComponent($("#wifi-netmask").value);
url += "&gateway=" + encodeURIComponent($("#wifi-gateway").value);
hideWarning();
var cb = $("#special-button");
addClass(cb, 'pure-button-disabled');
ajaxSpin("POST", url, function(resp) {
removeClass(cb, 'pure-button-disabled');
getWifiInfo();
}, function(s, st) {
showWarning("Error: "+st);
removeClass(cb, 'pure-button-disabled');
getWifiInfo();
});
}
window.onload=function(e) {
getWifiInfo();
$("#wifiform").onsubmit = changeWifiAp;
$("#specform").onsubmit = changeSpecial;
scanTimeout = window.setTimeout(scanAPs, 500);
};
</script>

@ -120,7 +120,7 @@ static HttpdConnData ICACHE_FLASH_ATTR *httpdFindConnData(void *arg) {
static void ICACHE_FLASH_ATTR httpdRetireConn(HttpdConnData *conn) {
uint32 dt = conn->startTime;
if (dt > 0) dt = (system_get_time() - dt)/1000;
os_printf("%s Closed, took %ums, heap=%ld\n", connStr, dt,
os_printf("%s Closed, %ums, heap=%ld\n", connStr, dt,
(unsigned long)system_get_free_heap_size());
if (conn->post->buff!=NULL) os_free(conn->post->buff);
conn->post->buff=NULL;
@ -405,8 +405,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 %s\n", connStr,
conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url);
// Count number of open connections
int open = 0;
for (int j=0; j<MAX_CONN; j++) if (connData[j].conn != NULL) open++;
os_printf("%s %s %s (%d conn open)\n", connStr,
conn->requestType == HTTPD_METHOD_GET ? "GET" : "POST", conn->url, open);
//Parse out the URL part before the GET parameters.
conn->getArgs=(char*)os_strstr(conn->url, "?");
if (conn->getArgs!=0) {
@ -540,9 +544,11 @@ static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) {
return;
}
#if 0
int num = 0;
for (int j=0; j<MAX_CONN; j++) if (connData[j].conn != NULL) num++;
os_printf("%s Connect (%d open)\n", connStr, num+1);
#endif
connData[i].priv=&connPrivData[i];
connData[i].conn=conn;

@ -5,6 +5,7 @@
#include "cgi.h"
#include "uart.h"
#include "serbridge.h"
#include "config.h"
#include "console.h"
// Microcontroller console capturing the last 1024 characters received on the uart so
@ -55,18 +56,24 @@ ajaxConsoleReset(HttpdConnData *connData) {
int ICACHE_FLASH_ATTR
ajaxConsoleBaud(HttpdConnData *connData) {
char buff[2048];
int len;
char buff[512];
int len, status = 400;
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;
flashConfig.baud_rate = rate;
status = configSave() ? 200 : 400;
}
} else if (connData->requestType == HTTPD_METHOD_GET) {
status = 200;
}
jsonHeader(connData, 400);
jsonHeader(connData, status);
os_sprintf(buff, "{\"rate\": %ld}", flashConfig.baud_rate);
httpdSend(connData, buff, -1);
return HTTPD_CGI_DONE;
}

@ -21,13 +21,15 @@ Some random cgi routines.
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0");
httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData);
}
#define TOKEN(x) (os_strcmp(token, x) == 0)
#if 0
// Handle system information variables and print their value, returns the number of
// characters appended to buff
int ICACHE_FLASH_ATTR printGlobalInfo(char *buff, int buflen, char *token) {

@ -18,6 +18,7 @@ Cgi/template routines for the /wifi url.
#include "cgiwifi.h"
#include "cgi.h"
#include "status.h"
#include "config.h"
#include "log.h"
//Enable this to disallow any changes in AP settings
@ -289,10 +290,7 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
char essid[128];
char passwd[128];
if (connData->conn==NULL) {
//Connection aborted. Clean up.
return HTTPD_CGI_DONE;
}
if (connData->conn==NULL) return HTTPD_CGI_DONE;
int el = httpdFindArg(connData->getArgs, "essid", essid, sizeof(essid));
int pl = httpdFindArg(connData->getArgs, "passwd", passwd, sizeof(passwd));
@ -317,6 +315,104 @@ int ICACHE_FLASH_ATTR cgiWiFiConnect(HttpdConnData *connData) {
return HTTPD_CGI_DONE;
}
static bool parse_ip(char *buff, ip_addr_t *ip_ptr) {
char *next = buff; // where to start parsing next integer
int found = 0; // number of integers parsed
uint32_t ip = 0; // the ip addres parsed
for (int i=0; i<32; i++) { // 32 is just a safety limit
char c = buff[i];
if (c == '.' || c == 0) {
// parse the preceding integer and accumulate into IP address
bool last = c == 0;
buff[i] = 0;
uint32_t v = atoi(next);
ip = ip | ((v&0xff)<<(found*8));
next = buff+i+1; // next integer starts after the '.'
found++;
if (last) { // if at end of string we better got 4 integers
ip_ptr->addr = ip;
return found == 4;
}
continue;
}
if (c < '0' || c > '9') return false;
}
return false;
}
#define DEBUGIP
#ifdef DEBUGIP
static void ICACHE_FLASH_ATTR debugIP() {
struct ip_info info;
if (wifi_get_ip_info(0, &info)) {
os_printf("\"ip\": \"%d.%d.%d.%d\"\n", IP2STR(&info.ip.addr));
os_printf("\"netmask\": \"%d.%d.%d.%d\"\n", IP2STR(&info.netmask.addr));
os_printf("\"gateway\": \"%d.%d.%d.%d\"\n", IP2STR(&info.gw.addr));
os_printf("\"hostname\": \"%s\"", flashConfig.hostname);
} else {
os_printf("\"ip\": \"-none-\"\n");
}
}
#endif
// Change special settings
int ICACHE_FLASH_ATTR cgiWiFiSpecial(HttpdConnData *connData) {
char hostname[32];
char staticip[32];
char netmask[32];
char gateway[32];
if (connData->conn==NULL) return HTTPD_CGI_DONE;
// get args and their string lengths
int hl = httpdFindArg(connData->getArgs, "hostname", hostname, sizeof(hostname));
int sl = httpdFindArg(connData->getArgs, "staticip", staticip, sizeof(staticip));
int nl = httpdFindArg(connData->getArgs, "netmask", netmask, sizeof(netmask));
int gl = httpdFindArg(connData->getArgs, "gateway", gateway, sizeof(gateway));
if (hl >= 0 && sl >= 0 && nl >= 0 && gl >= 0) {
if (sl > 0) {
// static IP overrides hostname (HDCP stuff)
wifi_station_dhcpc_stop();
struct ip_info ipi;
bool ok = parse_ip(staticip, &ipi.ip);
if (nl > 0) ok = ok && parse_ip(netmask, &ipi.netmask);
else IP4_ADDR(&ipi.netmask, 255, 255, 255, 0);
if (gl > 0) ok = ok && parse_ip(gateway, &ipi.gw);
else ipi.gw.addr = 0;
if (ok) {
os_printf("Setting static IP: %s\n", staticip);
ok = wifi_set_ip_info(0, &ipi);
if (ok) os_printf("Static IP set: %s\n", staticip);
#ifdef DEBUGIP
debugIP();
#endif
jsonHeader(connData, ok ? 200: 400);
return HTTPD_CGI_DONE;
}
} else {
// no static IP, set hostname
if (hl == 0) os_strcpy(hostname, "esp-link");
if (wifi_station_dhcpc_status() == DHCP_STARTED)
wifi_station_dhcpc_stop();
bool hok = wifi_station_set_hostname(hostname);
if (hok) {
os_strcpy(flashConfig.hostname, hostname);
hok = hok && configSave();
}
hok = hok && wifi_station_dhcpc_start();
if (hok) os_printf("DHCP hostname set: %s\n", hostname);
jsonHeader(connData, hok ? 200 : 400);
if (!hok) httpdSend(connData, "Error setting hostname or starting DHCP", -1);
return HTTPD_CGI_DONE;
}
}
jsonHeader(connData, 400);
httpdSend(connData, "Cannot parse hostname or staticip", -1);
return HTTPD_CGI_DONE;
}
//This cgi changes the operating mode: STA / AP / STA+AP
int ICACHE_FLASH_ATTR cgiWiFiSetMode(HttpdConnData *connData) {
int len;
@ -386,9 +482,10 @@ int ICACHE_FLASH_ATTR printWifiInfo(char *buff) {
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);
len += os_sprintf(buff+len, ", \"ip\": \"%d.%d.%d.%d\"", IP2STR(&info.ip.addr));
len += os_sprintf(buff+len, ", \"netmask\": \"%d.%d.%d.%d\"", IP2STR(&info.netmask.addr));
len += os_sprintf(buff+len, ", \"gateway\": \"%d.%d.%d.%d\"", IP2STR(&info.gw.addr));
len += os_sprintf(buff+len, ", \"hostname\": \"%s\"", flashConfig.hostname);
} else {
len += os_sprintf(buff+len, ", \"ip\": \"-none-\"");
}
@ -449,7 +546,7 @@ int ICACHE_FLASH_ATTR cgiWifiInfo(HttpdConnData *connData) {
// 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");
wifi_station_set_hostname(flashConfig.hostname);
int x = wifi_get_opmode() & 0x3;
os_printf("Wifi init, mode=%s\n", wifiMode[x]);
wifi_set_phy_mode(2);

@ -11,6 +11,7 @@ int cgiWiFi(HttpdConnData *connData);
int cgiWiFiConnect(HttpdConnData *connData);
int cgiWiFiSetMode(HttpdConnData *connData);
int cgiWiFiConnStatus(HttpdConnData *connData);
int cgiWiFiSpecial(HttpdConnData *connData);
void wifiInit(void);
#endif

@ -20,9 +20,11 @@ static bool log_newline; // at start of a new line
void ICACHE_FLASH_ATTR
log_uart(bool enable) {
if (!enable && !log_no_uart) {
#if 0
os_printf("Turning OFF uart log\n");
os_delay_us(4*1000L); // time for uart to flush
log_no_uart = !enable;
#endif
} else if (enable && log_no_uart) {
log_no_uart = !enable;
os_printf("Turning ON uart log\n");

@ -26,8 +26,6 @@
#include "console.h"
#include "config.h"
#include "log.h"
#define MCU_RESET 12
#define MCU_ISP 13
#include <gpio.h>
//#define SHOW_HEAP_USE
@ -88,6 +86,7 @@ HttpdBuiltInUrl builtInUrls[]={
{"/wifi/connect", cgiWiFiConnect, NULL},
{"/wifi/connstatus", cgiWiFiConnStatus, NULL},
{"/wifi/setmode", cgiWiFiSetMode, NULL},
{"/wifi/special", cgiWiFiSpecial, NULL},
{"/pins", cgiPins, NULL},
{"*", cgiEspFsHook, NULL}, //Catch-all cgi function for the filesystem
@ -113,31 +112,32 @@ static char *rst_codes[] = {
"normal", "wdt reset", "exception", "soft wdt", "restart", "deep sleep", "???",
};
# define VERS_STR_STR(V) #V
# define VERS_STR(V) VERS_STR_STR(V)
char *esp_link_version = VERS_STR(VERSION);
//Main routine. Initialize stdout, the I/O, filesystem and the webserver and we're done.
void user_init(void) {
// init gpio pins used to reset&reprogram attached microcontrollers
// get the flash config so we know how to init things
//configWipe(); // uncomment to reset the config for testing purposes
bool restoreOk = configRestore();
// init gpio pin registers
gpio_init();
// put MCU into reset in case it interferes with serial-programming of the esp8266
//GPIO_OUTPUT_SET(MCU_RESET, 0);
// init UART
uart_init(BIT_RATE_115200, BIT_RATE_115200);
uart_init(flashConfig.baud_rate, 115200);
logInit(); // must come after init of uart
// say hello (leave some time to cause break in TX after boot loader's msg
os_delay_us(10000L);
# define VERS_STR_STR(V) #V
# define VERS_STR(V) VERS_STR_STR(V)
os_printf("\n\nInitializing esp-link\n" VERS_STR(VERSION) "\n");
//configWipe();
if (configRestore()) os_printf("Flash config restored\n");
else os_printf("*** Flash config restore failed, using defaults ***\n");
os_printf("\n\n** %s\n", esp_link_version);
os_printf("Flash config restore %s\n", restoreOk ? "ok" : "*FAILED*");
// Status LEDs
statusInit();
serledInit();
logInit();
// Wifi
wifiInit();
// init the flash filesystem with the html stuff
EspFsInitResult res = espFsInit(&_binary_espfs_img_start);
os_printf("espFsInit(0x%08lx) returned %d\n", (uint32_t)&_binary_espfs_img_start, res);
os_printf("espFsInit %s\n", res?"ok":"ERR");
// mount the http handlers
httpdInit(builtInUrls, 80);
// init the wifi-serial transparent bridge (port 23)

Loading…
Cancel
Save