forked from cyberman54/ESP32-Paxcounter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
configmanager.cpp
162 lines (131 loc) · 5.71 KB
/
configmanager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
/* configmanager persists runtime configuration using NVRAM of ESP32*/
#include "globals.h"
#include "configmanager.h"
// Local logging tag
static const char TAG[] = __FILE__;
// default settings for device data to be sent
#define PAYLOADMASK \
((GPS_DATA | ALARM_DATA | MEMS_DATA | COUNT_DATA | SENSOR1_DATA | \
SENSOR2_DATA | SENSOR3_DATA) & \
(~BATT_DATA))
// namespace for device runtime preferences
#define DEVCONFIG "paxcntcfg"
Preferences nvram;
static const uint8_t cfgMagicBytes[] = {0x21, 0x76, 0x87, 0x32, 0xf4};
static const size_t cfgLen = sizeof(cfg), cfgLen2 = sizeof(cfgMagicBytes);
static uint8_t buffer[cfgLen + cfgLen2];
// populate runtime config with device factory settings
//
// configuration frame structure in NVRAM;
// 1. version header [10 bytes, containing version string]
// 2. user settings [cfgLen bytes, containing default runtime settings
// (configData_t cfg)]
// 3. magicByte [cfgLen2 bytes, containing a fixed identifier]
static void defaultConfig(configData_t *myconfig) {
memcpy(myconfig->version, &PROGVERSION, 10); // Firmware version
// device factory settings
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 = 0; // threshold for rssilimiter, negative value!
myconfig->sendcycle = SENDCYCLE; // payload send cycle [seconds/2]
myconfig->sleepcycle = SLEEPCYCLE; // sleep cycle [seconds/2]
myconfig->wifichancycle =
WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
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
myconfig->wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
myconfig->macfilter = MACFILTER; // 0=disabled, 1=enabled
myconfig->rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
myconfig->monitormode = 0; // 0=disabled, 1=enabled
myconfig->payloadmask = PAYLOADMASK; // payloads as defined in default
myconfig->enscount = COUNT_ENS; // 0=disabled, 1=enabled
#ifdef HAS_BME680
// initial BSEC state for BME680 sensor
myconfig->bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {0};
#endif
}
// migrate runtime configuration from earlier to current version
static void migrateConfig(void) {
// currently no configuration migration rules are implemented, we reset to
// factory settings instead
eraseConfig();
}
// save current configuration from RAM to NVRAM
void saveConfig(bool erase) {
ESP_LOGI(TAG, "Storing settings to NVRAM...");
nvram.begin(DEVCONFIG, false);
if (erase) {
ESP_LOGI(TAG, "Resetting device to factory settings");
nvram.clear();
defaultConfig(&cfg);
}
// Copy device runtime config cfg to byte array, padding it with magicBytes
memcpy(buffer, &cfg, cfgLen);
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");
nvram.end();
}
// load configuration from NVRAM into RAM and make it current
bool loadConfig() {
ESP_LOGI(TAG, "Loading device configuration from NVRAM...");
if (!nvram.begin(DEVCONFIG, true)) {
ESP_LOGI(TAG, "NVRAM initialized, device starts with factory settings");
eraseConfig();
}
// simple check that runtime config data matches
// if (nvram.getBytesLength(DEVCONFIG) != (cfgLen + cfgLen2)) {
// ESP_LOGE(TAG, "Configuration invalid");
// return false;
//}
// load device runtime config from nvram and copy it to byte array
nvram.getBytes(DEVCONFIG, buffer, cfgLen + cfgLen2);
nvram.end();
// validate loaded configuration by checking magic bytes at end of array
// if (memcmp(buffer + cfgLen, &cfgMagicBytes, cfgLen2) != 0) {
// ESP_LOGW(TAG, "No configuration found");
// return false;
//}
// 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
ESP_LOGE(TAG, "Incompatible device configuration");
eraseConfig();
return true;
case 1: // device configuration belongs to older than current firmware
ESP_LOGW(TAG, "Device was updated, attempt to migrate configuration");
migrateConfig();
return true;
default: // device configuration version matches current firmware version
return true;
}
}
// 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();
if (std::lexicographical_compare(a1, a1 + strlen(a1), a2, a2 + strlen(a2),
comp))
return -1;
else
return 1;
}
void eraseConfig(void) { saveConfig(true); }