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. 66
      esp-link/cgimqtt.c
  4. 10
      html/mqtt.html
  5. 83
      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 "espfs.h"
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
void noCacheHeaders(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");
}
void ICACHE_FLASH_ATTR
jsonHeader(HttpdConnData *connData, int code) {
noCacheHeaders(connData, code);
httpdHeader(connData, "Content-Type", "application/json");
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)
#if 0
// Handle system information variables and print their value, returns the number of

@ -4,6 +4,9 @@
#include "httpd.h"
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);
#endif

@ -38,34 +38,56 @@ int ICACHE_FLASH_ATTR cgiMqttGet(HttpdConnData *connData) {
int ICACHE_FLASH_ATTR cgiMqttSet(HttpdConnData *connData) {
if (connData->conn==NULL) return HTTPD_CGI_DONE;
#if 0
// Handle tcp_enable flag
char buff[128];
int len = httpdFindArg(connData->getArgs, "tcp_enable", buff, sizeof(buff));
if (len <= 0) {
jsonHeader(connData, 400);
return HTTPD_CGI_DONE;
// handle MQTT server settings
int mqtt_server = 0; // accumulator for changes/errors
mqtt_server |= getStringArg(connData, "mqtt-host",
flashConfig.mqtt_hostname, sizeof(flashConfig.mqtt_hostname));
if (mqtt_server < 0) return HTTPD_CGI_DONE;
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;
}
}
flashConfig.tcp_enable = os_strcmp(buff, "true") == 0;
// Handle rssi_enable flag
len = httpdFindArg(connData->getArgs, "rssi_enable", buff, sizeof(buff));
if (len <= 0) {
jsonHeader(connData, 400);
return HTTPD_CGI_DONE;
// if server setting changed, we need to "make it so"
if (mqtt_server) {
os_printf("MQTT server settings changed, enable=%d\n", flashConfig.mqtt_enable);
// TODO
}
flashConfig.rssi_enable = os_strcmp(buff, "true") == 0;
// Handle api_key flag
len = httpdFindArg(connData->getArgs, "api_key", buff, sizeof(buff));
if (len < 0) {
jsonHeader(connData, 400);
// no action required if mqtt status settings change, they just get picked up at the
// next status tick
if (getBoolArg(connData, "mqtt-status-enable", &flashConfig.mqtt_status_enable) < 0)
return HTTPD_CGI_DONE;
}
buff[sizeof(flashConfig.api_key)-1] = 0; // ensure we don't get an overrun
os_strcpy(flashConfig.api_key, buff);
#endif
if (getStringArg(connData, "mqtt-status-topic",
flashConfig.mqtt_status_topic, sizeof(flashConfig.mqtt_status_topic)) < 0)
return HTTPD_CGI_DONE;
// 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()) {
httpdStartResponse(connData, 200);
httpdEndHeaders(connData);

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

@ -316,44 +316,44 @@ function createInputForPin(pin) {
input.type = "radio";
input.name = "pins";
input.data = pin.name;
input.className = "pin-input";
input.className = "pin-input";
input.value= pin.value;
input.id = "opt-" + pin.value;
if (currPin == pin.name) input.checked = "1";
var descr = m('<label for="opt-'+pin.value+'"><b>'+pin.name+":</b>"+pin.descr+"</label>");
var div = document.createElement("div");
div.appendChild(input);
div.appendChild(descr);
return div;
var descr = m('<label for="opt-'+pin.value+'"><b>'+pin.name+":</b>"+pin.descr+"</label>");
var div = document.createElement("div");
div.appendChild(input);
div.appendChild(descr);
return div;
}
function displayPins(resp) {
var po = $("#pin-mux");
po.innerHTML = "";
currPin = resp.curr;
resp.map.forEach(function(v) {
po.appendChild(createInputForPin(v));
});
var i, inputs = $(".pin-input");
for (i=0; i<inputs.length; i++) {
inputs[i].onclick = function() { setPins(this.value, this.data) };
};
var po = $("#pin-mux");
po.innerHTML = "";
currPin = resp.curr;
resp.map.forEach(function(v) {
po.appendChild(createInputForPin(v));
});
var i, inputs = $(".pin-input");
for (i=0; i<inputs.length; i++) {
inputs[i].onclick = function() { setPins(this.value, this.data) };
};
}
function fetchPins() {
ajaxJson("GET", "/pins", displayPins, function() {
window.setTimeout(fetchPins, 1000);
});
window.setTimeout(fetchPins, 1000);
});
}
function setPins(v, name) {
ajaxSpin("POST", "/pins?map="+v, function() {
showNotification("Pin assignment changed to " + name);
}, function() {
showNotification("Pin assignment change failed");
window.setTimeout(fetchPins, 100);
});
showNotification("Pin assignment changed to " + name);
}, function() {
showNotification("Pin assignment change failed");
window.setTimeout(fetchPins, 100);
});
}
//===== TCP client card
@ -390,8 +390,8 @@ function displayTcpClient(resp) {
function fetchTcpClient() {
ajaxJson("GET", "/tcpclient", displayTcpClient, function() {
window.setTimeout(fetchTcpClient, 1000);
});
window.setTimeout(fetchTcpClient, 1000);
});
}
//===== MQTT cards
@ -399,7 +399,7 @@ function fetchTcpClient() {
function changeMqtt(e) {
e.preventDefault();
var url = "mqtt?1=1";
var i, inputs = $("input");
var i, inputs = document.querySelectorAll('#mqtt-form input');
for (i=0; i<inputs.length; i++) {
if (inputs[i].type != "checkbox")
url += "&" + inputs[i].name + "=" + inputs[i].value;
@ -409,12 +409,12 @@ function changeMqtt(e) {
var cb = $("#mqtt-button");
addClass(cb, 'pure-button-disabled');
ajaxSpin("POST", url, function(resp) {
showNotification("MQTT updated");
removeClass(cb, 'pure-button-disabled');
fetchMqtt();
}, function(s, st) {
showWarning("Error: "+st);
removeClass(cb, 'pure-button-disabled');
fetchMqtt();
window.setTimeout(fetchMqtt, 100);
});
}
@ -446,17 +446,28 @@ function displayMqtt(data) {
function fetchMqtt() {
ajaxJson("GET", "/mqtt", displayMqtt, function() {
window.setTimeout(fetchMqtt, 1000);
});
window.setTimeout(fetchMqtt, 1000);
});
}
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) {
ajaxSpin("POST", "/mqtt?" + name + "=" + (v ? 1 : 0), function() {
showNotification(name + " is now " + (v ? "enabled" : "disabled"));
}, function() {
showNotification("Enable/disable failed");
window.setTimeout(fetchMqtt, 100);
});
var n = name.replace("-enable", "");
showNotification(n + " is now " + (v ? "enabled" : "disabled"));
}, function() {
showWarning("Enable/disable failed");
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, "&");
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
}

@ -14,6 +14,7 @@
#include "serled.h"
#include "config.h"
#include "console.h"
#include "slip.h"
#include "cmd.h"
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
static void ICACHE_FLASH_ATTR
serbridgeSentCb(void *arg) {

@ -4,11 +4,10 @@
#include "uart.h"
#include "crc16.h"
#include "serbridge.h"
#include "serled.h"
#include "console.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);
@ -115,18 +114,7 @@ slip_parse_char(char c) {
// callback with a buffer of characters that have arrived on the uart
void ICACHE_FLASH_ATTR
serbridgeUartCb(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;
}
slip_parse_buf(char *buf, short length) {
// do SLIP parsing
for (short i=0; i<length; i++)
slip_parse_char(buf[i]);
@ -136,6 +124,5 @@ serbridgeUartCb(char *buf, short length) {
slip_process();
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