PlatformIO + ESP8266 + Debug mode = Stack overflow
Created by: lbussy
I am using the code right out of your book examples. Whenever I run it a second time (when it should have already created the /config.json
) it tells me it "Failed to deserialize configuration." When the JSON prints it looks fine, and I have run it through a JSON Validator and it returns ok.
The only changes I've made are as follows:
- Renamed
SpiffsConfig.ino
tomain.cpp
as I am using PlatformIO - Added prototypes for the functions at the top of the
main.cpp
I'm not going to include that code - because I got it from you. :)
So - problem statement: I am unable to use the example provided.
It never seems to be able to deserialize the file. The file prints out fine when writing, but when the ESP restarts the file is unable to deserialize again. The file exists.
Here's some demo code I made trying to make sense of it (using the same Config.h and Config.cpp):
#include <FS.h>
#include "Config.h"
const char *filename = "/config.json";
Config config;
bool loadConfig(const char *filename, Config &config);
bool saveConfig(const char *filename, const Config &config);
void setDefaultConfig();
bool printFile(const char *filename);
bool listFiles();
bool listFileSystemInfo();
void printConfig();
void setup();
void loop();
bool loadConfig(const char *filename, Config &config) {
// Loads the configuration from a file on SPIFFS
bool retVal;
// Mount SPIFFS
if (SPIFFS.begin()) {
// Open file for reading
File file = SPIFFS.open(filename, "r");
// This may fail if the file is missing
if (!file) {
Serial.println(F("Failed to open config file."));
retVal = false;
} else {
// Parse the JSON object in the file
// This may fail if the JSON is invalid
if (!deserializeConfig(file, config)) {
Serial.println(F("Failed to deserialize configuration, here's the file we attempted:"));
printFile(filename);
SPIFFS.remove(filename);
Serial.println(F("Deleted corrupt file."));
retVal = false;
} else {
retVal = true;
}
file.close();
}
SPIFFS.end();
} else {
Serial.println(F("Unable to start SPIFFS in loadConfig()."));
retVal = false;
}
return retVal;
}
bool saveConfig(const char *filename, const Config &config) {
bool retVal;
// Open file for writing
if (SPIFFS.begin()) {
File file = SPIFFS.open(filename, "w");
if (!file) {
Serial.println(F("Failed to create config file."));
retVal = false;
} else {
// Serialize JSON to file
bool success = serializeConfig(config, file);
if (!success) {
Serial.println(F("Failed to serialize configuration."));
retVal = false;
} else {
retVal = true;
}
file.close();
}
SPIFFS.end();
} else {
Serial.println(F("Unable to start SPIFFS in saveConfig()."));
retVal = false;
}
return retVal;
}
void setDefaultConfig() {
// Initialize configuration with defaults
Serial.println(F("Setting default config."));
strcpy(config.server.host, "example.com");
strcpy(config.server.path, "/resource");
strcpy(config.server.username, "admin");
strcpy(config.server.password, "s3cr3t");
strcpy(config.accessPoint[0].ssid, "SSID 1");
strcpy(config.accessPoint[0].passphrase, "Passphrase 1");
strcpy(config.accessPoint[1].ssid, "SSID 2");
strcpy(config.accessPoint[1].passphrase, "Passphrase 2");
config.accessPoints = 2;
}
bool printFile(const char *filename) {
// Prints the content of a file to the Serial
bool retVal;
// Open file for reading
if (SPIFFS.begin()) {
File file = SPIFFS.open(filename, "r");
if (!file) {
Serial.println(F("Failed to open file for printing."));
retVal = false;
} else {
// Extract each by one by one
while (file.available()) {
Serial.print((char)file.read());
}
Serial.println();
file.close();
retVal = true;
}
SPIFFS.end();
} else {
Serial.println(F("Unable to start SPIFFS in printFile()."));
retVal = false;
}
return retVal;
}
bool listFileSystemInfo() {
bool retVal;
if (SPIFFS.begin()) {
retVal = true;
// List filesystem information
FSInfo fs_info;
SPIFFS.info(fs_info);
Serial.println(F("-------------------"));
Serial.print(F("Total Bytes: "));
Serial.println(fs_info.totalBytes);
Serial.print(F("Used Bytes: "));
Serial.println(fs_info.usedBytes);
Serial.print(F("Block Size: "));
Serial.println(fs_info.blockSize);
Serial.print(F("Page Size: "));
Serial.println(fs_info.pageSize);
Serial.print(F("Max Open Files: "));
Serial.println(fs_info.maxOpenFiles);
Serial.print(F("Max Path Length: "));
Serial.println(fs_info.maxPathLength);
Serial.println(F("-------------------"));
SPIFFS.end();
return true;
} else {
Serial.println(F("Unable to start SPIFFS in listFileSystemInfo()."));
retVal = false;
}
return retVal;
}
bool listFiles() {
bool retVal;
if (SPIFFS.begin()) {
Dir dir = SPIFFS.openDir("");
int files = 0;
while (dir.next()) {
if (files == 0)
Serial.println(F("-------------------"));
Serial.print(dir.fileName());
Serial.print(F(" - "));
Serial.print(dir.fileSize());
Serial.println(F("B"));
files++;
}
if (files > 0)
Serial.println(F("-------------------"));
SPIFFS.end();
retVal = true;
} else {
Serial.println(F("Unable to start SPIFFS in listFiles()."));
retVal = false;
}
return retVal;
}
void printConfig() {
// TODO: Iterate through stuff
}
void setup() {
delay(1000);
Serial.begin(BAUD);
if (!listFileSystemInfo()) {
Serial.println(F("Error: Unable to list file system info."));
} else {
if (!listFiles()) {
Serial.println(F("Error: Unable to list files."));
} else {
// Load configuration
if (!loadConfig(filename, config)) {
Serial.println(F("Error: Unable to load configuration."));
// Set default configuration
setDefaultConfig();
// Save configuration
if (!saveConfig(filename, config)) {
Serial.println(F("Error: Unable to save configuration."));
} else {
// Dump config file
if (!printFile(filename)) {
Serial.println(F("Error: Unable to print configuration file."));
}
}
} else {
Serial.println(F("Everything seems ok."));
}
}
}
}
void loop() {}
Currently, it all works as expected the first time. Subsequently, when it should be loading the configuration it fails:
-------------------
Total Bytes: 957314
Used Bytes: 753
Block Size: 8192
Page Size: 256
Max Open Files: 5
Max Path Length: 32
-------------------
-------------------
/config.json - 309B
-------------------
Failed to deserialize configuration, here's the file we attempted:
{
"server": {
"username": "admin",
"password": "s3cr3t",
"host": "example.com",
"path": "/resource"
},
"access_points": [
{
"ssid": "SSID 1",
"passphrase": "Passphrase 1"
},
{
"ssid": "SSID 2",
"passphrase": "Passphrase 2"
}
]
}
Deleted corrupt file.
Error: Unable to load configuration.
Setting default config.
{
"server": {
"username": "admin",
"password": "s3cr3t",
"host": "example.com",
"path": "/resource"
},
"access_points": [
{
"ssid": "SSID 1",
"passphrase": "Passphrase 1"
},
{
"ssid": "SSID 2",
"passphrase": "Passphrase 2"
}
]
}
So you can see that the file looks right, it is 309 bytes in length (which is correct) yet still does not deserialize.
ETA: A debug line in deserializeConfig()
tells me that it fails because of IncompleteInput
.