server-side handling of MQTT web page

pull/47/head
Thorsten von Eicken 9 years ago
parent d698b94ac6
commit c1ed3695a9
  1. 52
      esp-link/cgi.c
  2. 3
      esp-link/cgi.h
  3. 64
      esp-link/cgimqtt.c
  4. 10
      html/mqtt.html
  5. 23
      html/ui.js
  6. 2
      httpd/httpd.c
  7. 14
      serial/serbridge.c
  8. 19
      serial/slip.c
  9. 6
      serial/slip.h

@ -18,16 +18,64 @@ Some random cgi routines.
#include "cgi.h" #include "cgi.h"
#include "espfs.h" #include "espfs.h"
void ICACHE_FLASH_ATTR void noCacheHeaders(HttpdConnData *connData, int code) {
jsonHeader(HttpdConnData *connData, int code) {
httpdStartResponse(connData, code); httpdStartResponse(connData, code);
httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate"); httpdHeader(connData, "Cache-Control", "no-cache, no-store, must-revalidate");
httpdHeader(connData, "Pragma", "no-cache"); httpdHeader(connData, "Pragma", "no-cache");
httpdHeader(connData, "Expires", "0"); httpdHeader(connData, "Expires", "0");
}
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
noCacheHeaders(connData, code);
httpdHeader(connData, "Content-Type", "application/json"); httpdHeader(connData, "Content-Type", "application/json");
httpdEndHeaders(connData); httpdEndHeaders(connData);
} }
void ICACHE_FLASH_ATTR
errorResponse(HttpdConnData *connData, int code, char *message) {
noCacheHeaders(connData, code);
httpdEndHeaders(connData);
httpdSend(connData, message, -1);
os_printf("HTTP %d error response: \"%s\"\n", code, message);
}
// look for the HTTP arg 'name' and store it at 'config' with max length 'max_len' (incl
// terminating zero), returns -1 on error, 0 if not found, 1 if found and OK
int ICACHE_FLASH_ATTR
getStringArg(HttpdConnData *connData, char *name, char *config, int max_len) {
char buff[128];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip
if (len >= max_len) {
os_sprintf(buff, "Value for %s too long (%d > %d allowed)", name, len, max_len-1);
errorResponse(connData, 400, buff);
return -1;
}
strcpy(config, buff);
return 1;
}
int ICACHE_FLASH_ATTR
getBoolArg(HttpdConnData *connData, char *name, bool*config) {
char buff[64];
int len = httpdFindArg(connData->getArgs, name, buff, sizeof(buff));
if (len < 0) return 0; // not found, skip
if (strcmp(buff, "1") == 0 || strcmp(buff, "true") == 0) {
*config = true;
return 1;
}
if (strcmp(buff, "0") == 0 || strcmp(buff, "false") == 0) {
*config = false;
return 1;
}
os_sprintf(buff, "Invalid value for %s", name);
errorResponse(connData, 400, buff);
return -1;
}
#define TOKEN(x) (os_strcmp(token, x) == 0) #define TOKEN(x) (os_strcmp(token, x) == 0)
#if 0 #if 0
// Handle system information variables and print their value, returns the number of // Handle system information variables and print their value, returns the number of

@ -4,6 +4,9 @@
#include "httpd.h" #include "httpd.h"
void jsonHeader(HttpdConnData *connData, int code); void jsonHeader(HttpdConnData *connData, int code);
void errorResponse(HttpdConnData *connData, int code, char *message);
int getStringArg(HttpdConnData *connData, char *name, char *config, int max_len);
int getBoolArg(HttpdConnData *connData, char *name, bool*config);
int cgiMenu(HttpdConnData *connData); int cgiMenu(HttpdConnData *connData);
#endif #endif

