diff --git a/get-started/csi_recv_router/main/app_main.c b/get-started/csi_recv_router/main/app_main.c index 97c84c9..926a6d0 100644 --- a/get-started/csi_recv_router/main/app_main.c +++ b/get-started/csi_recv_router/main/app_main.c @@ -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");