165 lines
3.9 KiB
C++
165 lines
3.9 KiB
C++
#include "config.h"
|
|
#include "log.h"
|
|
|
|
#include <EEPROM.h>
|
|
#include <ArduinoJson.h>
|
|
|
|
#define DIRTY_WRITE_DELAY (10 * 1000)
|
|
|
|
JsonDocument config;
|
|
|
|
unsigned long lastChangeMillis = 0;
|
|
|
|
bool configRead();
|
|
|
|
bool configWrite();
|
|
|
|
bool configWriteBytes(int *address, uint8_t *data, size_t size);
|
|
|
|
bool configReadBytes(int *address, uint8_t *data, size_t size);
|
|
|
|
void configSetup() {
|
|
configRead();
|
|
}
|
|
|
|
void configLoop() {
|
|
if (lastChangeMillis > 0 && millis() - lastChangeMillis > DIRTY_WRITE_DELAY) {
|
|
configWrite();
|
|
}
|
|
}
|
|
|
|
void configReset() {
|
|
config.clear();
|
|
configWrite();
|
|
}
|
|
|
|
String configGetString(const char *name, const char *fallback, bool allowEmpty) {
|
|
if (!config.containsKey(name)) {
|
|
return fallback;
|
|
}
|
|
String value = config[name];
|
|
if (!allowEmpty && value.isEmpty()) {
|
|
return fallback;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
void configPutString(const char *name, const char *value) {
|
|
if (config[name] != value) {
|
|
config[name] = value;
|
|
lastChangeMillis = millis();
|
|
}
|
|
}
|
|
|
|
double configGetDouble(const char *name, double fallback) {
|
|
if (!config.containsKey(name)) {
|
|
return fallback;
|
|
}
|
|
return config[name];
|
|
}
|
|
|
|
void configPutDouble(const char *name, double value) {
|
|
if (config[name] != value) {
|
|
config[name] = value;
|
|
lastChangeMillis = millis();
|
|
}
|
|
}
|
|
|
|
void configPrint() {
|
|
info("Config:");
|
|
for (JsonPair pair: config.as<JsonObject>()) {
|
|
const char *key = pair.key().c_str();
|
|
const JsonVariant &value = pair.value();
|
|
|
|
char valueStr[64];
|
|
if (strcmp(key, "WIFI_PKEY") == 0) {
|
|
snprintf(valueStr, sizeof valueStr, "[PASSWORD REDACTED]");
|
|
} else {
|
|
if (value.is<const char *>()) {
|
|
snprintf(valueStr, sizeof valueStr, "%s", value.as<const char *>());
|
|
} else if (value.is<double>()) {
|
|
snprintf(valueStr, sizeof valueStr, "%f", value.as<double>());
|
|
} else if (value.is<int>()) {
|
|
snprintf(valueStr, sizeof valueStr, "%d", value.as<int>());
|
|
} else if (value.is<bool>()) {
|
|
snprintf(valueStr, sizeof valueStr, "%s", value.as<bool>() ? "true" : "false");
|
|
} else {
|
|
snprintf(valueStr, sizeof valueStr, "[UNKNOWN TYPE]");
|
|
}
|
|
}
|
|
|
|
info(" -%-15s = %s", key, valueStr);
|
|
}
|
|
}
|
|
|
|
bool configRead() {
|
|
size_t length;
|
|
char buffer[512];
|
|
|
|
bool ok = true;
|
|
int address = 0;
|
|
EEPROM.begin(512);
|
|
ok &= configReadBytes(&address, reinterpret_cast<uint8_t *>(&length), sizeof length);
|
|
ok &= configReadBytes(&address, reinterpret_cast<uint8_t *>(buffer), length);
|
|
ok &= EEPROM.end();
|
|
|
|
if (ok) {
|
|
JsonDocument tmp;
|
|
deserializeJson(tmp, buffer);
|
|
if (tmp.is<JsonObject>() && !tmp.isNull()) {
|
|
info("Config loaded");
|
|
config = tmp;
|
|
return true;
|
|
} else {
|
|
error("Failed to parse config JSON");
|
|
}
|
|
} else {
|
|
error("Failed to load config from EEPROM");
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool configWrite() {
|
|
lastChangeMillis = 0;
|
|
|
|
char buffer[512];
|
|
size_t length = serializeJson(config, buffer, sizeof buffer);
|
|
|
|
bool ok = true;
|
|
int address = 0;
|
|
EEPROM.begin(512);
|
|
ok &= configWriteBytes(&address, reinterpret_cast<uint8_t *>(&length), sizeof length);
|
|
ok &= configWriteBytes(&address, reinterpret_cast<uint8_t *>(buffer), length);
|
|
ok &= EEPROM.end();
|
|
if (ok) {
|
|
info("Successfully wrote config to EEPROM");
|
|
} else {
|
|
info("Failed to write config to EEPROM");
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
bool configWriteBytes(int *address, uint8_t *data, size_t size) {
|
|
uint8_t *b = data;
|
|
for (; b < data + size; b++) {
|
|
EEPROM.write((*address)++, *b);
|
|
if ((size_t) *address >= EEPROM.length()) {
|
|
error("END OF EEPROM!!!");
|
|
break;
|
|
}
|
|
}
|
|
return (size_t) (b - data) == size;
|
|
}
|
|
|
|
bool configReadBytes(int *address, uint8_t *data, size_t size) {
|
|
uint8_t *b = data;
|
|
for (; b < data + size; b++) {
|
|
*b = EEPROM.read((*address)++);
|
|
if ((size_t) *address >= EEPROM.length()) {
|
|
error("END OF EEPROM!!!");
|
|
break;
|
|
}
|
|
}
|
|
return (size_t) (b - data) == size;
|
|
}
|