forked from ruvnet/RuView
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnvs_config.c
More file actions
288 lines (253 loc) · 9.96 KB
/
nvs_config.c
File metadata and controls
288 lines (253 loc) · 9.96 KB
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
/**
* @file nvs_config.c
* @brief Runtime configuration via NVS (Non-Volatile Storage).
*
* Checks NVS namespace "csi_cfg" for keys: ssid, password, target_ip,
* target_port, node_id. Falls back to Kconfig defaults when absent.
*/
#include "nvs_config.h"
#include <string.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "sdkconfig.h"
static const char *TAG = "nvs_config";
void nvs_config_load(nvs_config_t *cfg)
{
if (cfg == NULL) {
ESP_LOGE(TAG, "nvs_config_load: cfg is NULL");
return;
}
/* Start with Kconfig compiled defaults */
strncpy(cfg->wifi_ssid, CONFIG_CSI_WIFI_SSID, NVS_CFG_SSID_MAX - 1);
cfg->wifi_ssid[NVS_CFG_SSID_MAX - 1] = '\0';
#ifdef CONFIG_CSI_WIFI_PASSWORD
strncpy(cfg->wifi_password, CONFIG_CSI_WIFI_PASSWORD, NVS_CFG_PASS_MAX - 1);
cfg->wifi_password[NVS_CFG_PASS_MAX - 1] = '\0';
#else
cfg->wifi_password[0] = '\0';
#endif
strncpy(cfg->target_ip, CONFIG_CSI_TARGET_IP, NVS_CFG_IP_MAX - 1);
cfg->target_ip[NVS_CFG_IP_MAX - 1] = '\0';
cfg->target_port = (uint16_t)CONFIG_CSI_TARGET_PORT;
cfg->node_id = (uint8_t)CONFIG_CSI_NODE_ID;
/* ADR-029: Defaults for channel hopping and TDM.
* hop_count=1 means single-channel (backward-compatible). */
cfg->channel_hop_count = 1;
cfg->channel_list[0] = (uint8_t)CONFIG_CSI_WIFI_CHANNEL;
for (uint8_t i = 1; i < NVS_CFG_HOP_MAX; i++) {
cfg->channel_list[i] = 0;
}
cfg->dwell_ms = 50;
cfg->tdm_slot_index = 0;
cfg->tdm_node_count = 1;
/* ADR-039: Edge intelligence defaults from Kconfig. */
#ifdef CONFIG_EDGE_TIER
cfg->edge_tier = (uint8_t)CONFIG_EDGE_TIER;
#else
cfg->edge_tier = 2;
#endif
cfg->presence_thresh = 0.0f; /* 0 = auto-calibrate. */
#ifdef CONFIG_EDGE_FALL_THRESH
cfg->fall_thresh = (float)CONFIG_EDGE_FALL_THRESH / 1000.0f;
#else
cfg->fall_thresh = 2.0f;
#endif
cfg->vital_window = 256;
#ifdef CONFIG_EDGE_VITAL_INTERVAL_MS
cfg->vital_interval_ms = (uint16_t)CONFIG_EDGE_VITAL_INTERVAL_MS;
#else
cfg->vital_interval_ms = 1000;
#endif
#ifdef CONFIG_EDGE_TOP_K
cfg->top_k_count = (uint8_t)CONFIG_EDGE_TOP_K;
#else
cfg->top_k_count = 8;
#endif
#ifdef CONFIG_EDGE_POWER_DUTY
cfg->power_duty = (uint8_t)CONFIG_EDGE_POWER_DUTY;
#else
cfg->power_duty = 100;
#endif
/* ADR-040: WASM programmable sensing defaults from Kconfig. */
#ifdef CONFIG_WASM_MAX_MODULES
cfg->wasm_max_modules = (uint8_t)CONFIG_WASM_MAX_MODULES;
#else
cfg->wasm_max_modules = 4;
#endif
cfg->wasm_verify = 1; /* Default: verify enabled (secure-by-default). */
#ifndef CONFIG_WASM_VERIFY_SIGNATURE
cfg->wasm_verify = 0; /* Kconfig disabled signature verification. */
#endif
/* Try to override from NVS */
nvs_handle_t handle;
esp_err_t err = nvs_open("csi_cfg", NVS_READONLY, &handle);
if (err != ESP_OK) {
ESP_LOGI(TAG, "No NVS config found, using compiled defaults");
return;
}
size_t len;
char buf[NVS_CFG_PASS_MAX];
/* WiFi SSID */
len = sizeof(buf);
if (nvs_get_str(handle, "ssid", buf, &len) == ESP_OK && len > 1) {
strncpy(cfg->wifi_ssid, buf, NVS_CFG_SSID_MAX - 1);
cfg->wifi_ssid[NVS_CFG_SSID_MAX - 1] = '\0';
ESP_LOGI(TAG, "NVS override: ssid=%s", cfg->wifi_ssid);
}
/* WiFi password */
len = sizeof(buf);
if (nvs_get_str(handle, "password", buf, &len) == ESP_OK) {
strncpy(cfg->wifi_password, buf, NVS_CFG_PASS_MAX - 1);
cfg->wifi_password[NVS_CFG_PASS_MAX - 1] = '\0';
ESP_LOGI(TAG, "NVS override: password=***");
}
/* Target IP */
len = sizeof(buf);
if (nvs_get_str(handle, "target_ip", buf, &len) == ESP_OK && len > 1) {
strncpy(cfg->target_ip, buf, NVS_CFG_IP_MAX - 1);
cfg->target_ip[NVS_CFG_IP_MAX - 1] = '\0';
ESP_LOGI(TAG, "NVS override: target_ip=%s", cfg->target_ip);
}
/* Target port */
uint16_t port_val;
if (nvs_get_u16(handle, "target_port", &port_val) == ESP_OK) {
cfg->target_port = port_val;
ESP_LOGI(TAG, "NVS override: target_port=%u", cfg->target_port);
}
/* Node ID */
uint8_t node_val;
if (nvs_get_u8(handle, "node_id", &node_val) == ESP_OK) {
cfg->node_id = node_val;
ESP_LOGI(TAG, "NVS override: node_id=%u", cfg->node_id);
}
/* ADR-029: Channel hop count */
uint8_t hop_count_val;
if (nvs_get_u8(handle, "hop_count", &hop_count_val) == ESP_OK) {
if (hop_count_val >= 1 && hop_count_val <= NVS_CFG_HOP_MAX) {
cfg->channel_hop_count = hop_count_val;
ESP_LOGI(TAG, "NVS override: hop_count=%u", (unsigned)cfg->channel_hop_count);
} else {
ESP_LOGW(TAG, "NVS hop_count=%u out of range [1..%u], ignored",
(unsigned)hop_count_val, (unsigned)NVS_CFG_HOP_MAX);
}
}
/* ADR-029: Channel list (stored as a blob of up to NVS_CFG_HOP_MAX bytes) */
len = NVS_CFG_HOP_MAX;
uint8_t ch_blob[NVS_CFG_HOP_MAX];
if (nvs_get_blob(handle, "chan_list", ch_blob, &len) == ESP_OK && len > 0) {
uint8_t count = (len < cfg->channel_hop_count) ? (uint8_t)len : cfg->channel_hop_count;
for (uint8_t i = 0; i < count; i++) {
cfg->channel_list[i] = ch_blob[i];
}
ESP_LOGI(TAG, "NVS override: chan_list loaded (%u channels)", (unsigned)count);
}
/* ADR-029: Dwell time */
uint32_t dwell_val;
if (nvs_get_u32(handle, "dwell_ms", &dwell_val) == ESP_OK) {
if (dwell_val >= 10) {
cfg->dwell_ms = dwell_val;
ESP_LOGI(TAG, "NVS override: dwell_ms=%lu", (unsigned long)cfg->dwell_ms);
} else {
ESP_LOGW(TAG, "NVS dwell_ms=%lu too small, ignored", (unsigned long)dwell_val);
}
}
/* ADR-029/031: TDM slot index */
uint8_t slot_val;
if (nvs_get_u8(handle, "tdm_slot", &slot_val) == ESP_OK) {
cfg->tdm_slot_index = slot_val;
ESP_LOGI(TAG, "NVS override: tdm_slot_index=%u", (unsigned)cfg->tdm_slot_index);
}
/* ADR-029/031: TDM node count */
uint8_t tdm_nodes_val;
if (nvs_get_u8(handle, "tdm_nodes", &tdm_nodes_val) == ESP_OK) {
if (tdm_nodes_val >= 1) {
cfg->tdm_node_count = tdm_nodes_val;
ESP_LOGI(TAG, "NVS override: tdm_node_count=%u", (unsigned)cfg->tdm_node_count);
} else {
ESP_LOGW(TAG, "NVS tdm_nodes=%u invalid, ignored", (unsigned)tdm_nodes_val);
}
}
/* ADR-039: Edge intelligence overrides. */
uint8_t edge_tier_val;
if (nvs_get_u8(handle, "edge_tier", &edge_tier_val) == ESP_OK) {
if (edge_tier_val <= 2) {
cfg->edge_tier = edge_tier_val;
ESP_LOGI(TAG, "NVS override: edge_tier=%u", (unsigned)cfg->edge_tier);
}
}
/* Presence threshold stored as u16 (value * 1000). */
uint16_t pres_thresh_val;
if (nvs_get_u16(handle, "pres_thresh", &pres_thresh_val) == ESP_OK) {
cfg->presence_thresh = (float)pres_thresh_val / 1000.0f;
ESP_LOGI(TAG, "NVS override: presence_thresh=%.3f", cfg->presence_thresh);
}
/* Fall threshold stored as u16 (value * 1000). */
uint16_t fall_thresh_val;
if (nvs_get_u16(handle, "fall_thresh", &fall_thresh_val) == ESP_OK) {
cfg->fall_thresh = (float)fall_thresh_val / 1000.0f;
ESP_LOGI(TAG, "NVS override: fall_thresh=%.3f", cfg->fall_thresh);
}
uint16_t vital_win_val;
if (nvs_get_u16(handle, "vital_win", &vital_win_val) == ESP_OK) {
if (vital_win_val >= 32 && vital_win_val <= 256) {
cfg->vital_window = vital_win_val;
ESP_LOGI(TAG, "NVS override: vital_window=%u", cfg->vital_window);
}
}
uint16_t vital_int_val;
if (nvs_get_u16(handle, "vital_int", &vital_int_val) == ESP_OK) {
if (vital_int_val >= 100) {
cfg->vital_interval_ms = vital_int_val;
ESP_LOGI(TAG, "NVS override: vital_interval_ms=%u", cfg->vital_interval_ms);
}
}
uint8_t topk_val;
if (nvs_get_u8(handle, "subk_count", &topk_val) == ESP_OK) {
if (topk_val >= 1 && topk_val <= 32) {
cfg->top_k_count = topk_val;
ESP_LOGI(TAG, "NVS override: top_k_count=%u", (unsigned)cfg->top_k_count);
}
}
uint8_t duty_val;
if (nvs_get_u8(handle, "power_duty", &duty_val) == ESP_OK) {
if (duty_val >= 10 && duty_val <= 100) {
cfg->power_duty = duty_val;
ESP_LOGI(TAG, "NVS override: power_duty=%u%%", (unsigned)cfg->power_duty);
}
}
/* ADR-040: WASM configuration overrides. */
uint8_t wasm_max_val;
if (nvs_get_u8(handle, "wasm_max", &wasm_max_val) == ESP_OK) {
if (wasm_max_val >= 1 && wasm_max_val <= 8) {
cfg->wasm_max_modules = wasm_max_val;
ESP_LOGI(TAG, "NVS override: wasm_max_modules=%u", (unsigned)cfg->wasm_max_modules);
}
}
uint8_t wasm_verify_val;
if (nvs_get_u8(handle, "wasm_verify", &wasm_verify_val) == ESP_OK) {
cfg->wasm_verify = wasm_verify_val ? 1 : 0;
ESP_LOGI(TAG, "NVS override: wasm_verify=%u", (unsigned)cfg->wasm_verify);
}
/* ADR-040: Load WASM signing public key from NVS (32-byte blob). */
cfg->wasm_pubkey_valid = 0;
memset(cfg->wasm_pubkey, 0, 32);
size_t pubkey_len = 32;
if (nvs_get_blob(handle, "wasm_pubkey", cfg->wasm_pubkey, &pubkey_len) == ESP_OK
&& pubkey_len == 32)
{
cfg->wasm_pubkey_valid = 1;
ESP_LOGI(TAG, "NVS: wasm_pubkey loaded (%02x%02x...%02x%02x)",
cfg->wasm_pubkey[0], cfg->wasm_pubkey[1],
cfg->wasm_pubkey[30], cfg->wasm_pubkey[31]);
} else if (cfg->wasm_verify) {
ESP_LOGW(TAG, "wasm_verify=1 but no wasm_pubkey in NVS — uploads will be rejected");
}
/* Validate tdm_slot_index < tdm_node_count */
if (cfg->tdm_slot_index >= cfg->tdm_node_count) {
ESP_LOGW(TAG, "tdm_slot_index=%u >= tdm_node_count=%u, clamping to 0",
(unsigned)cfg->tdm_slot_index, (unsigned)cfg->tdm_node_count);
cfg->tdm_slot_index = 0;
}
nvs_close(handle);
}