@ -38,34 +38,56 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) {
int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) { int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE; if (connData->conn==NULL) return HTTPD_CGI_DONE;
#if 0 // handle MQTT server settings
// Handle tcp_enable flag int mqtt_server = 0; // accumulator for changes/errors
char buff[128]; mqtt_server |= getStringArg(connData, "mqtt-host",
int len = httpdFindArg(connData->getArgs, "tcp_enable", buff, sizeof(buff)); flashConfig.mqtt_hostname, sizeof(flashConfig.mqtt_hostname));
if (len <= 0) { if (mqtt_server < 0) return HTTPD_CGI_DONE;
jsonHeader(connData, 400); mqtt_server |= getStringArg(connData, "mqtt-client-id",
flashConfig.mqtt_client, sizeof(flashConfig.mqtt_client));
if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getStringArg(connData, "mqtt-username",
flashConfig.mqtt_username, sizeof(flashConfig.mqtt_username));
if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getStringArg(connData, "mqtt-password",
flashConfig.mqtt_password, sizeof(flashConfig.mqtt_password));
if (mqtt_server < 0) return HTTPD_CGI_DONE;
mqtt_server |= getBoolArg(connData, "mqtt-enable",
&flashConfig.mqtt_enable);
// handle mqtt port
char buff[16];
if (httpdFindArg(connData->getArgs, "mqtt-port", buff, sizeof(buff)) > 0) {
int32_t port = atoi(buff);
if (port > 0 && port < 65536) {
flashConfig.mqtt_port = port;
mqtt_server |= 1;
} else {
errorResponse(connData, 400, "Invalid MQTT port");
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} }
flashConfig.tcp_enable = os_strcmp(buff, "true") == 0; }
// Handle rssi_enable flag // if server setting changed, we need to "make it so"
len = httpdFindArg(connData->getArgs, "rssi_enable", buff, sizeof(buff)); if (mqtt_server) {
if (len <= 0) { os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable);
jsonHeader(connData, 400); // TODO
return HTTPD_CGI_DONE;
} }
flashConfig.rssi_enable = os_strcmp(buff, "true") == 0;
// Handle api_key flag // no action required if mqtt status settings change, they just get picked up at the
len = httpdFindArg(connData->getArgs, "api_key", buff, sizeof(buff)); // next status tick
if (len < 0) { if (getBoolArg(connData, "mqtt-status-enable", &flashConfig.mqtt_status_enable) < 0)
jsonHeader(connData, 400);
return HTTPD_CGI_DONE; return HTTPD_CGI_DONE;
} if (getStringArg(connData, "mqtt-status-topic",
buff[sizeof(flashConfig.api_key)-1] = 0; // ensure we don't get an overrun flashConfig.mqtt_status_topic, sizeof(flashConfig.mqtt_status_topic)) < 0)
os_strcpy(flashConfig.api_key, buff); return HTTPD_CGI_DONE;
#endif
// if SLIP-enable is toggled it gets picked-up immediately by the parser
int slip_update = getBoolArg(connData, "slip-enable", &flashConfig.slip_enable);
if (slip_update < 0) return HTTPD_CGI_DONE;
if (slip_update > 0) os_printf("SLIP-enable changed: %d\n", flashConfig.slip_enable);
os_printf("Saving config\n");
if (configSave()) { if (configSave()) {
httpdStartResponse(connData, 200); httpdStartResponse(connData, 200);
httpdEndHeaders(connData); httpdEndHeaders(connData);

@ -71,18 +71,17 @@
<div class="pure-form-stacked"> <div class="pure-form-stacked">
<label>Topic prefix</label> <label>Topic prefix</label>
<input type="text" name="mqtt-status-topic"/> <input type="text" name="mqtt-status-topic"/>
Suffixes: rssi, heap-free, ...
</div> </div>
<button id="mqtt-status-button" type="submit" class="pure-button button-primary">
Update status settings!
</button>
</form> </form>
</div> </div>
<div class="card"> <div class="card">
<h1>REST</h1> <h1>REST</h1>
<p>REST requests are enabled as soon as SLIP is enabled. <p>REST requests are enabled as soon as SLIP is enabled.
There are no REST-specific settings.</p> There are no REST-specific settings.</p>
<!-- div id="rest-spinner" class="spinner spinner-small"></div>
<div class="form-horizontal">
<input type="checkbox" name="tcp-enable"/>
<label>Enable REST client</label>
</div -->
</div> </div>
</div> </div>
</div> </div>
@ -94,6 +93,7 @@
onLoad(function() { onLoad(function() {
fetchMqtt(); fetchMqtt();
bnd($("#mqtt-form"), "submit", changeMqtt); bnd($("#mqtt-form"), "submit", changeMqtt);
bnd($("#mqtt-status-form"), "submit", changeMqttStatus);
}); });
</script> </script>
</body></html> </body></html>

@ -399,7 +399,7 @@ function fetchTcpClient() {
function changeMqtt(e) { function changeMqtt(e) {
e.preventDefault(); e.preventDefault();
var url = "mqtt?1=1"; var url = "mqtt?1=1";
var i, inputs = $("input"); var i, inputs = document.querySelectorAll('#mqtt-form input');
for (i=0; i<inputs.length; i++) { for (i=0; i<inputs.length; i++) {
if (inputs[i].type != "checkbox") if (inputs[i].type != "checkbox")
url += "&" + inputs[i].name + "=" + inputs[i].value; url += "&" + inputs[i].name + "=" + inputs[i].value;
@ -409,12 +409,12 @@ function changeMqtt(e) {
var cb = $("#mqtt-button"); var cb = $("#mqtt-button");
addClass(cb, 'pure-button-disabled'); addClass(cb, 'pure-button-disabled');
ajaxSpin("POST", url, function(resp) { ajaxSpin("POST", url, function(resp) {
showNotification("MQTT updated");
removeClass(cb, 'pure-button-disabled'); removeClass(cb, 'pure-button-disabled');
fetchMqtt();
}, function(s, st) { }, function(s, st) {
showWarning("Error: "+st); showWarning("Error: "+st);
removeClass(cb, 'pure-button-disabled'); removeClass(cb, 'pure-button-disabled');
fetchMqtt(); window.setTimeout(fetchMqtt, 100);
}); });
} }
@ -450,13 +450,24 @@ function fetchMqtt() {
}); });
} }
function changeMqttStatus(e) {
e.preventDefault();
var v = document.querySelector('input[name="mqtt-status-topic"]').value;
ajaxSpin("POST", "/mqtt?mqtt-status-topic=" + v, function() {
showNotification("MQTT status settings updated");
}, function(s, st) {
showWarning("Error: "+st);
window.setTimeout(fetchMqtt, 100);
});
}
function setMqtt(name, v) { function setMqtt(name, v) {
ajaxSpin("POST", "/mqtt?" + name + "=" + (v ? 1 : 0), function() { ajaxSpin("POST", "/mqtt?" + name + "=" + (v ? 1 : 0), function() {
showNotification(name + " is now " + (v ? "enabled" : "disabled")); var n = name.replace("-enable", "");
showNotification(n + " is now " + (v ? "enabled" : "disabled"));
}, function() { }, function() {
showNotification("Enable/disable failed"); showWarning("Enable/disable failed");
window.setTimeout(fetchMqtt, 100); window.setTimeout(fetchMqtt, 100);
}); });
} }

@ -191,7 +191,7 @@ int ICACHE_FLASH_ATTR httpdFindArg(char *line, char *arg, char *buff, int buffLe
p=(char*)os_strstr(p, "&"); p=(char*)os_strstr(p, "&");
if (p!=NULL) p+=1; if (p!=NULL) p+=1;
} }
os_printf("Finding %s in %s: Not found :/\n", arg, line); //os_printf("Finding %s in %s: Not found :/\n", arg, line);
return -1; //not found return -1; //not found
} }

