ESP32-PaxCounter/src/configmanager.cpp

158 lines
5.3 KiB
C++
Raw Normal View History

/* configmanager persists runtime configuration using NVRAM of ESP32*/
#include "globals.h"
2020-03-29 18:08:52 +02:00
#include "configmanager.h"
2020-10-02 23:07:24 +02:00
// namespace for device runtime preferences
#define DEVCONFIG "paxcntcfg"
Preferences nvram;
configData_t cfg; // struct holds current device configuration
static const uint8_t cfgMagicBytes[] = {0x21, 0x76, 0x87, 0x32, 0xf4};
2020-10-04 13:15:17 +02:00
static const size_t cfgLen = sizeof(cfg), cfgLen2 = sizeof(cfgMagicBytes);
static uint8_t buffer[cfgLen + cfgLen2];
// populate runtime config with device factory settings
2020-10-04 19:32:22 +02:00
//
// configuration frame structure in NVRAM;
// 1. version header [10 bytes, containing version string]
2020-10-04 23:22:48 +02:00
// 2. user settings [cfgLen bytes, containing default runtime settings
// (configData_t cfg)]
2020-10-04 19:32:22 +02:00
// 3. magicByte [cfgLen2 bytes, containing a fixed identifier]
static void defaultConfig(configData_t *myconfig) {
strncpy(myconfig->version, PROGVERSION,
sizeof(myconfig->version) - 1); // Firmware version
// device factory settings
2020-10-02 23:07:24 +02:00
myconfig->loradr = LORADRDEFAULT; // 0-15, lora datarate, see paxcounter.conf
myconfig->txpower = LORATXPOWDEFAULT; // 0-15, lora tx power
myconfig->adrmode = 1; // 0=disabled, 1=enabled
myconfig->screensaver = 0; // 0=disabled, 1=enabled
myconfig->screenon = 1; // 0=disabled, 1=enabled
myconfig->countermode =
COUNTERMODE; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
myconfig->rssilimit = RSSILIMIT; // threshold for rssilimiter, negative value!
2020-10-02 23:07:24 +02:00
myconfig->sendcycle = SENDCYCLE; // payload send cycle [seconds/2]
2021-03-27 18:52:39 +01:00
myconfig->sleepcycle = SLEEPCYCLE; // sleep cycle [seconds/10]
2020-10-02 23:07:24 +02:00
myconfig->wifichancycle =
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
2020-10-02 23:07:24 +02:00
myconfig->blescantime =
BLESCANINTERVAL /
10; // BT channel scan cycle [seconds/100], default 1 (= 10ms)
myconfig->blescan = BLECOUNTER; // 0=disabled, 1=enabled
myconfig->wifiscan = WIFICOUNTER; // 0=disabled, 1=enabled
2020-12-13 19:29:15 +01:00
myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
myconfig->payloadmask = PAYLOADMASK; // payloads as defined in default
2020-10-02 23:07:24 +02:00
#ifdef HAS_BME680
// initial BSEC state for BME680 sensor
myconfig->bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {0};
#endif
}
2020-10-04 19:25:49 +02:00
// migrate runtime configuration from earlier to current version
static void migrateConfig(void) {
2020-10-05 15:41:49 +02:00
// currently no configuration migration rules are implemented, we reset to
// factory settings instead
eraseConfig();
}
// save current configuration from RAM to NVRAM
2020-10-02 23:07:24 +02:00
void saveConfig(bool erase) {
2020-10-04 13:15:17 +02:00
ESP_LOGI(TAG, "Storing settings to NVRAM...");
2020-10-02 23:07:24 +02:00
nvram.begin(DEVCONFIG, false);
2020-10-02 23:07:24 +02:00
if (erase) {
2020-10-04 13:15:17 +02:00
ESP_LOGI(TAG, "Resetting device to factory settings");
2020-10-02 23:07:24 +02:00
nvram.clear();
defaultConfig(&cfg);
}
2020-10-04 13:15:17 +02:00
// Copy device runtime config cfg to byte array, padding it with magicBytes
2020-10-02 23:07:24 +02:00
memcpy(buffer, &cfg, cfgLen);
2020-10-04 13:15:17 +02:00
memcpy(buffer + cfgLen, &cfgMagicBytes, cfgLen2);
// save byte array to NVRAM, padding with cfg magicbyes
if (nvram.putBytes(DEVCONFIG, buffer, cfgLen + cfgLen2))
ESP_LOGI(TAG, "Device settings saved");
else
ESP_LOGE(TAG, "NVRAM Error, device settings not saved");
2020-10-02 23:07:24 +02:00
nvram.end();
}
// load configuration from NVRAM into RAM and make it current
2021-12-27 21:03:41 +01:00
void loadConfig(void) {
int readBytes = 0;
2020-10-04 19:25:49 +02:00
ESP_LOGI(TAG, "Loading device configuration from NVRAM...");
2021-12-27 21:03:41 +01:00
if (nvram.begin(DEVCONFIG, true)) {
// load device runtime config from nvram and copy it to byte array
readBytes = nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2);
nvram.end();
// check that runtime config data length matches
if (readBytes != cfgLen + cfgLen2) {
ESP_LOGE(TAG, "No valid configuration found");
migrateConfig();
}
} else {
2020-10-04 19:25:49 +02:00
ESP_LOGI(TAG, "NVRAM initialized, device starts with factory settings");
2020-10-02 23:07:24 +02:00
eraseConfig();
}
2020-10-04 13:15:17 +02:00
// validate loaded configuration by checking magic bytes at end of array
2021-12-27 21:03:41 +01:00
if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) {
ESP_LOGE(TAG, "Configuration data corrupt");
eraseConfig();
}
// copy loaded configuration into runtime cfg struct
memcpy(&cfg, buffer, cfgLen);
ESP_LOGI(TAG, "Runtime configuration v%s loaded", cfg.version);
// check if config version matches current firmware version
switch (version_compare(PROGVERSION, cfg.version)) {
case -1: // device configuration belongs to newer than current firmware
2020-10-04 19:25:49 +02:00
ESP_LOGE(TAG, "Incompatible device configuration");
eraseConfig();
2021-12-27 21:03:41 +01:00
break;
case 1: // device configuration belongs to older than current firmware
2020-10-04 19:25:49 +02:00
ESP_LOGW(TAG, "Device was updated, attempt to migrate configuration");
migrateConfig();
2021-12-27 21:03:41 +01:00
break;
default: // device configuration version matches current firmware version
2021-12-27 21:03:41 +01:00
break; // nothing to do here
}
}
// helper function to convert strings into lower case
bool comp(char s1, char s2) { return (tolower(s1) < tolower(s2)); }
// helper function to lexicographically compare two versions. Returns 1 if v2
// is smaller, -1 if v1 is smaller, 0 if equal
int version_compare(const String v1, const String v2) {
if (v1 == v2)
return 0;
const char *a1 = v1.c_str(), *a2 = v2.c_str();
2020-10-04 19:25:49 +02:00
if (std::lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2),
comp))
return -1;
else
return 1;
2020-10-02 23:07:24 +02:00
}
void eraseConfig(void) {
reset_rtc_vars();
saveConfig(true);
}