Prevent config corruption by checking whether memory allocation was successfull.
This commit is contained in:
parent
a65f1e48a5
commit
88d75673fc
@ -6,6 +6,7 @@
|
|||||||
#include "WebApi_device.h"
|
#include "WebApi_device.h"
|
||||||
#include "WebApi_devinfo.h"
|
#include "WebApi_devinfo.h"
|
||||||
#include "WebApi_dtu.h"
|
#include "WebApi_dtu.h"
|
||||||
|
#include "WebApi_errors.h"
|
||||||
#include "WebApi_eventlog.h"
|
#include "WebApi_eventlog.h"
|
||||||
#include "WebApi_firmware.h"
|
#include "WebApi_firmware.h"
|
||||||
#include "WebApi_gridprofile.h"
|
#include "WebApi_gridprofile.h"
|
||||||
@ -42,6 +43,8 @@ public:
|
|||||||
|
|
||||||
static void sendTooManyRequests(AsyncWebServerRequest* request);
|
static void sendTooManyRequests(AsyncWebServerRequest* request);
|
||||||
|
|
||||||
|
static void writeConfig(JsonObject& retMsg, const WebApiError code = WebApiError::GenericSuccess, const String& message = "Settings saved!");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@ enum WebApiError {
|
|||||||
GenericDataTooLarge,
|
GenericDataTooLarge,
|
||||||
GenericParseError,
|
GenericParseError,
|
||||||
GenericValueMissing,
|
GenericValueMissing,
|
||||||
|
GenericWriteFailed,
|
||||||
|
|
||||||
DtuBase = 2000,
|
DtuBase = 2000,
|
||||||
DtuSerialZero,
|
DtuSerialZero,
|
||||||
|
|||||||
@ -26,6 +26,11 @@ bool ConfigurationClass::write()
|
|||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (doc.capacity() == 0) {
|
||||||
|
MessageOutput.println("Failed to allocate memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject cfg = doc.createNestedObject("cfg");
|
JsonObject cfg = doc.createNestedObject("cfg");
|
||||||
cfg["version"] = config.Cfg.Version;
|
cfg["version"] = config.Cfg.Version;
|
||||||
cfg["save_count"] = config.Cfg.SaveCount;
|
cfg["save_count"] = config.Cfg.SaveCount;
|
||||||
@ -226,6 +231,12 @@ bool ConfigurationClass::read()
|
|||||||
File f = LittleFS.open(CONFIG_FILENAME, "r", false);
|
File f = LittleFS.open(CONFIG_FILENAME, "r", false);
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (doc.capacity() == 0) {
|
||||||
|
MessageOutput.println("Failed to allocate memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
const DeserializationError error = deserializeJson(doc, f);
|
const DeserializationError error = deserializeJson(doc, f);
|
||||||
if (error) {
|
if (error) {
|
||||||
@ -461,6 +472,12 @@ void ConfigurationClass::migrate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
DynamicJsonDocument doc(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
|
if (doc.capacity() == 0) {
|
||||||
|
MessageOutput.println("Failed to allocate memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Deserialize the JSON document
|
// Deserialize the JSON document
|
||||||
const DeserializationError error = deserializeJson(doc, f);
|
const DeserializationError error = deserializeJson(doc, f);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|||||||
@ -117,4 +117,16 @@ void WebApiClass::sendTooManyRequests(AsyncWebServerRequest* request)
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebApiClass::writeConfig(JsonObject& retMsg, const WebApiError code, const String& message)
|
||||||
|
{
|
||||||
|
if (!Configuration.write()) {
|
||||||
|
retMsg["message"] = "Write failed!";
|
||||||
|
retMsg["code"] = WebApiError::GenericWriteFailed;
|
||||||
|
} else {
|
||||||
|
retMsg["type"] = "success";
|
||||||
|
retMsg["message"] = message;
|
||||||
|
retMsg["code"] = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WebApiClass WebApi;
|
WebApiClass WebApi;
|
||||||
@ -193,11 +193,7 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)
|
|||||||
Display.setLanguage(config.Display.Language);
|
Display.setLanguage(config.Display.Language);
|
||||||
Display.Diagram().updatePeriod();
|
Display.Diagram().updatePeriod();
|
||||||
|
|
||||||
Configuration.write();
|
WebApi.writeConfig(retMsg);
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -157,11 +157,8 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)
|
|||||||
config.Dtu.Nrf.PaLevel = root["nrf_palevel"].as<uint8_t>();
|
config.Dtu.Nrf.PaLevel = root["nrf_palevel"].as<uint8_t>();
|
||||||
config.Dtu.Cmt.PaLevel = root["cmt_palevel"].as<int8_t>();
|
config.Dtu.Cmt.PaLevel = root["cmt_palevel"].as<int8_t>();
|
||||||
config.Dtu.Cmt.Frequency = root["cmt_frequency"].as<uint32_t>();
|
config.Dtu.Cmt.Frequency = root["cmt_frequency"].as<uint32_t>();
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -167,11 +167,8 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)
|
|||||||
inverter->Serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
inverter->Serial = strtoll(root["serial"].as<String>().c_str(), NULL, 16);
|
||||||
|
|
||||||
strncpy(inverter->Name, root["name"].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
strncpy(inverter->Name, root["name"].as<String>().c_str(), INV_MAX_NAME_STRLEN);
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg, WebApiError::InverterAdded, "Inverter created!");
|
||||||
retMsg["message"] = "Inverter created!";
|
|
||||||
retMsg["code"] = WebApiError::InverterAdded;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -294,11 +291,7 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)
|
|||||||
arrayCount++;
|
arrayCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration.write();
|
WebApi.writeConfig(retMsg, WebApiError::InverterChanged, "Inverter changed!");
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
|
||||||
retMsg["code"] = WebApiError::InverterChanged;
|
|
||||||
retMsg["message"] = "Inverter changed!";
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -395,11 +388,8 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)
|
|||||||
|
|
||||||
inverter.Serial = 0;
|
inverter.Serial = 0;
|
||||||
strncpy(inverter.Name, "", sizeof(inverter.Name));
|
strncpy(inverter.Name, "", sizeof(inverter.Name));
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg, WebApiError::InverterDeleted, "Inverter deleted!");
|
||||||
retMsg["message"] = "Inverter deleted!";
|
|
||||||
retMsg["code"] = WebApiError::InverterDeleted;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
@ -466,11 +456,7 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)
|
|||||||
order++;
|
order++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Configuration.write();
|
WebApi.writeConfig(retMsg, WebApiError::InverterOrdered, "Inverter order saved!");
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
|
||||||
retMsg["message"] = "Inverter order saved!";
|
|
||||||
retMsg["code"] = WebApiError::InverterOrdered;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -342,11 +342,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
|
|||||||
config.Mqtt.Hass.Retain = root["mqtt_hass_retain"].as<bool>();
|
config.Mqtt.Hass.Retain = root["mqtt_hass_retain"].as<bool>();
|
||||||
config.Mqtt.Hass.IndividualPanels = root["mqtt_hass_individualpanels"].as<bool>();
|
config.Mqtt.Hass.IndividualPanels = root["mqtt_hass_individualpanels"].as<bool>();
|
||||||
strlcpy(config.Mqtt.Hass.Topic, root["mqtt_hass_topic"].as<String>().c_str(), sizeof(config.Mqtt.Hass.Topic));
|
strlcpy(config.Mqtt.Hass.Topic, root["mqtt_hass_topic"].as<String>().c_str(), sizeof(config.Mqtt.Hass.Topic));
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -238,11 +238,8 @@ void WebApiNetworkClass::onNetworkAdminPost(AsyncWebServerRequest* request)
|
|||||||
}
|
}
|
||||||
config.WiFi.ApTimeout = root["aptimeout"].as<uint>();
|
config.WiFi.ApTimeout = root["aptimeout"].as<uint>();
|
||||||
config.Mdns.Enabled = root["mdnsenabled"].as<bool>();
|
config.Mdns.Enabled = root["mdnsenabled"].as<bool>();
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -179,11 +179,8 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request)
|
|||||||
config.Ntp.Latitude = root["latitude"].as<double>();
|
config.Ntp.Latitude = root["latitude"].as<double>();
|
||||||
config.Ntp.Longitude = root["longitude"].as<double>();
|
config.Ntp.Longitude = root["longitude"].as<double>();
|
||||||
config.Ntp.SunsetType = root["sunsettype"].as<uint8_t>();
|
config.Ntp.SunsetType = root["sunsettype"].as<uint8_t>();
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -101,11 +101,8 @@ void WebApiSecurityClass::onSecurityPost(AsyncWebServerRequest* request)
|
|||||||
CONFIG_T& config = Configuration.get();
|
CONFIG_T& config = Configuration.get();
|
||||||
strlcpy(config.Security.Password, root["password"].as<String>().c_str(), sizeof(config.Security.Password));
|
strlcpy(config.Security.Password, root["password"].as<String>().c_str(), sizeof(config.Security.Password));
|
||||||
config.Security.AllowReadonly = root["allow_readonly"].as<bool>();
|
config.Security.AllowReadonly = root["allow_readonly"].as<bool>();
|
||||||
Configuration.write();
|
|
||||||
|
|
||||||
retMsg["type"] = "success";
|
WebApi.writeConfig(retMsg);
|
||||||
retMsg["message"] = "Settings saved!";
|
|
||||||
retMsg["code"] = WebApiError::GenericSuccess;
|
|
||||||
|
|
||||||
response->setLength();
|
response->setLength();
|
||||||
request->send(response);
|
request->send(response);
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
"1003": "Daten zu groß!",
|
"1003": "Daten zu groß!",
|
||||||
"1004": "Fehler beim interpretieren der Daten!",
|
"1004": "Fehler beim interpretieren der Daten!",
|
||||||
"1005": "Benötigte Werte fehlen!",
|
"1005": "Benötigte Werte fehlen!",
|
||||||
|
"1006": "Schreiben fehlgeschlagen!",
|
||||||
"2001": "Die Seriennummer darf nicht 0 sein!",
|
"2001": "Die Seriennummer darf nicht 0 sein!",
|
||||||
"2002": "Das Abfraginterval muss größer als 0 sein!",
|
"2002": "Das Abfraginterval muss größer als 0 sein!",
|
||||||
"2003": "Ungültige Sendeleistung angegeben!",
|
"2003": "Ungültige Sendeleistung angegeben!",
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
"1003": "Data too large!",
|
"1003": "Data too large!",
|
||||||
"1004": "Failed to parse data!",
|
"1004": "Failed to parse data!",
|
||||||
"1005": "Values are missing!",
|
"1005": "Values are missing!",
|
||||||
|
"1006": "Write failed!",
|
||||||
"2001": "Serial cannot be zero!",
|
"2001": "Serial cannot be zero!",
|
||||||
"2002": "Poll interval must be greater zero!",
|
"2002": "Poll interval must be greater zero!",
|
||||||
"2003": "Invalid power level setting!",
|
"2003": "Invalid power level setting!",
|
||||||
|
|||||||
@ -48,6 +48,7 @@
|
|||||||
"1003": "Données trop importantes !",
|
"1003": "Données trop importantes !",
|
||||||
"1004": "Échec de l'analyse des données !",
|
"1004": "Échec de l'analyse des données !",
|
||||||
"1005": "Certaines valeurs sont manquantes !",
|
"1005": "Certaines valeurs sont manquantes !",
|
||||||
|
"1006": "Write failed!",
|
||||||
"2001": "Le numéro de série ne peut pas être nul !",
|
"2001": "Le numéro de série ne peut pas être nul !",
|
||||||
"2002": "L'intervalle de sondage doit être supérieur à zéro !",
|
"2002": "L'intervalle de sondage doit être supérieur à zéro !",
|
||||||
"2003": "Réglage du niveau de puissance invalide !",
|
"2003": "Réglage du niveau de puissance invalide !",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user