@ -14,6 +14,7 @@
#include "serled.h" #include "serled.h"
#include "config.h" #include "config.h"
#include "console.h" #include "console.h"
#include "slip.h"
#include "cmd.h" #include "cmd.h"
static struct espconn serbridgeConn; static struct espconn serbridgeConn;
@ -258,6 +259,19 @@ console_process(char *buf, short len) {
} }
} }
// callback with a buffer of characters that have arrived on the uart
void ICACHE_FLASH_ATTR
serbridgeUartCb(char *buf, short length) {
if (!flashConfig.slip_enable || slip_disabled > 0) {
//os_printf("SLIP: disabled got %d\n", length);
console_process(buf, length);
} else {
slip_parse_buf(buf, length);
}
serledFlash(50); // short blink on serial LED
}
//callback after the data are sent //callback after the data are sent
static void ICACHE_FLASH_ATTR static void ICACHE_FLASH_ATTR
serbridgeSentCb(void *arg) { serbridgeSentCb(void *arg) {

@ -4,11 +4,10 @@
#include "uart.h" #include "uart.h"
#include "crc16.h" #include "crc16.h"
#include "serbridge.h" #include "serbridge.h"
#include "serled.h"
#include "console.h" #include "console.h"
#include "cmd.h" #include "cmd.h"
uint8_t slip_disabled; // disable slip to allow flashing of attached MCU uint8_t slip_disabled; // temporarily disable slip to allow flashing of attached MCU
extern void ICACHE_FLASH_ATTR console_process(char *buf, short len); extern void ICACHE_FLASH_ATTR console_process(char *buf, short len);
@ -115,18 +114,7 @@ slip_parse_char(char c) {
// callback with a buffer of characters that have arrived on the uart // callback with a buffer of characters that have arrived on the uart
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
serbridgeUartCb(char *buf, short length) { slip_parse_buf(char *buf, short length) {
if (slip_disabled > 0) {
//os_printf("SLIP: disabled got %d\n", length);
console_process(buf, length);
for (short i=0; i<length; i++)
if (buf[i] == SLIP_START) {
os_printf("SLIP: START while disabled=%d\n", slip_disabled);
break;
}
return;
}
// do SLIP parsing // do SLIP parsing
for (short i=0; i<length; i++) for (short i=0; i<length; i++)
slip_parse_char(buf[i]); slip_parse_char(buf[i]);
@ -136,6 +124,5 @@ serbridgeUartCb(char *buf, short length) {
slip_process(); slip_process();
slip_reset(); slip_reset();
} }
serledFlash(50); // short blink on serial LED
} }

@ -0,0 +1,6 @@
#ifndef SLIP_H
#define SLIP_H
void slip_parse_buf(char *buf, short length);
#endif
Loading…
Cancel
Save