feat: add MAC address filter for ESP32 CSI collection

In multi-AP environments, CSI frames from different access points get
mixed together, corrupting the sensing signal. Add transmitter MAC
filtering so only frames from a specified AP are processed.

Implementation:
- csi_collector: filter in wifi_csi_callback by comparing info->mac
  against configured MAC; log transmitter MAC in periodic debug output
- csi_collector_set_filter_mac(): runtime API to enable/disable filter
- Kconfig: CSI_FILTER_MAC option (format "AA:BB:CC:DD:EE:FF")
- NVS: "filter_mac" 6-byte blob overrides Kconfig at runtime
- nvs_config: parse Kconfig MAC string at boot, load NVS override
- main: apply filter from config after csi_collector_init()

When no filter is configured (default), behavior is unchanged —
all transmitter MACs are accepted for backward compatibility.

Fixes #98

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
ruv
2026-03-02 16:43:21 -05:00
parent 66392cb4e2
commit 4643fcf88e
6 changed files with 131 additions and 2 deletions
+45
View File
@@ -9,6 +9,7 @@
#include "nvs_config.h"
#include <string.h>
#include <stdio.h>
#include "esp_log.h"
#include "nvs_flash.h"
#include "nvs.h"
@@ -51,6 +52,29 @@ void nvs_config_load(nvs_config_t *cfg)
cfg->tdm_slot_index = 0;
cfg->tdm_node_count = 1;
/* MAC filter: default disabled (all zeros) */
memset(cfg->filter_mac, 0, 6);
cfg->filter_mac_enabled = 0;
/* Parse compile-time Kconfig MAC filter if set (format: "AA:BB:CC:DD:EE:FF") */
#ifdef CONFIG_CSI_FILTER_MAC
{
const char *mac_str = CONFIG_CSI_FILTER_MAC;
unsigned int m[6];
if (mac_str[0] != '\0' &&
sscanf(mac_str, "%x:%x:%x:%x:%x:%x",
&m[0], &m[1], &m[2], &m[3], &m[4], &m[5]) == 6) {
for (int i = 0; i < 6; i++) {
cfg->filter_mac[i] = (uint8_t)m[i];
}
cfg->filter_mac_enabled = 1;
ESP_LOGI(TAG, "Kconfig MAC filter: %02X:%02X:%02X:%02X:%02X:%02X",
cfg->filter_mac[0], cfg->filter_mac[1], cfg->filter_mac[2],
cfg->filter_mac[3], cfg->filter_mac[4], cfg->filter_mac[5]);
}
}
#endif
/* Try to override from NVS */
nvs_handle_t handle;
esp_err_t err = nvs_open("csi_cfg", NVS_READONLY, &handle);
@@ -152,6 +176,27 @@ void nvs_config_load(nvs_config_t *cfg)
}
}
/* MAC filter (stored as a 6-byte blob in NVS key "filter_mac") */
uint8_t mac_blob[6];
size_t mac_len = 6;
if (nvs_get_blob(handle, "filter_mac", mac_blob, &mac_len) == ESP_OK && mac_len == 6) {
/* Check it's not all zeros (which would mean "no filter") */
uint8_t is_zero = 1;
for (int i = 0; i < 6; i++) {
if (mac_blob[i] != 0) { is_zero = 0; break; }
}
if (!is_zero) {
memcpy(cfg->filter_mac, mac_blob, 6);
cfg->filter_mac_enabled = 1;
ESP_LOGI(TAG, "NVS override: filter_mac=%02X:%02X:%02X:%02X:%02X:%02X",
mac_blob[0], mac_blob[1], mac_blob[2],
mac_blob[3], mac_blob[4], mac_blob[5]);
} else {
cfg->filter_mac_enabled = 0;
ESP_LOGI(TAG, "NVS override: filter_mac disabled (all zeros)");
}
}
/* 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",