#include "config.h" #include "log.h" #include #include #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()) { const char *value = pair.value().as(); if (strcmp(pair.key().c_str(), "WIFI_PKEY") == 0) { value = "[***]"; } info(" - %s: \"%s\"", pair.key().c_str(), value); } } bool configRead() { size_t length; char buffer[512]; bool ok = true; int address = 0; EEPROM.begin(512); ok &= configReadBytes(&address, reinterpret_cast(&length), sizeof length); ok &= configReadBytes(&address, reinterpret_cast(buffer), length); ok &= EEPROM.end(); if (ok) { JsonDocument tmp; deserializeJson(tmp, buffer); if (tmp.is() && !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(&length), sizeof length); ok &= configWriteBytes(&address, reinterpret_cast(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; }