Browse Source

Refactor websocket sending

fastled
Xose Pérez 7 years ago
parent
commit
44da6178f4
7 changed files with 2725 additions and 2736 deletions
  1. +2
    -0
      code/espurna/config/general.h
  2. BIN
      code/espurna/data/index.html.gz
  3. +2578
    -2575
      code/espurna/static/index.html.gz.h
  4. +3
    -0
      code/espurna/wifi.ino
  5. +98
    -127
      code/espurna/ws.ino
  6. +40
    -26
      code/html/custom.js
  7. +4
    -8
      code/html/index.html

+ 2
- 0
code/espurna/config/general.h View File

@ -495,6 +495,8 @@ PROGMEM const char* const custom_reset_string[] = {
#define SETTINGS_AUTOSAVE 1 // Autosave settings o force manual commit
#endif
#define SETTINGS_MAX_LIST_COUNT 10 // Maximum index for settings lists
// -----------------------------------------------------------------------------
// LIGHT
// -----------------------------------------------------------------------------


BIN
code/espurna/data/index.html.gz View File


+ 2578
- 2575
code/espurna/static/index.html.gz.h
File diff suppressed because it is too large
View File


+ 3
- 0
code/espurna/wifi.ino View File

@ -84,6 +84,9 @@ void wifiConfigure() {
if (!systemCheck()) return;
#endif
// Clean settings
wifiClean(WIFI_MAX_NETWORKS);
int i;
for (i = 0; i< WIFI_MAX_NETWORKS; i++) {
if (getSetting("ssid" + String(i)).length() == 0) break;


+ 98
- 127
code/espurna/ws.ino View File

@ -33,6 +33,44 @@ void _wsMQTTCallback(unsigned int type, const char * topic, const char * payload
}
#endif
bool _wsStore(String key, String value) {
// HTTP port
if (key == "webPort") {
if ((value.toInt() == 0) || (value.toInt() == 80)) {
return delSetting(key);
}
}
if (value != getSetting(key)) {
return setSetting(key, value);
}
return false;
}
bool _wsStore(String key, JsonArray& value) {
bool changed = false;
unsigned char index = 0;
for (auto element : (JsonArray&) value) {
if (_wsStore(key + index, element.as<String>())) changed = true;
index++;
}
// Delete further values
for (unsigned char i=index; i<SETTINGS_MAX_LIST_COUNT; i++) {
if (!delSetting(key, index)) break;
changed = true;
}
if (changed) Serial.println(key);
return changed;
}
void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
//DEBUG_MSG_P(PSTR("[WEBSOCKET] Parsing: %s\n"), length ? (char*) payload : "");
@ -93,64 +131,39 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
// Check configuration -----------------------------------------------------
if (root.containsKey("config") && root["config"].is<JsonArray&>()) {
if (root.containsKey("config") && root["config"].is<JsonObject&>()) {
JsonArray& config = root["config"];
JsonObject& config = root["config"];
DEBUG_MSG_P(PSTR("[WEBSOCKET] Parsing configuration data\n"));
unsigned char webMode = WEB_MODE_NORMAL;
String adminPass;
bool save = false;
bool changed = false;
#if MQTT_SUPPORT
bool changedMQTT = false;
#endif
unsigned int wifiIdx = 0;
unsigned int dczRelayIdx = 0;
unsigned int mqttGroupIdx = 0;
String adminPass;
for (unsigned int i=0; i<config.size(); i++) {
for (auto kv: config) {
String key = config[i]["name"];
String value = config[i]["value"];
// Skip firmware filename
if (key.equals("filename")) continue;
// -----------------------------------------------------------------
// GENERAL
// -----------------------------------------------------------------
// Web mode (normal or password)
if (key == "webMode") {
webMode = value.toInt();
continue;
}
// HTTP port
if (key == "webPort") {
if ((value.toInt() == 0) || (value.toInt() == 80)) {
save = changed = true;
delSetting(key);
continue;
}
}
bool changed = false;
String key = kv.key;
JsonVariant& value = kv.value;
// Check password
if (key == "adminPass1") {
adminPass = value;
continue;
}
if (key == "adminPass2") {
if (!value.equals(adminPass)) {
if (key == "adminPass") {
if (!value.is<JsonArray&>()) continue;
JsonArray& values = value.as<JsonArray&>();
if (values.size() != 2) continue;
if (values[0].as<String>().equals(values[1].as<String>())) {
String password = values[0].as<String>();
if (password.length() > 0) {
setSetting(key, password);
save = true;
}
wsSend_P(client_id, PSTR("{\"action\": \"reload\"}"));
} else {
wsSend_P(client_id, PSTR("{\"message\": 7}"));
return;
}
if (value.length() == 0) continue;
wsSend_P(client_id, PSTR("{\"action\": \"reload\"}"));
key = String("adminPass");
continue;
}
// -----------------------------------------------------------------
@ -159,103 +172,66 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
#if POWER_PROVIDER != POWER_PROVIDER_NONE
double expected;
if (key == "pwrExpectedP") {
powerCalibrate(POWER_MAGNITUDE_ACTIVE, value.toFloat());
changed = true;
if (expected = value.as<double>()) {
powerCalibrate(POWER_MAGNITUDE_ACTIVE, expected);
save = true;
}
delSetting(key);
continue;
}
if (key == "pwrExpectedV") {
powerCalibrate(POWER_MAGNITUDE_VOLTAGE, value.toFloat());
changed = true;
if (expected = value.as<double>()) {
powerCalibrate(POWER_MAGNITUDE_VOLTAGE, expected);
save = true;
}
delSetting(key);
continue;
}
if (key == "pwrExpectedC") {
powerCalibrate(POWER_MAGNITUDE_CURRENT, value.toFloat());
changed = true;
if (expected = value.as<double>()) {
powerCalibrate(POWER_MAGNITUDE_CURRENT, expected);
save = true;
}
delSetting(key);
continue;
}
if (key == "pwrExpectedF") {
powerCalibrate(POWER_MAGNITUDE_POWER_FACTOR, value.toFloat());
changed = true;
if (expected = value.as<double>()) {
powerCalibrate(POWER_MAGNITUDE_POWER_FACTOR, expected);
save = true;
}
delSetting(key);
continue;
}
if (key == "pwrResetCalibration") {
if (value.toInt() == 1) {
if (value.as<bool>()) {
powerResetCalibration();
changed = true;
save = true;
Serial.println(key);
}
delSetting(key);
continue;
}
#endif
// -----------------------------------------------------------------
// DOMOTICZ
// -----------------------------------------------------------------
#if DOMOTICZ_SUPPORT
if (key == "dczRelayIdx") {
if (dczRelayIdx >= relayCount()) continue;
key = key + String(dczRelayIdx);
++dczRelayIdx;
}
#else
if (key.startsWith("dcz")) continue;
#endif
// -----------------------------------------------------------------
// MQTT GROUP TOPICS
// -----------------------------------------------------------------
#if MQTT_SUPPORT
if (key == "mqttGroup") {
key = key + String(mqttGroupIdx);
}
if (key == "mqttGroupInv") {
key = key + String(mqttGroupIdx);
++mqttGroupIdx;
}
#endif
// -----------------------------------------------------------------
// WIFI
// -----------------------------------------------------------------
if (key == "ssid") {
key = key + String(wifiIdx);
}
if (key == "pass") {
key = key + String(wifiIdx);
}
if (key == "ip") {
key = key + String(wifiIdx);
}
if (key == "gw") {
key = key + String(wifiIdx);
}
if (key == "mask") {
key = key + String(wifiIdx);
}
if (key == "dns") {
key = key + String(wifiIdx);
++wifiIdx;
// Store values
if (value.is<JsonArray&>()) {
if (_wsStore(key, value.as<JsonArray&>())) changed = true;
} else {
if (_wsStore(key, value.as<String>())) changed = true;
}
// -----------------------------------------------------------------
if (value != getSetting(key)) {
setSetting(key, value);
save = changed = true;
// Update flags if value has changed
if (changed) {
save = true;
#if MQTT_SUPPORT
if (key.startsWith("mqtt")) changedMQTT = true;
#endif
@ -263,10 +239,6 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
}
if (webMode == WEB_MODE_NORMAL) {
if (wifiClean(wifiIdx)) save = changed = true;
}
// Save settings
if (save) {
@ -275,9 +247,9 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
(_ws_on_after_parse_callbacks[i])();
}
// This should got to callback as well
// but first change management has to be in place
#if MQTT_SUPPORT
// This should got to callback as well
// but first change management has to be in place
#if MQTT_SUPPORT
if (changedMQTT) {
mqttConfigure();
mqttDisconnect();
@ -287,13 +259,12 @@ void _wsParse(AsyncWebSocketClient *client, uint8_t * payload, size_t length) {
// Persist settings
saveSettings();
}
if (changed) {
wsSend_P(client_id, PSTR("{\"message\": 8}"));
} else {
wsSend_P(client_id, PSTR("{\"message\": 9}"));
}
}


+ 40
- 26
code/html/custom.js View File

@ -46,13 +46,13 @@ function zeroPad(number, positions) {
function validateForm(form) {
// password
var adminPass1 = $("input[name='adminPass1']", form).val();
var adminPass1 = $("input[name='adminPass']", form).first().val();
if (adminPass1.length > 0 && !checkPassword(adminPass1)) {
alert("The password you have entered is not valid, it must have at least 5 characters, 1 lowercase and 1 uppercase or number!");
return false;
}
var adminPass2 = $("input[name='adminPass2']", form).val();
var adminPass2 = $("input[name='adminPass']", form).last().val();
if (adminPass1 != adminPass2) {
alert("Passwords are different!");
return false;
@ -62,14 +62,40 @@ function validateForm(form) {
}
function valueSet(data, name, value) {
for (var i in data) {
if (data[i]['name'] == name) {
data[i]['value'] = value;
return;
// These fields will always be a list of values
var is_group = ["ssid", "pass", "gw", "mask", "ip", "dns", "mqttGroup", "mqttGroupInv", "dczRelayIdx", "ledMode", "ntpServer", "adminPass"];
function getData(form) {
var data = {};
// Populate data
$("input,select", form).each(function() {
var name = $(this).attr("name");
if (name) {
if ($(this).attr('type') == 'checkbox') {
value = $(this).is(':checked') ? 1 : 0;
} else if ($(this).attr('type') == 'radio') {
if (!$(this).is(':checked')) return;
value = $(this).val();
} else {
value = $(this).val();
}
if (name in data) {
data[name].push(value);
} else if (is_group.indexOf(name) >= 0) {
data[name] = [value];
} else {
data[name] = value;
}
}
}
data.push({'name': name, 'value': value});
});
// Delete unwanted fields
delete(data["filename"]);
return data;
}
function randomString(length, chars) {
@ -112,28 +138,19 @@ function doReload(milliseconds) {
function doUpdate() {
var form = $("#formSave");
if (validateForm(form)) {
// Get data
var data = form.serializeArray();
// Post-process
delete(data['filename']);
$("input[type='checkbox']").each(function() {
var name = $(this).attr("name");
if (name) {
valueSet(data, name, $(this).is(':checked') ? 1 : 0);
}
});
var data = getData(form);
websock.send(JSON.stringify({'config': data}));
// Empty special fields
$(".pwrExpected").val(0);
$("input[name='pwrResetCalibration']")
.prop("checked", false)
.iphoneStyle("refresh");
// Change handling
numChanged = 0;
setTimeout(function() {
@ -219,7 +236,7 @@ function doUpgrade() {
function doUpdatePassword() {
var form = $("#formPassword");
if (validateForm(form)) {
var data = form.serializeArray();
var data = getData(form);
websock.send(JSON.stringify({'config': data}));
}
return false;
@ -862,10 +879,7 @@ function hasChanged() {
}
function resetOriginals() {
$("input").each(function() {
$(this).attr("original", $(this).val());
})
$("select").each(function() {
$("input,select").each(function() {
$(this).attr("original", $(this).val());
})
numReboot = numReconnect = numReload = 0;


+ 4
- 8
code/html/index.html View File

@ -26,8 +26,6 @@
<form id="formPassword" class="pure-form" action="/" method="post">
<input class="pure-u-1 pure-u-sm-3-4" type="hidden" name="webMode" value="1" />
<div class="panel block">
<div class="header">
@ -41,7 +39,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4">Admin password</label>
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="1" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="1" autocomplete="false" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br />
@ -50,7 +48,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4">Admin password (repeat)</label>
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="2" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-md-3-4" type="password" tabindex="2" autocomplete="false" />
</div>
<button class="pure-button button-update-password">Update</button>
@ -289,8 +287,6 @@
<form id="formSave" class="pure-form" action="/" method="post" enctype="multipart/form-data">
<input class="pure-u-1 pure-u-sm-3-4" type="hidden" name="webMode" value="0" />
<div class="panel" id="panel-general">
<div class="header">
@ -534,7 +530,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4">Admin password</label>
<input name="adminPass1" class="pure-u-1 pure-u-md-3-4" type="password" action="reboot" tabindex="11" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-md-3-4" type="password" action="reboot" tabindex="11" autocomplete="false" />
<div class="pure-u-0 pure-u-md-1-4">&nbsp;</div>
<div class="pure-u-1 pure-u-md-3-4 hint">
The administrator password is used to access this web interface (user 'admin'), but also to connect to the device when in AP mode or to flash a new firmware over-the-air (OTA).<br />
@ -543,7 +539,7 @@
<div class="pure-g">
<label class="pure-u-1 pure-u-md-1-4">Repeat password</label>
<input name="adminPass2" class="pure-u-1 pure-u-md-3-4" type="password" action="reboot" tabindex="12" autocomplete="false" />
<input name="adminPass" class="pure-u-1 pure-u-md-3-4" type="password" action="reboot" tabindex="12" autocomplete="false" />
</div>
<div class="pure-g">


Loading…
Cancel
Save