+
-  
+  
@@ -1387,8 +1386,10 @@
socket.onopen = function () {
setInterval(ping, 15000);
- getTrack();
- getCoverimage();
+ socket.send('{"settings":{}}'); // request settings
+ socket.send('{"ssids":{}}'); // request SSIDs
+ socket.send('{"trackinfo":{}}'); // get current track
+ socket.send('{"coverimg":{}}'); // get cover image
};
socket.onclose = function (e) {
@@ -1450,21 +1451,123 @@
}
} if ("coverimg" in socketMsg) {
document.getElementById('coverimg').src = "/cover?" + new Date().getTime();
- }
+ } if ("settings" in socketMsg) {
+ fillSettings(socketMsg.settings);
+ }
};
}
- const wifiListSavedSSIDs = document.getElementById("wifiListSavedSSIDs");
- async function rebuildSSIDList() {
- let ssidList = await (await fetch("/savedSSIDs")).json();
- let ssidActiveObj = await (await fetch("/activeSSID")).json();
-
- console.log(ssidActiveObj);
- let ssidActive = ssidActiveObj.active;
+ async function fillSettings(settings) {
+ if (!settings) {
+ return false
+ }
+ // general
+ let genSettings = settings.general;
+ if (genSettings) {
+ $('#initialVolume').bootstrapSlider('setValue', genSettings.initVolume);
+ $('#maxVolumeSpeaker').bootstrapSlider('setValue', genSettings.maxVolumeSp);
+ $('#maxVolumeHeadphone').bootstrapSlider('setValue', genSettings.maxVolumeHp);
+ $('#inactivityTime').bootstrapSlider('setValue', genSettings.sleepInactivity);
+ }
+ // current values
+ let currSettings = settings.current;
+ if (currSettings) {
+ document.getElementById("rfidIdMusic").value = currSettings.rfidTagId;
+ volumeSlider.setValue(currSettings.volume);
+ }
+ // default (factory) settings
+ let defSettings = settings.defaults;
+ if (defSettings) {
+ $('#initialVolume').bootstrapSlider('setValue', defSettings.initVolume);
+ $('#maxVolumeSpeaker').bootstrapSlider('setValue', defSettings.maxVolumeSp);
+ $('#maxVolumeHeadphone').bootstrapSlider('setValue', defSettings.maxVolumeHp);
+ $('#inactivityTime').bootstrapSlider('setValue', defSettings.sleepInactivity);
+ $('#initBrightness').bootstrapSlider('setValue', defSettings.initBrightness);
+ $('#nightBrightness').bootstrapSlider('setValue', defSettings.nightBrightness);
+ $('#warningLowVoltage').bootstrapSlider('setValue', defSettings.warnLowVoltage);
+ $('#voltageIndicatorLow').bootstrapSlider('setValue', defSettings.indicatorLow);
+ $('#voltageIndicatorHigh').bootstrapSlider('setValue', defSettings.indicatorHi);
+ $('#voltageCheckInterval').bootstrapSlider('setValue', defSettings.voltageCheckInterval);
+ }
+ // wifi
+ let wifiSettings = settings.wifi;
+ if (wifiSettings) {
+ document.getElementById("hostname").value = wifiSettings.hostname;
+ document.getElementById("scan_wifi_on_start").checked = wifiSettings.scanOnStart;
+ }
+ // ssids
+ let ssidSettings = settings.ssids;
+ if (ssidSettings) {
+ rebuildSSIDList(ssidSettings);
+ }
+ // led
+ let ledSettings = settings.led;
+ if (ledSettings) {
+ document.getElementById('neopixelConfig').setAttribute('data-visible', true);
+ $('#initBrightness').bootstrapSlider('setValue', ledSettings.initBrightness);
+ $('#nightBrightness').bootstrapSlider('setValue', ledSettings.nightBrightness);
+ }
+ // battery
+ let batSettings = settings.battery;
+ if (batSettings) {
+ document.getElementById('batteryConfig').setAttribute('data-visible', true);
+ $('#warningLowVoltage').bootstrapSlider('setValue', batSettings.warnLowVoltage);
+ $('#voltageIndicatorLow').bootstrapSlider('setValue', batSettings.indicatorLow);
+ $('#voltageIndicatorHigh').bootstrapSlider('setValue', batSettings.indicatorHi);
+ $('#voltageCheckInterval').bootstrapSlider('setValue', batSettings.voltageCheckInterval);
+ }
+ // ftp
+ let ftpSettings = settings.ftp;
+ if (ftpSettings) {
+ document.getElementById('nav-ftp-tab').setAttribute('data-visible', true);
+ document.getElementById("ftpUser").value = ftpSettings.username;
+ document.getElementById("ftpUser").setAttribute('maxlength', ftpSettings.maxUserLength);
+ document.getElementById("ftpPwd").value = ftpSettings.password;
+ document.getElementById("ftpPwd").setAttribute('maxlength', ftpSettings.maxPwdLength);
+ }
+ // mqtt
+ let mqttSettings = settings.mqtt;
+ if (mqttSettings) {
+ // todo: get the bootstrap sliders to work:
+ document.getElementById('nav-mqtt-tab').setAttribute('data-visible', true);
+ document.getElementById('mqttEnable').checked = mqttSettings.enable;
+ document.getElementById('mqttClientId').value = mqttSettings.clientID;
+ document.getElementById('mqttClientId').setAttribute('maxlength', mqttSettings.maxClientIdLength);
+ document.getElementById('mqttServer').value = mqttSettings.server;
+ document.getElementById('mqttServer').setAttribute('maxlength', mqttSettings.maxServerLength);
+ document.getElementById('mqttUser').value = mqttSettings.username;
+ document.getElementById('mqttUser').setAttribute('maxlength', mqttSettings.maxUserLength);
+ document.getElementById('mqttPwd').value = mqttSettings.password;
+ document.getElementById('mqttPwd').setAttribute('maxlength', mqttSettings.maxPwdLength);
+ document.getElementById('mqttPort').value = mqttSettings.port;
+ }
+ // bluetooth
+ let btSettings = settings.bluetooth;
+ if (btSettings) {
+ document.getElementById('nav-bt-tab').setAttribute('data-visible', true);
+ document.getElementById('btDeviceName').value = btSettings.deviceName;
+ document.getElementById('btPinCode').value = btSettings.pinCode;
+ }
+ }
- console.log(ssidList);
- console.log(ssidActive);
+ async function resetSettings() {
+ let defaults = await (await fetch("/settings?section=defaults")).json();
+ fillSettings(defaults);
+ }
+ const wifiListSavedSSIDs = document.getElementById("wifiListSavedSSIDs");
+ async function rebuildSSIDList(data) {
+ var ssidList;
+ var ssidActive;
+ if (data) {
+ ssidList = data.savedSSIDs;
+ ssidActive = data.active;
+ } else {
+ ssidList = await (await fetch("/savedSSIDs")).json();
+ let ssidActiveObj = await (await fetch("/activeSSID")).json();
+ console.log(ssidActiveObj);
+ ssidActive = ssidActiveObj.active;
+ }
wifiListSavedSSIDs.innerHTML = "";
for (let ssid of ssidList) {
@@ -1497,27 +1600,7 @@
ssidElem.appendChild(deleteSpan);
wifiListSavedSSIDs.appendChild(ssidElem);
- }
- }
-
- async function updateWifiFields() {
- let hostnameElem = document.getElementById("hostname");
- let scanWifiElem = document.getElementById("scan_wifi_on_start");
-
- let config = await (await fetch("/wificonfig")).json();
-
- if (config.hostname && config.hostname !== "") {
- hostnameElem.value = config.hostname;
- hostnameElem.defaultValue = config.hostname;
- }
- scanWifiElem.checked = config.scanwifionstart;
- }
-
- function onWifiTabOpened() {
- console.log("wifi tab opened!")
- rebuildSSIDList();
-
- updateWifiFields();
+ }
}
async function deleteSSID(ssid) {
@@ -1528,20 +1611,6 @@
}
- const config = {attributes: true};
- const wifiTab = document.getElementById("nav-wifi-tab");
- var wifiTabWasActive = false;
- const wifiTabObserver = new MutationObserver((mutationList, observer) => {
- if (!wifiTabWasActive && wifiTab.classList.contains("active")) {
- wifiTabWasActive = true;
- onWifiTabOpened();
- } else {
- wifiTabWasActive = false;
- }
- })
- wifiTabObserver.observe(wifiTab, config);
-
-
function ping() {
var myObj = {
"ping": {
@@ -1559,41 +1628,22 @@
clearTimeout(tm);
}
- function getTrack() {
- var myObj = {
- "trackinfo": {
- trackinfo: 'trackinfo'
- }
- };
- var myJSON = JSON.stringify(myObj);
- socket.send(myJSON);
- }
-
- function getCoverimage() {
- var myObj = {
- "coverimg": {
- coverimg: 'coverimg'
- }
- };
- var myJSON = JSON.stringify(myObj);
- socket.send(myJSON);
- }
-
-
function genSettings(clickedId) {
lastIdclicked = clickedId;
var myObj = {
"general": {
- iVol: document.getElementById('initialVolume').value,
- mVolSpeaker: document.getElementById('maxVolumeSpeaker').value,
- mVolHeadphone: document.getElementById('maxVolumeHeadphone').value,
- iBright: document.getElementById('initBrightness').value,
- nBright: document.getElementById('nightBrightness').value,
- iTime: document.getElementById('inactivityTime').value,
- vWarning: document.getElementById('warningLowVoltage').value,
- vIndLow: document.getElementById('voltageIndicatorLow').value,
- vIndHi: document.getElementById('voltageIndicatorHigh').value,
- vInt: document.getElementById('voltageCheckInterval').value
+ initVolume: document.getElementById('initialVolume').value,
+ maxVolumeSp: document.getElementById('maxVolumeSpeaker').value,
+ maxVolumeHp: document.getElementById('maxVolumeHeadphone').value,
+ sleepInactivity: document.getElementById('inactivityTime').value},
+ "led": {
+ initBrightness: document.getElementById('initBrightness').value,
+ nightBrightness: document.getElementById('nightBrightness').value},
+ "battery": {
+ warnLowVoltage: document.getElementById('warningLowVoltage').value,
+ indicatorLow: document.getElementById('voltageIndicatorLow').value,
+ indicatorHi: document.getElementById('voltageIndicatorHigh').value,
+ voltageCheckInterval: document.getElementById('voltageCheckInterval').value
}
};
var myJSON = JSON.stringify(myObj);
@@ -1604,8 +1654,8 @@
lastIdclicked = clickedId;
var myObj = {
"ftp": {
- ftpUser: document.getElementById('ftpUser').value,
- ftpPwd: document.getElementById('ftpPwd').value
+ username: document.getElementById('ftpUser').value,
+ password: document.getElementById('ftpPwd').value
}
};
var myJSON = JSON.stringify(myObj);
@@ -1632,12 +1682,12 @@
}
var myObj = {
"mqtt": {
- mqttEnable: val,
- mqttClientId: document.getElementById('mqttClientId').value,
- mqttServer: document.getElementById('mqttServer').value,
- mqttUser: document.getElementById('mqttUser').value,
- mqttPwd: document.getElementById('mqttPwd').value,
- mqttPort: document.getElementById('mqttPort').value
+ enable: val,
+ clientID: document.getElementById('mqttClientId').value,
+ server: document.getElementById('mqttServer').value,
+ username: document.getElementById('mqttUser').value,
+ password: document.getElementById('mqttPwd').value,
+ port: document.getElementById('mqttPort').value
}
};
var myJSON = JSON.stringify(myObj);
@@ -1692,7 +1742,7 @@
var myObj = {
hostname: hostname,
- scanwifionstart: scanWifi
+ scanOnStart: scanWifi
};
await fetch("/wificonfig", {
diff --git a/processHtml.py b/processHtml.py
index cba9bbf1..0adc27c6 100644
--- a/processHtml.py
+++ b/processHtml.py
@@ -24,13 +24,12 @@
) # pylint: disable=undefined-variable
HTML_DIR = Path("html").absolute()
# List of files, which will only be minifed but not compressed (f.e. html files with templates)
-WWW_FILES = [
- Path("management.html"),
- Path("accesspoint.html"),
-]
+WWW_FILES = []
# list of all files, which shall be compressed before embedding
# files with ".json" ending will be minifed before compression, ".js" will not be changed!
BINARY_FILES =[
+ Path("management.html"),
+ Path("accesspoint.html"),
Path("js/i18next.min.js"),
Path("js/i18nextHttpBackend.min.js"),
Path("js/loc_i18next.min.js"),
diff --git a/src/Web.cpp b/src/Web.cpp
index 9338aaee..3d8b5ccb 100644
--- a/src/Web.cpp
+++ b/src/Web.cpp
@@ -28,8 +28,6 @@
#include "Rfid.h"
#include "HallEffectSensor.h"
-#include "HTMLaccesspoint.h"
-#include "HTMLmanagement.h"
#include "HTMLbinary.h"
typedef struct {
@@ -73,11 +71,15 @@ static void handleGetWiFiConfig(AsyncWebServerRequest *request);
static void handlePostWiFiConfig(AsyncWebServerRequest *request, JsonVariant &json);
static void handleCoverImageRequest(AsyncWebServerRequest *request);
static void handleWiFiScanRequest(AsyncWebServerRequest *request);
+static void handleGetSettings(AsyncWebServerRequest *request);
+static void handlePostSettings(AsyncWebServerRequest *request, JsonVariant &json);
+
static bool Web_DumpNvsToSd(const char *_namespace, const char *_destFile);
static void onWebsocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
-static String templateProcessor(const String &templ);
+static void settingsToJSON(JsonObject obj, String section);
+static bool JSONToSettings(JsonObject obj);
static void webserverStart(void);
// If PSRAM is available use it allocate memory for JSON-objects
@@ -205,8 +207,10 @@ void Web_Init(void) {
const bool etag = false;
if (etag)
response = request->beginResponse(304);
- else
- response = request->beginResponse_P(200, "text/html", accesspoint_HTML);
+ else {
+ response = request->beginResponse_P(200, "text/html", (const uint8_t *)accesspoint_BIN, sizeof(accesspoint_BIN));
+ response->addHeader("Content-Encoding", "gzip");
+ }
// response->addHeader("Cache-Control", "public, max-age=31536000, immutable");
// response->addHeader("ETag", gitRevShort); // use git revision as digest
request->send(response);
@@ -311,9 +315,11 @@ void webserverStart(void) {
response = request->beginResponse(304);
else {
if (gFSystem.exists("/.html/index.htm"))
- response = request->beginResponse(gFSystem, "/.html/index.htm", String(), false, templateProcessor);
- else
- response = request->beginResponse_P(200, "text/html", management_HTML, templateProcessor);
+ response = request->beginResponse(gFSystem, "/.html/index.htm", String(), false);
+ else {
+ response = request->beginResponse_P(200, "text/html", (const uint8_t *)management_BIN, sizeof(management_BIN));
+ response->addHeader("Content-Encoding", "gzip");
+ }
}
// response->addHeader("Cache-Control", "public, max-age=31536000, immutable");
// response->addHeader("ETag", gitRevShort); // use git revision as digest
@@ -504,7 +510,10 @@ void webserverStart(void) {
};
request->redirect("https://espuino.de/espuino/favicon.ico");
});
- // Init HallEffectSensor Value
+ // ESPuino settings
+ wServer.on("/settings", HTTP_GET, handleGetSettings);
+ wServer.addHandler(new AsyncCallbackJsonWebHandler("/settings", handlePostSettings));
+ // Init HallEffectSensor Value
#ifdef HALLEFFECT_SENSOR_ENABLE
wServer.on("/inithalleffectsensor", HTTP_GET, [](AsyncWebServerRequest *request) {
bool bres = gHallEffectSensor.saveActualFieldValue2NVS();
@@ -524,194 +533,64 @@ void webserverStart(void) {
}
}
-// Used for substitution of some variables/templates of html-files. Is called by webserver's template-engine
-String templateProcessor(const String &templ) {
- if (templ == "FTP_USER") {
- return gPrefsSettings.getString("ftpuser", "-1");
- } else if (templ == "FTP_PWD") {
- return gPrefsSettings.getString("ftppassword", "-1");
- } else if (templ == "FTP_USER_LENGTH") {
- return String(ftpUserLength - 1);
- } else if (templ == "FTP_PWD_LENGTH") {
- return String(ftpPasswordLength - 1);
- } else if (templ == "SHOW_FTP_TAB") { // Only show FTP-tab if FTP-support was compiled
- #ifdef FTP_ENABLE
- return "true";
- #else
- return "false";
- #endif
- } else if (templ == "SHOW_BLUETOOTH_TAB") { // Only show Bluetooth-tab if Bluetooth-support was compiled
- #ifdef BLUETOOTH_ENABLE
- return "true";
- #else
- return "false";
- #endif
- } else if (templ == "INIT_LED_BRIGHTNESS") {
- return String(gPrefsSettings.getUChar("iLedBrightness", 0));
- } else if (templ == "NIGHT_LED_BRIGHTNESS") {
- return String(gPrefsSettings.getUChar("nLedBrightness", 0));
- } else if (templ == "MAX_INACTIVITY") {
- return String(gPrefsSettings.getUInt("mInactiviyT", 0));
- } else if (templ == "INIT_VOLUME") {
- return String(gPrefsSettings.getUInt("initVolume", 0));
- } else if (templ == "CURRENT_VOLUME") {
- return String(AudioPlayer_GetCurrentVolume());
- } else if (templ == "MAX_VOLUME_SPEAKER") {
- return String(gPrefsSettings.getUInt("maxVolumeSp", 0));
- } else if (templ == "MAX_VOLUME_HEADPHONE") {
- return String(gPrefsSettings.getUInt("maxVolumeHp", 0));
-#ifdef BATTERY_MEASURE_ENABLE
- #ifdef MEASURE_BATTERY_VOLTAGE
- } else if (templ == "WARNING_LOW_VOLTAGE") {
- return String(gPrefsSettings.getFloat("wLowVoltage", warningLowVoltage));
- } else if (templ == "VOLTAGE_INDICATOR_LOW") {
- return String(gPrefsSettings.getFloat("vIndicatorLow", voltageIndicatorLow));
- } else if (templ == "VOLTAGE_INDICATOR_HIGH") {
- return String(gPrefsSettings.getFloat("vIndicatorHigh", voltageIndicatorHigh));
- #endif
- #ifdef MEASURE_BATTERY_OTHER // placeholder
- } else if (templ == "todo") {
- return "todo";
- #endif
- } else if (templ == "BATTERY_CHECK_INTERVAL") {
- return String(gPrefsSettings.getUInt("vCheckIntv", batteryCheckInterval));
-#else
- // TODO: hide battery config
-#endif
- } else if (templ == "MQTT_CLIENTID") {
- if (gPrefsSettings.isKey("mqttClientId")) {
- return gPrefsSettings.getString("mqttClientId", "-1");
- } else {
- return "-1";
- }
- } else if (templ == "MQTT_SERVER") {
- if (gPrefsSettings.isKey("mqttServer")) {
- return gPrefsSettings.getString("mqttServer", "-1");
- } else {
- return "-1";
- }
- } else if (templ == "SHOW_MQTT_TAB") { // Only show MQTT-tab if MQTT-support was compiled
- #ifdef MQTT_ENABLE
- return "true";
- #else
- return "false";
- #endif
- } else if (templ == "MQTT_ENABLE") {
- if (Mqtt_IsEnabled()) {
- return "checked=\"checked\"";
- } else {
- return String();
- }
- } else if (templ == "MQTT_USER") {
- if (gPrefsSettings.isKey("mqttUser")) {
- return gPrefsSettings.getString("mqttUser", "-1");
- } else {
- return "-1";
- }
- } else if (templ == "MQTT_PWD") {
- if (gPrefsSettings.isKey("mqttPassword")) {
- return gPrefsSettings.getString("mqttPassword", "-1");
- } else {
- return "-1";
- }
- } else if (templ == "MQTT_USER_LENGTH") {
- return String(mqttUserLength - 1);
- } else if (templ == "MQTT_PWD_LENGTH") {
- return String(mqttPasswordLength - 1);
- } else if (templ == "MQTT_CLIENTID_LENGTH") {
- return String(mqttClientIdLength - 1);
- } else if (templ == "MQTT_SERVER_LENGTH") {
- return String(mqttServerLength - 1);
- } else if (templ == "MQTT_PORT") {
-#ifdef MQTT_ENABLE
- return String(gMqttPort);
-#endif
- } else if (templ == "BT_DEVICE_NAME") {
- if (gPrefsSettings.isKey("btDeviceName")) {
- return gPrefsSettings.getString("btDeviceName", "");
- }
- } else if (templ == "BT_PIN_CODE") {
- if (gPrefsSettings.isKey("btPinCode")) {
- return gPrefsSettings.getString("btPinCode", "");
- }
- } else if (templ == "IPv4") {
- return WiFi.localIP().toString();
- } else if (templ == "RFID_TAG_ID") {
- return String(gCurrentRfidTagId);
- } else if (templ == "HOSTNAME") {
- return Wlan_GetHostname();
- }
-
- return String();
-}
-// Takes inputs from webgui, parses JSON and saves values in NVS
-// If operation was successful (NVS-write is verified) true is returned
-bool processJsonRequest(char *_serialJson) {
- if (!_serialJson) {
+// process JSON to settings
+bool JSONToSettings(JsonObject doc) {
+ if (!doc) {
+ Log_Println("JSONToSettings: doc unassigned", LOGLEVEL_DEBUG);
return false;
}
- #ifdef BOARD_HAS_PSRAM
- SpiRamJsonDocument doc(1000);
- #else
- StaticJsonDocument<1000> doc;
- #endif
-
- DeserializationError error = deserializeJson(doc, _serialJson);
-
- if (error) {
- Log_Printf(LOGLEVEL_ERROR, jsonErrorMsg, error.c_str());
- return false;
+ if (doc.containsKey("general")) {
+ // general settings
+ if (gPrefsSettings.putUInt("initVolume", doc["general"]["initVolume"].as
()) == 0 ||
+ gPrefsSettings.putUInt("maxVolumeSp", doc["general"]["maxVolumeSp"].as()) == 0 ||
+ gPrefsSettings.putUInt("maxVolumeHp", doc["general"]["maxVolumeHp"].as()) == 0 ||
+ gPrefsSettings.putUInt("mInactiviyT", doc["general"]["sleepInactivity"].as()) == 0 ) {
+ Log_Println("Failed to save general settings", LOGLEVEL_ERROR);
+ return false;
+ }
}
-
- JsonObject object = doc.as();
-
- if (doc.containsKey("general")) {
- uint8_t iVol = doc["general"]["iVol"].as();
- uint8_t mVolSpeaker = doc["general"]["mVolSpeaker"].as();
- uint8_t mVolHeadphone = doc["general"]["mVolHeadphone"].as();
- uint8_t iBright = doc["general"]["iBright"].as();
- uint8_t nBright = doc["general"]["nBright"].as();
- uint8_t iTime = doc["general"]["iTime"].as();
- float vWarning = doc["general"]["vWarning"].as();
- float vIndLow = doc["general"]["vIndLow"].as();
- float vIndHi = doc["general"]["vIndHi"].as();
- uint8_t vInt = doc["general"]["vInt"].as();
-
- gPrefsSettings.putUInt("initVolume", iVol);
- gPrefsSettings.putUInt("maxVolumeSp", mVolSpeaker);
- gPrefsSettings.putUInt("maxVolumeHp", mVolHeadphone);
- gPrefsSettings.putUChar("iLedBrightness", iBright);
- gPrefsSettings.putUChar("nLedBrightness", nBright);
- gPrefsSettings.putUInt("mInactiviyT", iTime);
- gPrefsSettings.putFloat("wLowVoltage", vWarning);
- gPrefsSettings.putFloat("vIndicatorLow", vIndLow);
- gPrefsSettings.putFloat("vIndicatorHigh", vIndHi);
- gPrefsSettings.putUInt("vCheckIntv", vInt);
-
- // Check if settings were written successfully
- if (gPrefsSettings.getUInt("initVolume", 0) != iVol ||
- gPrefsSettings.getUInt("maxVolumeSp", 0) != mVolSpeaker ||
- gPrefsSettings.getUInt("maxVolumeHp", 0) != mVolHeadphone ||
- gPrefsSettings.getUChar("iLedBrightness", 0) != iBright ||
- gPrefsSettings.getUChar("nLedBrightness", 0) != nBright ||
- gPrefsSettings.getUInt("mInactiviyT", 0) != iTime ||
- gPrefsSettings.getFloat("wLowVoltage", 999.99) != vWarning ||
- gPrefsSettings.getFloat("vIndicatorLow", 999.99) != vIndLow ||
- gPrefsSettings.getFloat("vIndicatorHigh", 999.99) != vIndHi ||
- gPrefsSettings.getUInt("vCheckIntv", 17777) != vInt) {
+ if (doc.containsKey("wifi")) {
+ // WiFi settings
+ static String hostName = doc["wifi"]["hostname"];
+ if (!Wlan_ValidateHostname(hostName)) {
+ Log_Println("Invalid hostname", LOGLEVEL_ERROR);
+ return false;
+ }
+ if (((!Wlan_SetHostname(hostName)) || gPrefsSettings.putBool("ScanWiFiOnStart", doc["wifi"]["scanOnStart"].as()) == 0)) {
+ Log_Println("Failed to save wifi settings", LOGLEVEL_ERROR);
return false;
}
+ }
+ if (doc.containsKey("led")) {
+ // Neopixel settings
+ if (gPrefsSettings.putUInt("iLedBrightness", doc["led"]["initBrightness"].as()) == 0 ||
+ gPrefsSettings.putUInt("nLedBrightness", doc["led"]["nightBrightness"].as()) == 0 ) {
+ Log_Println("Failed to save LED settings", LOGLEVEL_ERROR);
+ return false;
+ }
+ }
+ if (doc.containsKey("battery")) {
+ // Battery settings
+ if (gPrefsSettings.putFloat("wLowVoltage", doc["battery"]["warnLowVoltage"].as()) == 0 ||
+ gPrefsSettings.putFloat("vIndicatorLow", doc["battery"]["indicatorLow"].as()) == 0 ||
+ gPrefsSettings.putFloat("vIndicatorHigh", doc["battery"]["indicatorHi"].as()) == 0 ||
+ gPrefsSettings.putUInt("vCheckIntv", doc["battery"]["voltageCheckInterval"].as()) == 0 ) {
+ Log_Println("Failed to save battery settings", LOGLEVEL_ERROR);
+ return false;
+ }
Battery_Init();
- } else if (doc.containsKey("ftp")) {
- const char *_ftpUser = doc["ftp"]["ftpUser"];
- const char *_ftpPwd = doc["ftp"]["ftpPwd"];
+ }
+ if (doc.containsKey("ftp")) {
+ const char *_ftpUser = doc["ftp"]["username"];
+ const char *_ftpPwd = doc["ftp"]["password"];
gPrefsSettings.putString("ftpuser", (String)_ftpUser);
gPrefsSettings.putString("ftppassword", (String)_ftpPwd);
-
+ // Check if settings were written successfully
if (!(String(_ftpUser).equals(gPrefsSettings.getString("ftpuser", "-1")) ||
String(_ftpPwd).equals(gPrefsSettings.getString("ftppassword", "-1")))) {
+ Log_Println("Failed to save ftp settings", LOGLEVEL_ERROR);
return false;
}
} else if (doc.containsKey("ftpStatus")) {
@@ -719,13 +598,14 @@ bool processJsonRequest(char *_serialJson) {
if (_ftpStart == 1) { // ifdef FTP_ENABLE is checked in Ftp_EnableServer()
Ftp_EnableServer();
}
- } else if (doc.containsKey("mqtt")) {
- uint8_t _mqttEnable = doc["mqtt"]["mqttEnable"].as();
- const char *_mqttClientId = object["mqtt"]["mqttClientId"];
- const char *_mqttServer = object["mqtt"]["mqttServer"];
- const char *_mqttUser = doc["mqtt"]["mqttUser"];
- const char *_mqttPwd = doc["mqtt"]["mqttPwd"];
- uint16_t _mqttPort = doc["mqtt"]["mqttPort"].as();
+ }
+ if (doc.containsKey("mqtt")) {
+ uint8_t _mqttEnable = doc["mqtt"]["enable"].as();
+ const char *_mqttClientId = doc["mqtt"]["clientID"];
+ const char *_mqttServer = doc["mqtt"]["server"];
+ const char *_mqttUser = doc["mqtt"]["username"];
+ const char *_mqttPwd = doc["mqtt"]["password"];
+ uint16_t _mqttPort = doc["mqtt"]["port"].as();
gPrefsSettings.putUChar("enableMQTT", _mqttEnable);
gPrefsSettings.putString("mqttClientId", (String)_mqttClientId);
@@ -736,17 +616,25 @@ bool processJsonRequest(char *_serialJson) {
if ((gPrefsSettings.getUChar("enableMQTT", 99) != _mqttEnable) ||
(!String(_mqttServer).equals(gPrefsSettings.getString("mqttServer", "-1")))) {
+ Log_Println("Failed to save mqtt settings", LOGLEVEL_ERROR);
return false;
}
- } else if (doc.containsKey("bluetooth")) {
+ }
+ if (doc.containsKey("bluetooth")) {
// bluetooth settings
const char *_btDeviceName = doc["bluetooth"]["deviceName"];
gPrefsSettings.putString("btDeviceName", (String)_btDeviceName);
const char *btPinCode = doc["bluetooth"]["pinCode"];
gPrefsSettings.putString("btPinCode", (String)btPinCode);
+ // Check if settings were written successfully
+ if (gPrefsSettings.getString("btDeviceName", "") != _btDeviceName ||
+ gPrefsSettings.getString("btPinCode", "") != btPinCode) {
+ Log_Println("Failed to save bluetooth settings", LOGLEVEL_ERROR);
+ return false;
+ }
} else if (doc.containsKey("rfidMod")) {
- const char *_rfidIdModId = object["rfidMod"]["rfidIdMod"];
- uint8_t _modId = object["rfidMod"]["modId"];
+ const char *_rfidIdModId = doc["rfidMod"]["rfidIdMod"];
+ uint8_t _modId = doc["rfidMod"]["modId"];
char rfidString[12];
if (_modId <= 0) {
gPrefsRfid.remove(_rfidIdModId);
@@ -761,10 +649,10 @@ bool processJsonRequest(char *_serialJson) {
}
Web_DumpNvsToSd("rfidTags", backupFile); // Store backup-file every time when a new rfid-tag is programmed
} else if (doc.containsKey("rfidAssign")) {
- const char *_rfidIdAssinId = object["rfidAssign"]["rfidIdMusic"];
+ const char *_rfidIdAssinId = doc["rfidAssign"]["rfidIdMusic"];
char _fileOrUrlAscii[MAX_FILEPATH_LENTGH];
- convertFilenameToAscii(object["rfidAssign"]["fileOrUrl"], _fileOrUrlAscii);
- uint8_t _playMode = object["rfidAssign"]["playMode"];
+ convertFilenameToAscii(doc["rfidAssign"]["fileOrUrl"], _fileOrUrlAscii);
+ uint8_t _playMode = doc["rfidAssign"]["playMode"];
char rfidString[275];
snprintf(rfidString, sizeof(rfidString) / sizeof(rfidString[0]), "%s%s%s0%s%u%s0", stringDelimiter, _fileOrUrlAscii, stringDelimiter, stringDelimiter, _playMode, stringDelimiter);
gPrefsRfid.putString(_rfidIdAssinId, rfidString);
@@ -781,10 +669,10 @@ bool processJsonRequest(char *_serialJson) {
Web_SendWebsocketData(0, 20);
return false;
} else if (doc.containsKey("controls")) {
- if (object["controls"].containsKey("set_volume")) {
+ if (doc["controls"].containsKey("set_volume")) {
uint8_t new_vol = doc["controls"]["set_volume"].as();
AudioPlayer_VolumeToQueueSender(new_vol, true);
- } if (object["controls"].containsKey("action")) {
+ } if (doc["controls"].containsKey("action")) {
uint8_t cmd = doc["controls"]["action"].as();
Cmd_Action(cmd);
}
@@ -794,19 +682,189 @@ bool processJsonRequest(char *_serialJson) {
Web_SendWebsocketData(0, 40);
} else if (doc.containsKey("volume")) {
Web_SendWebsocketData(0, 50);
+ } else if (doc.containsKey("settings")) {
+ Web_SendWebsocketData(0, 60);
+ } else if (doc.containsKey("ssids")) {
+ Web_SendWebsocketData(0, 70);
}
return true;
}
+// process settings to JSON object
+static void settingsToJSON(JsonObject obj, String section) {
+ if ((section == "") || (section == "current")) {
+ // current values
+ JsonObject curObj = obj.createNestedObject("current");
+ curObj["volume"].set(AudioPlayer_GetCurrentVolume());
+ curObj["rfidTagId"] = String(gCurrentRfidTagId);
+ }
+ if ((section == "") || (section == "general")) {
+ // general settings
+ JsonObject generalObj = obj.createNestedObject("general");
+ generalObj["initVolume"].set(gPrefsSettings.getUInt("initVolume", 0));
+ generalObj["maxVolumeSp"].set(gPrefsSettings.getUInt("maxVolumeSp", 0));
+ generalObj["maxVolumeHp"].set(gPrefsSettings.getUInt("maxVolumeHp", 0));
+ generalObj["sleepInactivity"].set(gPrefsSettings.getUInt("mInactiviyT", 0));
+ }
+ if ((section == "") || (section == "wifi")) {
+ // WiFi settings
+ JsonObject wifiObj = obj.createNestedObject("wifi");
+ wifiObj["hostname"] = Wlan_GetHostname();
+ wifiObj["scanOnStart"].set(gPrefsSettings.getBool("ScanWiFiOnStart", false));
+ }
+ if (section == "ssids") {
+ // saved SSID's
+ JsonObject ssidsObj = obj.createNestedObject("ssids");
+ static String ssids[10];
+
+ JsonArray ssidArr = ssidsObj.createNestedArray("savedSSIDs");
+ size_t len = Wlan_GetSSIDs(ssids, 10);
+ if (len > 0) {
+ for (int i = 0; i < len; i++) {
+ ssidArr.add(ssids[i]);
+ }
+ }
+ // active SSID
+ if (Wlan_IsConnected()) {
+ ssidsObj["active"] = Wlan_GetCurrentSSID();
+ }
+ }
+ #ifdef NEOPIXEL_ENABLE
+ if ((section == "") || (section == "led")) {
+ // LED settings
+ JsonObject ledObj = obj.createNestedObject("led");
+ ledObj["initBrightness"].set(gPrefsSettings.getUInt("iLedBrightness", 0));
+ ledObj["nightBrightness"].set(gPrefsSettings.getUInt("nLedBrightness", 0));
+ }
+ #endif
+ #ifdef MEASURE_BATTERY_VOLTAGE
+ if ((section == "") || (section == "battery")) {
+ // battery settings
+ JsonObject batteryObj = obj.createNestedObject("battery");
+ batteryObj["warnLowVoltage"].set(gPrefsSettings.getFloat("wLowVoltage", s_warningLowVoltage));
+ batteryObj["indicatorLow"].set(gPrefsSettings.getFloat("vIndicatorLow", s_voltageIndicatorLow));
+ batteryObj["indicatorHi"].set(gPrefsSettings.getFloat("vIndicatorHigh", s_voltageIndicatorHigh));
+ batteryObj["voltageCheckInterval"].set(gPrefsSettings.getUInt("vCheckIntv", s_batteryCheckInterval));
+ }
+ #endif
+ if (section == "defaults") {
+ // default factory settings
+ JsonObject defaultsObj = obj.createNestedObject("defaults");
+ defaultsObj["initVolume"].set(3u); // AUDIOPLAYER_VOLUME_INIT
+ defaultsObj["maxVolumeSp"].set(21u); // AUDIOPLAYER_VOLUME_MAX
+ defaultsObj["maxVolumeHp"].set(18u); // gPrefsSettings.getUInt("maxVolumeHp", 0));
+ defaultsObj["sleepInactivity"].set(10u); // System_MaxInactivityTime
+ #ifdef NEOPIXEL_ENABLE
+ defaultsObj["initBrightness"].set(16u); // LED_INITIAL_BRIGHTNESS
+ defaultsObj["nightBrightness"].set(2u); // LED_INITIAL_NIGHT_BRIGHTNESS
+ #endif
+ #ifdef MEASURE_BATTERY_VOLTAGE
+ defaultsObj["warnLowVoltage"].set(s_warningLowVoltage);
+ defaultsObj["indicatorLow"].set(s_voltageIndicatorLow);
+ defaultsObj["indicatorHi"].set(s_voltageIndicatorHigh);
+ defaultsObj["voltageCheckInterval"].set(s_batteryCheckInterval);
+ #endif
+ }
+ // FTP
+ #ifdef FTP_ENABLE
+ if ((section == "") || (section == "ftp")) {
+ JsonObject ftpObj = obj.createNestedObject("ftp");
+ ftpObj["username"] = gPrefsSettings.getString("ftpuser", "-1");
+ ftpObj["password"] = gPrefsSettings.getString("ftppassword", "-1");
+ ftpObj["maxUserLength"].set(ftpUserLength - 1);
+ ftpObj["maxPwdLength"].set(ftpUserLength - 1);
+ }
+ #endif
+ // MQTT
+ #ifdef MQTT_ENABLE
+ if ((section == "") || (section == "mqtt")) {
+ JsonObject mqttObj = obj.createNestedObject("mqtt");
+ mqttObj["enable"].set(Mqtt_IsEnabled());
+ mqttObj["clientID"] = gPrefsSettings.getString("mqttClientId", "-1");
+ mqttObj["server"] = gPrefsSettings.getString("mqttServer", "-1");
+ mqttObj["port"].set(gPrefsSettings.getUInt("mqttPort", 0));
+ mqttObj["username"] = gPrefsSettings.getString("mqttUser", "-1");
+ mqttObj["password"] = gPrefsSettings.getString("mqttPassword", "-1");
+ mqttObj["maxUserLength"].set(mqttUserLength - 1);
+ mqttObj["maxPwdLength"].set(mqttPasswordLength - 1);
+ mqttObj["maxClientIdLength"].set(mqttClientIdLength - 1);
+ mqttObj["maxServerLength"].set(mqttServerLength - 1);
+ }
+ #endif
+ // Bluetooth
+ #ifdef BLUETOOTH_ENABLE
+ if ((section == "") || (section == "bluetooth")) {
+ JsonObject btObj = obj.createNestedObject("bluetooth");
+ btObj["deviceName"] = gPrefsSettings.getString("btDeviceName", "");
+ btObj["pinCode"] = gPrefsSettings.getString("btPinCode", "");
+ }
+ #endif
+}
+
+// handle get settings
+void handleGetSettings(AsyncWebServerRequest *request) {
+
+ // param to get a single settings section
+ String section = "";
+ if (request->hasParam("section")) {
+ section = request->getParam("section")->value();
+ }
+ #ifdef BOARD_HAS_PSRAM
+ SpiRamJsonDocument doc(8192);
+ #else
+ StaticJsonDocument<8192> doc;
+ #endif
+ JsonObject settingsObj = doc.createNestedObject("settings");
+ settingsToJSON(settingsObj, section);
+ String serializedJsonString;
+ serializeJson(settingsObj, serializedJsonString);
+ request->send(200, "application/json; charset=utf-8", serializedJsonString);
+}
+
+// handle post settings
+void handlePostSettings(AsyncWebServerRequest *request, JsonVariant &json) {
+ const JsonObject& jsonObj = json.as();
+ bool succ = JSONToSettings(jsonObj);
+ if (succ) {
+ request->send(200);
+ } else {
+ request->send(500, "text/plain; charset=utf-8", "error saving settings");
+ }
+}
+
+
+
+// Takes inputs from webgui, parses JSON and saves values in NVS
+// If operation was successful (NVS-write is verified) true is returned
+bool processJsonRequest(char *_serialJson) {
+ if (!_serialJson) {
+ return false;
+ }
+ #ifdef BOARD_HAS_PSRAM
+ SpiRamJsonDocument doc(1000);
+ #else
+ StaticJsonDocument<1000> doc;
+ #endif
+
+ DeserializationError error = deserializeJson(doc, _serialJson);
+
+ if (error) {
+ Log_Printf(LOGLEVEL_ERROR, jsonErrorMsg, error.c_str());
+ return false;
+ }
+
+ JsonObject obj = doc.as();
+ return JSONToSettings(obj);
+}
+
+
// Sends JSON-answers via websocket
void Web_SendWebsocketData(uint32_t client, uint8_t code) {
if (!webserverStarted)
return;
- char *jBuf = (char *) x_calloc(255, sizeof(char));
-
- const size_t CAPACITY = JSON_OBJECT_SIZE(1) + 200;
- StaticJsonDocument doc;
+ char *jBuf = (char *) x_calloc(1024, sizeof(char));
+ StaticJsonDocument<1024> doc;
JsonObject object = doc.to();
if (code == 1) {
@@ -831,9 +889,16 @@ void Web_SendWebsocketData(uint32_t client, uint8_t code) {
object["coverimg"] = "coverimg";
} else if (code == 50) {
object["volume"] = AudioPlayer_GetCurrentVolume();
+ } else if (code == 60) {
+ JsonObject entry = object.createNestedObject("settings");
+ settingsToJSON(entry, "");
+ } else if (code == 70) {
+ JsonObject entry = object.createNestedObject("settings");
+ settingsToJSON(entry, "ssids");
};
- serializeJson(doc, jBuf, 255);
+
+ serializeJson(doc, jBuf, 1024);
if (client == 0) {
ws.printfAll(jBuf);
@@ -1410,7 +1475,7 @@ void handleGetWiFiConfig(AsyncWebServerRequest *request) {
bool scanWifiOnStart = gPrefsSettings.getBool("ScanWiFiOnStart", false);
obj["hostname"] = Wlan_GetHostname();
- obj["scanwifionstart"].set(scanWifiOnStart);
+ obj["scanOnStart"].set(scanWifiOnStart);
response->setLength();
request->send(response);
@@ -1420,41 +1485,23 @@ void handlePostWiFiConfig(AsyncWebServerRequest *request, JsonVariant &json){
const JsonObject& jsonObj = json.as();
// always perform perform a WiFi scan on startup?
- static bool alwaysScan = (bool) jsonObj["scanwifionstart"];
+ bool alwaysScan = jsonObj["scanOnStart"];
gPrefsSettings.putBool("ScanWiFiOnStart", alwaysScan);
// hostname
String strHostname = jsonObj["hostname"];
- size_t len = strHostname.length();
- const char *hostname = strHostname.c_str();
-
- // validation: first char alphanumerical, then alphanumerical or '-', last char alphanumerical
- // These rules are mainly for mDNS purposes, a "pretty" hostname could have far fewer restrictions
- bool validated = true;
- if(len < 2 || len > 32) {
- validated = false;
- }
-
- if(!isAlphaNumeric(hostname[0]) || !isAlphaNumeric(hostname[len-1])) {
- validated = false;
- }
-
- for(int i = 0; i < len; i++) {
- if(!isAlphaNumeric(hostname[i]) && hostname[i] != '-') {
- validated = false;
- break;
- }
- }
-
- if (!validated) {
+ if (!Wlan_ValidateHostname(strHostname)) {
+ Log_Println("hostname validation failed", LOGLEVEL_ERROR);
request->send(400, "text/plain; charset=utf-8", "hostname validation failed");
return;
}
- bool succ = Wlan_SetHostname(String(hostname));
+ bool succ = Wlan_SetHostname(strHostname);
if (succ) {
- request->send(200, "text/plain; charset=utf-8", hostname);
+ Log_Println("WiFi configuration saved.", LOGLEVEL_NOTICE);
+ request->send(200, "text/plain; charset=utf-8", strHostname);
} else {
+ Log_Println("error setting hostname", LOGLEVEL_ERROR);
request->send(500, "text/plain; charset=utf-8", "error setting hostname");
}
}
diff --git a/src/Wlan.cpp b/src/Wlan.cpp
index f40244aa..902eae8a 100644
--- a/src/Wlan.cpp
+++ b/src/Wlan.cpp
@@ -436,10 +436,37 @@ void Wlan_Cyclic(void) {
}
}
+
+bool Wlan_ValidateHostname(String newHostname) {
+ size_t len = newHostname.length();
+ const char *hostname = newHostname.c_str();
+
+ // validation: first char alphanumerical, then alphanumerical or '-', last char alphanumerical
+ // These rules are mainly for mDNS purposes, a "pretty" hostname could have far fewer restrictions
+ bool validated = true;
+ if(len < 2 || len > 32) {
+ validated = false;
+ }
+
+ if(!isAlphaNumeric(hostname[0]) || !isAlphaNumeric(hostname[len-1])) {
+ validated = false;
+ }
+
+ for(int i = 0; i < len; i++) {
+ if(!isAlphaNumeric(hostname[i]) && hostname[i] != '-') {
+ validated = false;
+ break;
+ }
+ }
+
+ return validated;
+}
+
bool Wlan_SetHostname(String newHostname) {
// hostname should just be applied after reboot
gPrefsSettings.putString("Hostname", newHostname);
- return true;
+ // check if hostname is written
+ return (gPrefsSettings.getString("Hostname", "-1") == newHostname);
}
bool Wlan_AddNetworkSettings(WiFiSettings settings) {
diff --git a/src/Wlan.h b/src/Wlan.h
index a6adc459..3f6fb287 100644
--- a/src/Wlan.h
+++ b/src/Wlan.h
@@ -20,6 +20,7 @@ size_t Wlan_GetSSIDs(String*, size_t);
const String Wlan_GetCurrentSSID();
const String Wlan_GetHostname();
bool Wlan_DeleteNetwork(String);
+bool Wlan_ValidateHostname(String);
bool Wlan_SetHostname(String);
bool Wlan_IsConnected(void);
void Wlan_ToggleEnable(void);