feat: Add STATUS counters, WiFi reconnect events, SCANRATE/PROBERATE commands
- Promote CSI packet counter to global, add csi_count= to STATUS - Add uptime_s= (raw seconds) to STATUS for programmatic parsing - Emit EVENT on WiFi reconnect with rssi and ip fields - Add SCANRATE command (5-300s) to tune BLE scan restart interval - Add PROBERATE command (1-300s) to tune probe dedup cooldown
This commit is contained in:
@@ -89,6 +89,8 @@ static volatile led_mode_t s_led_mode = LED_OFF;
|
||||
static volatile int64_t s_last_csi_time = 0;
|
||||
static volatile int64_t s_identify_end_time = 0;
|
||||
static volatile bool s_ota_in_progress = false;
|
||||
static volatile uint32_t s_csi_count = 0;
|
||||
static volatile bool s_wifi_connected = false;
|
||||
|
||||
/* Adaptive sampling */
|
||||
#define WANDER_WINDOW 50
|
||||
@@ -105,9 +107,11 @@ static uint32_t s_energy_buf[WANDER_WINDOW];
|
||||
static uint32_t s_energy_idx = 0;
|
||||
|
||||
/* BLE scanning */
|
||||
#define BLE_SCAN_RESTART_US 30000000LL /* restart scan every 30s to refresh duplicate filter */
|
||||
#define BLE_SCAN_RESTART_DEFAULT_US 30000000LL /* restart scan every 30s to refresh duplicate filter */
|
||||
static int64_t s_ble_scan_interval_us = BLE_SCAN_RESTART_DEFAULT_US;
|
||||
static bool s_ble_enabled = false;
|
||||
static uint8_t s_ble_own_addr_type;
|
||||
static esp_timer_handle_t s_ble_timer = NULL;
|
||||
|
||||
/* Chip temperature sensor */
|
||||
#if SOC_TEMP_SENSOR_SUPPORTED
|
||||
@@ -295,7 +299,6 @@ static void wifi_csi_rx_cb(void *ctx, wifi_csi_info_t *info)
|
||||
s_last_csi_time = esp_timer_get_time();
|
||||
|
||||
const wifi_pkt_rx_ctrl_t *rx_ctrl = &info->rx_ctrl;
|
||||
static int s_count = 0;
|
||||
float compensate_gain = 1.0f;
|
||||
static uint8_t agc_gain = 0;
|
||||
static int8_t fft_gain = 0;
|
||||
@@ -303,9 +306,9 @@ static void wifi_csi_rx_cb(void *ctx, wifi_csi_info_t *info)
|
||||
static uint8_t agc_gain_baseline = 0;
|
||||
static int8_t fft_gain_baseline = 0;
|
||||
esp_csi_gain_ctrl_get_rx_gain(rx_ctrl, &agc_gain, &fft_gain);
|
||||
if (s_count < 100) {
|
||||
if (s_csi_count < 100) {
|
||||
esp_csi_gain_ctrl_record_rx_gain(agc_gain, fft_gain);
|
||||
} else if (s_count == 100) {
|
||||
} else if (s_csi_count == 100) {
|
||||
esp_csi_gain_ctrl_get_rx_gain_baseline(&agc_gain_baseline, &fft_gain_baseline);
|
||||
#if CONFIG_FORCE_GAIN
|
||||
esp_csi_gain_ctrl_set_rx_force_gain(agc_gain_baseline, fft_gain_baseline);
|
||||
@@ -320,21 +323,21 @@ static void wifi_csi_rx_cb(void *ctx, wifi_csi_info_t *info)
|
||||
int pos = 0;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C61
|
||||
if (!s_count) {
|
||||
if (!s_csi_count) {
|
||||
ESP_LOGI(TAG, "================ CSI RECV (UDP) ================");
|
||||
}
|
||||
pos = snprintf(s_udp_buffer, sizeof(s_udp_buffer),
|
||||
"CSI_DATA,%s,%d," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
s_hostname, s_count, MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate,
|
||||
"CSI_DATA,%s,%lu," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
s_hostname, (unsigned long)s_csi_count, MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate,
|
||||
rx_ctrl->noise_floor, fft_gain, agc_gain, rx_ctrl->channel,
|
||||
rx_ctrl->timestamp, rx_ctrl->sig_len, rx_ctrl->rx_state);
|
||||
#else
|
||||
if (!s_count) {
|
||||
if (!s_csi_count) {
|
||||
ESP_LOGI(TAG, "================ CSI RECV (UDP) ================");
|
||||
}
|
||||
pos = snprintf(s_udp_buffer, sizeof(s_udp_buffer),
|
||||
"CSI_DATA,%s,%d," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
s_hostname, s_count, MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate, rx_ctrl->sig_mode,
|
||||
"CSI_DATA,%s,%lu," MACSTR ",%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
|
||||
s_hostname, (unsigned long)s_csi_count, MAC2STR(info->mac), rx_ctrl->rssi, rx_ctrl->rate, rx_ctrl->sig_mode,
|
||||
rx_ctrl->mcs, rx_ctrl->cwb, rx_ctrl->smoothing, rx_ctrl->not_sounding,
|
||||
rx_ctrl->aggregation, rx_ctrl->stbc, rx_ctrl->fec_coding, rx_ctrl->sgi,
|
||||
rx_ctrl->noise_floor, rx_ctrl->ampdu_cnt, rx_ctrl->channel, rx_ctrl->secondary_channel,
|
||||
@@ -373,7 +376,7 @@ static void wifi_csi_rx_cb(void *ctx, wifi_csi_info_t *info)
|
||||
s_energy_idx++;
|
||||
}
|
||||
|
||||
s_count++;
|
||||
s_csi_count++;
|
||||
}
|
||||
|
||||
static void wifi_csi_init()
|
||||
@@ -700,9 +703,10 @@ typedef struct {
|
||||
uint16_t seq_ctrl;
|
||||
} __attribute__((packed)) wifi_ieee80211_mac_hdr_t;
|
||||
|
||||
/* Probe request deduplication: report each MAC at most once per 10 seconds */
|
||||
/* Probe request deduplication: report each MAC at most once per N seconds */
|
||||
#define PROBE_DEDUP_SIZE 32
|
||||
#define PROBE_DEDUP_US 10000000LL
|
||||
#define PROBE_DEDUP_DEFAULT_US 10000000LL
|
||||
static int64_t s_probe_dedup_us = PROBE_DEDUP_DEFAULT_US;
|
||||
|
||||
static struct {
|
||||
uint8_t mac[6];
|
||||
@@ -717,7 +721,7 @@ static bool probe_dedup_check(const uint8_t *mac)
|
||||
|
||||
for (int i = 0; i < PROBE_DEDUP_SIZE; i++) {
|
||||
if (memcmp(s_probe_seen[i].mac, mac, 6) == 0) {
|
||||
if (now - s_probe_seen[i].ts < PROBE_DEDUP_US) {
|
||||
if (now - s_probe_seen[i].ts < s_probe_dedup_us) {
|
||||
return true; /* seen recently, skip */
|
||||
}
|
||||
s_probe_seen[i].ts = now;
|
||||
@@ -879,12 +883,12 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
}
|
||||
|
||||
snprintf(reply, reply_size,
|
||||
"OK STATUS uptime=%s heap=%lu rssi=%d tx_power=%d rate=%d hostname=%s version=%s adaptive=%s motion=%d ble=%s target=%s:%d temp=%.1f",
|
||||
uptime_str, (unsigned long)heap, rssi, (int)s_tx_power_dbm,
|
||||
"OK STATUS uptime=%s uptime_s=%lld heap=%lu rssi=%d tx_power=%d rate=%d hostname=%s version=%s adaptive=%s motion=%d ble=%s target=%s:%d temp=%.1f csi_count=%lu",
|
||||
uptime_str, (long long)up, (unsigned long)heap, rssi, (int)s_tx_power_dbm,
|
||||
s_send_frequency, s_hostname, app_desc->version,
|
||||
s_adaptive ? "on" : "off", s_motion_detected ? 1 : 0,
|
||||
s_ble_enabled ? "on" : "off", s_target_ip, s_target_port,
|
||||
chip_temp);
|
||||
chip_temp, (unsigned long)s_csi_count);
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
@@ -1024,6 +1028,34 @@ static int cmd_handle(const char *cmd, char *reply, size_t reply_size)
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* SCANRATE <5-300> */
|
||||
if (strncmp(cmd, "SCANRATE ", 9) == 0) {
|
||||
int val = atoi(cmd + 9);
|
||||
if (val < 5 || val > 300) {
|
||||
snprintf(reply, reply_size, "ERR SCANRATE range 5-300 seconds");
|
||||
return strlen(reply);
|
||||
}
|
||||
s_ble_scan_interval_us = (int64_t)val * 1000000LL;
|
||||
if (s_ble_timer) {
|
||||
esp_timer_stop(s_ble_timer);
|
||||
esp_timer_start_periodic(s_ble_timer, s_ble_scan_interval_us);
|
||||
}
|
||||
snprintf(reply, reply_size, "OK SCANRATE %ds", val);
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* PROBERATE <1-300> */
|
||||
if (strncmp(cmd, "PROBERATE ", 10) == 0) {
|
||||
int val = atoi(cmd + 10);
|
||||
if (val < 1 || val > 300) {
|
||||
snprintf(reply, reply_size, "ERR PROBERATE range 1-300 seconds");
|
||||
return strlen(reply);
|
||||
}
|
||||
s_probe_dedup_us = (int64_t)val * 1000000LL;
|
||||
snprintf(reply, reply_size, "OK PROBERATE %ds", val);
|
||||
return strlen(reply);
|
||||
}
|
||||
|
||||
/* PROFILE */
|
||||
if (strcmp(cmd, "PROFILE") == 0) {
|
||||
int pos = 0;
|
||||
@@ -1154,6 +1186,37 @@ static void cmd_task(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* --- WiFi event handler --- */
|
||||
|
||||
static void wifi_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
s_wifi_connected = false;
|
||||
ESP_LOGW(TAG, "WiFi disconnected");
|
||||
}
|
||||
if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
bool was_disconnected = !s_wifi_connected;
|
||||
s_wifi_connected = true;
|
||||
|
||||
if (was_disconnected && s_udp_socket >= 0) {
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
|
||||
wifi_ap_record_t ap;
|
||||
int rssi = 0;
|
||||
if (esp_wifi_sta_get_ap_info(&ap) == ESP_OK) {
|
||||
rssi = ap.rssi;
|
||||
}
|
||||
char evt[128];
|
||||
int len = snprintf(evt, sizeof(evt),
|
||||
"EVENT,%s,wifi=reconnected rssi=%d ip=" IPSTR "\n",
|
||||
s_hostname, rssi, IP2STR(&event->ip_info.ip));
|
||||
sendto(s_udp_socket, evt, len, 0,
|
||||
(struct sockaddr *)&s_dest_addr, sizeof(s_dest_addr));
|
||||
ESP_LOGI(TAG, "WiFi reconnected, event sent");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Main --- */
|
||||
|
||||
void app_main()
|
||||
@@ -1167,12 +1230,19 @@ void app_main()
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
/* Register WiFi event handler for reconnect notifications */
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||
WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, wifi_event_handler, NULL, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||
IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL, NULL));
|
||||
|
||||
/**
|
||||
* @brief This helper function configures Wi-Fi, as selected in menuconfig.
|
||||
* Read "Establishing Wi-Fi Connection" section in esp-idf/examples/protocols/README.md
|
||||
* for more information about this function.
|
||||
*/
|
||||
ESP_ERROR_CHECK(example_connect());
|
||||
s_wifi_connected = true;
|
||||
|
||||
/* Apply saved TX power after WiFi is up */
|
||||
esp_wifi_set_max_tx_power(s_tx_power_dbm * 4);
|
||||
@@ -1217,9 +1287,8 @@ void app_main()
|
||||
.callback = ble_scan_restart_timer_cb,
|
||||
.name = "ble_scan",
|
||||
};
|
||||
esp_timer_handle_t ble_timer;
|
||||
esp_timer_create(&ble_timer_args, &ble_timer);
|
||||
esp_timer_start_periodic(ble_timer, BLE_SCAN_RESTART_US);
|
||||
esp_timer_create(&ble_timer_args, &s_ble_timer);
|
||||
esp_timer_start_periodic(s_ble_timer, s_ble_scan_interval_us);
|
||||
|
||||
ESP_LOGI(TAG, "BLE: NimBLE initialized, scan=%s", s_ble_enabled ? "on" : "off");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user