I have not that much experience with native languages like c/c++ and I'm facing a strange issue, which drives me crazy. So I'm using an Wemos D1 mini (ESP8266) which uses a class calles ConfigManager
to read a configuration file from eeprom. The config file is formatted as json, so I'm using ArduinoJson to parse the content. I have declared a StaticJsonBuffer
and pointer to a JsonObject
in the header, like you can see in the code example:
//FILE: ConfigManager.h
#ifndef ConfigManager_H
#define ConfigManager_H
#include <Arduino.h>
#include <ArduinoJson.h>
#include <FS.h>
#include "Logger.h"
class ConfigManager {
public:
Settings *settings;
ConfigManager();
void read_from_eeprom();
private:
File configFile;
JsonObject *json;
StaticJsonBuffer<200> jsonBuffer;
void open_file(const char *permission);
void read_json();
void recreate_file();
void create_json();
void check_success();
void populate_settings();
void clean_up();
};
#endif
When the function read_from_eeprom
is invoked, it opens the file and invokes the functionread_json
:
void ConfigManager::read_json() {
size_t size = configFile.size();
Log.verbose("[ConfigManager] Config file size: %d", size);
std::unique_ptr<char[]> buf(new char[size]);
configFile.readBytes(buf.get(), size);
Log.verbose("[ConfigManager] File content: %s", buf.get());
Log.verbose("[ConfigManager] Parsing json");
json = &jsonBuffer.parseObject(buf.get());
Log.notice("[ConfigManager] Json is:");
json->printTo(Serial);
Serial.println();
}
Which is followed by a call to check_success()
void ConfigManager::check_success() {
Log.notice("[ConfigManager] Json is:");
json->printTo(Serial);
Serial.println();
bool should_recreate = true;
if (json->success()) {
Log.notice("[ConfigManager] Parsed json successfully");
auto version = json->get<const char*>("version");
if (version) {
if (strcmp(version, Settings::current_version) == 0) {
Log.notice("[ConfigManager] Config version is up2date");
should_recreate = false;
} else {
Log.warning("[ConfigManager] Config version outdated");
}
} else {
Log.warning("[ConfigManager] Invalid config file");
}
} else {
Log.warning("[ConfigManager] Config file is not valid json");
}
if (should_recreate) {
Log.notice("[ConfigManager] Recreating config file");
recreate_file();
create_json();
}
Log.notice("JSON IS: ");
json->prettyPrintTo(Serial);
Log.notice("[ConfigManager] Sucessfully read json");
}
So what I noticed is that the file content is fine. E.g. {"version":"0.2","led_count":"64"}
.
Then the json is parsed, which succeeds and logs the json object, which is again {"version":"0.2","led_count":"64"}
.
Afterwards the function returns, and calls check_success
, which again prints the content of the json object to the log, but this time it seems that something has overwritten the JsonBuffer, which causes the json object to be corrupted. This time the logged content is {"v␂":"0.2","led_count":"64"}
(with some strange unicorn characters that change as the source code changes). I'm trying to figure out whats going on for many hours now, but I'm stuck. Can someone please point me in the right direction to solve this problem? Thank you!
-
I give +1 for the care you put debugging your code and a well stated question (which led to a timely answer).user31481– user314812018年02月19日 18:18:47 +00:00Commented Feb 19, 2018 at 18:18
1 Answer 1
the ArduinoJson library doesn't copy the strings, it only stores pointers and writes terminating zeros into input buffer. And your buffer buf is disposed by std::unique_ptr at the end of read_json() function
-
That's exactly what I needed. I'm now creating the unique_ptr dynamically and dispose it at the end. It now works flawless. Thank you so much!Simon– Simon2018年02月19日 18:13:34 +00:00Commented Feb 19, 2018 at 18:13
-
@Simon Could you show an example of how you did that ?Anum Sheraz– Anum Sheraz2019年09月15日 20:03:11 +00:00Commented Sep 15, 2019 at 20:03
-
@AnumSheraz The 3rd line in the
read_json
function (where I create the unique_ptr) was the issue. A quick fix would be to move the variable to class level rather than defining it in the function itself. This will keep the buffer available until the class instance is disposed.Simon– Simon2019年09月16日 06:50:00 +00:00Commented Sep 16, 2019 at 6:50