From 0f1c5b307982d60f9162801794b76281ee29b5ec Mon Sep 17 00:00:00 2001 From: Robert McMahon Date: Fri, 19 Dec 2025 10:12:32 -0800 Subject: [PATCH] more on console --- components/app_console/app_console.c | 196 ++++++++++++++----- components/wifi_controller/wifi_controller.c | 47 ++--- main/main.c | 8 +- 3 files changed, 167 insertions(+), 84 deletions(-) diff --git a/components/app_console/app_console.c b/components/app_console/app_console.c index dc87117..6935e50 100644 --- a/components/app_console/app_console.c +++ b/components/app_console/app_console.c @@ -1,12 +1,12 @@ -#include -#include #include "app_console.h" #include "esp_console.h" #include "esp_log.h" #include "argtable3/argtable3.h" #include "wifi_cfg.h" #include "iperf.h" -#include "wifi_controller.h" +#include "wifi_controller.h" // Required for Mode Switching +#include +#include // Helper to refresh prompt at end of commands static void end_cmd(void) { @@ -32,7 +32,13 @@ static int cmd_iperf(int argc, char **argv) { } if (iperf_args.help->count > 0) { - printf("Usage: iperf [options]\n"); // ... (Shortened for brevity) + printf("Usage: iperf [options]\n"); + printf(" --start Start traffic\n"); + printf(" --stop Stop traffic\n"); + printf(" --status Show stats\n"); + printf(" --save Save config to NVS\n"); + printf(" -c Set Destination IP\n"); + printf(" --pps Set Packets Per Second\n"); return 0; } @@ -49,10 +55,10 @@ static int cmd_iperf(int argc, char **argv) { if (iperf_args.port->count > 0) { cfg.dport = (uint16_t)iperf_args.port->ival[0]; config_changed = true; } if (iperf_args.len->count > 0) { cfg.send_len = (uint32_t)iperf_args.len->ival[0]; config_changed = true; } if (iperf_args.burst->count > 0) { cfg.burst_count = (uint32_t)iperf_args.burst->ival[0]; config_changed = true; } - if (iperf_args.pps->count > 0) { + if (iperf_args.pps->count > 0) { int pps = iperf_args.pps->ival[0]; if (pps > 0) { - cfg.target_pps = (uint32_t)pps; // Update directly + cfg.target_pps = (uint32_t)pps; config_changed = true; } } @@ -75,15 +81,17 @@ static int cmd_iperf(int argc, char **argv) { if (iperf_args.start->count > 0) iperf_start(); if (iperf_args.status->count > 0) iperf_print_status(); - end_cmd(); // Update Prompt + end_cmd(); return 0; } // ============================================================================ -// COMMAND: monitor +// COMMAND: monitor (Switch STA/MONITOR) // ============================================================================ static struct { - struct arg_lit *start, *stop, *status, *save, *reload; + struct arg_lit *start; + struct arg_lit *stop; + struct arg_lit *status; struct arg_int *channel; struct arg_lit *help; struct arg_end *end; @@ -97,33 +105,30 @@ static int cmd_monitor(int argc, char **argv) { } if (mon_args.help->count > 0) { - printf("Usage: monitor [--start|--stop] [-c ] [--save|--reload]\n"); + printf("Usage: monitor [--start] [--stop] [-c ]\n"); return 0; } - if (mon_args.reload->count > 0) { - wifi_ctl_param_reload(); - printf("Config reloaded from NVS.\n"); - } - + // 1. Handle Channel Set + uint8_t ch = 0; if (mon_args.channel->count > 0) { - wifi_ctl_param_set_monitor_channel((uint8_t)mon_args.channel->ival[0]); - printf("Channel set to %d (RAM).\n", mon_args.channel->ival[0]); - } - - if (mon_args.save->count > 0) { - if (wifi_ctl_param_save()) printf("Configuration saved to NVS.\n"); - else printf("No changes to save (NVS matches RAM).\n"); + ch = (uint8_t)mon_args.channel->ival[0]; + // Note: You could add a setter to wifi_controller here if you want it staged } + // 2. Handle Actions if (mon_args.stop->count > 0) { wifi_ctl_switch_to_sta(WIFI_BW_HT20); printf("Switched to Station Mode.\n"); } if (mon_args.start->count > 0) { - if (wifi_ctl_switch_to_monitor(0, WIFI_BW_HT20) == ESP_OK) printf("Monitor Mode Started.\n"); - else printf("Failed to start Monitor Mode.\n"); + // If ch is 0, controller uses default/staged + if (wifi_ctl_switch_to_monitor(ch, WIFI_BW_HT20) == ESP_OK) { + printf("Monitor Mode Started%s.\n", (ch > 0) ? " (Channel Override)" : ""); + } else { + printf("Failed to start Monitor Mode.\n"); + } } if (mon_args.status->count > 0) { @@ -131,15 +136,15 @@ static int cmd_monitor(int argc, char **argv) { printf("MONITOR STATUS:\n"); printf(" Mode: %s\n", (mode == WIFI_CTL_MODE_MONITOR) ? "MONITOR" : "STATION"); printf(" Active: Ch %d\n", (mode == WIFI_CTL_MODE_MONITOR) ? wifi_ctl_get_monitor_channel() : 0); - printf(" Staged: Ch %d\n", wifi_ctl_param_get_monitor_channel()); + printf(" Frames: %lu\n", (unsigned long)wifi_ctl_get_monitor_frame_count()); } - end_cmd(); // Update Prompt + end_cmd(); return 0; } // ============================================================================ -// COMMAND: scan +// COMMAND: scan (List Networks) // ============================================================================ static struct { struct arg_lit *help; @@ -159,8 +164,18 @@ static int cmd_scan(int argc, char **argv) { } printf("Starting WiFi Scan...\n"); - wifi_scan_config_t scan_config = { .show_hidden = true }; - esp_err_t err = esp_wifi_scan_start(&scan_config, true); + + // Ensure we are in a mode that supports scanning (STA or NULL) + wifi_ctl_switch_to_sta(WIFI_BW_HT20); + + wifi_scan_config_t scan_config = { + .ssid = 0, + .bssid = 0, + .channel = 0, + .show_hidden = true + }; + + esp_err_t err = esp_wifi_scan_start(&scan_config, true); // true = blocking if (err != ESP_OK) { printf("Scan failed: %s\n", esp_err_to_name(err)); return 1; @@ -177,7 +192,11 @@ static int cmd_scan(int argc, char **argv) { printf("%-32s | %-4s | %-4s | %-3s\n", "SSID", "RSSI", "CH", "Auth"); printf("----------------------------------------------------------\n"); for (int i = 0; i < ap_count; i++) { - printf("%-32s | %-4d | %-4d | %d\n", (char *)ap_list[i].ssid, ap_list[i].rssi, ap_list[i].primary, ap_list[i].authmode); + printf("%-32s | %-4d | %-4d | %d\n", + (char *)ap_list[i].ssid, + ap_list[i].rssi, + ap_list[i].primary, + ap_list[i].authmode); } free(ap_list); } @@ -185,51 +204,120 @@ static int cmd_scan(int argc, char **argv) { return 0; } -// Registration +// ============================================================================ +// COMMAND: wifi_config +// ============================================================================ +static struct { + struct arg_str *ssid; + struct arg_str *pass; + struct arg_str *ip; + struct arg_lit *dhcp; + struct arg_lit *help; + struct arg_end *end; +} wifi_args; + +static int cmd_wifi_config(int argc, char **argv) { + int nerrors = arg_parse(argc, argv, (void **)&wifi_args); + if (nerrors > 0) { + arg_print_errors(stderr, wifi_args.end, argv[0]); + return 1; + } + + if (wifi_args.help->count > 0) { + printf("Usage: wifi_config -s -p [-i ] [-d]\n"); + return 0; + } + + if (wifi_args.ssid->count == 0) { + printf("Error: SSID is required (-s)\n"); + return 1; + } + + const char* ssid = wifi_args.ssid->sval[0]; + const char* pass = (wifi_args.pass->count > 0) ? wifi_args.pass->sval[0] : ""; + const char* ip = (wifi_args.ip->count > 0) ? wifi_args.ip->sval[0] : NULL; + bool dhcp = (wifi_args.dhcp->count > 0); + + printf("Saving WiFi Config to NVS: SSID='%s' DHCP=%d\n", ssid, dhcp); + + // This immediately writes to NVS via wifi_cfg.c + wifi_cfg_set_credentials(ssid, pass); + + if (ip) { + char mask[] = "255.255.255.0"; + char gw[32]; + strlcpy(gw, ip, sizeof(gw)); + char *last_dot = strrchr(gw, '.'); + if (last_dot) strcpy(last_dot, ".1"); // Guess Gateway + + wifi_cfg_set_static_ip(ip, mask, gw); + wifi_cfg_set_dhcp(false); + } else { + wifi_cfg_set_dhcp(dhcp); + } + + printf("Config saved. Rebooting to apply...\n"); + esp_restart(); + return 0; +} + +// ============================================================================ +// REGISTRATION +// ============================================================================ + static void register_iperf_cmd(void) { - iperf_args.start = arg_lit0(NULL, "start", "Start"); - iperf_args.stop = arg_lit0(NULL, "stop", "Stop"); + iperf_args.start = arg_lit0(NULL, "start", "Start"); + iperf_args.stop = arg_lit0(NULL, "stop", "Stop"); iperf_args.status = arg_lit0(NULL, "status", "Status"); - iperf_args.save = arg_lit0(NULL, "save", "Save"); + iperf_args.save = arg_lit0(NULL, "save", "Save"); iperf_args.reload = arg_lit0(NULL, "reload", "Reload"); - iperf_args.ip = arg_str0("c", "client", "", "IP"); - iperf_args.port = arg_int0("p", "port", "", "Port"); - iperf_args.pps = arg_int0(NULL, "pps", "", "PPS"); - iperf_args.len = arg_int0(NULL, "len", "", "Len"); - iperf_args.burst = arg_int0(NULL, "burst", "", "Burst"); - iperf_args.help = arg_lit0("h", "help", "Help"); - iperf_args.end = arg_end(20); + iperf_args.ip = arg_str0("c", "client", "", "IP"); + iperf_args.port = arg_int0("p", "port", "", "Port"); + iperf_args.pps = arg_int0(NULL, "pps", "", "PPS"); + iperf_args.len = arg_int0(NULL, "len", "", "Len"); + iperf_args.burst = arg_int0(NULL, "burst", "", "Burst"); + iperf_args.help = arg_lit0("h", "help", "Help"); + iperf_args.end = arg_end(20); const esp_console_cmd_t cmd = { .command = "iperf", .help = "Traffic Gen", .func = &cmd_iperf, .argtable = &iperf_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } static void register_monitor_cmd(void) { - mon_args.start = arg_lit0(NULL, "start", "Start"); - mon_args.stop = arg_lit0(NULL, "stop", "Stop"); - mon_args.status = arg_lit0(NULL, "status", "Status"); - mon_args.save = arg_lit0(NULL, "save", "Save"); - mon_args.reload = arg_lit0(NULL, "reload", "Reload"); - mon_args.channel = arg_int0("c", "channel", "", "Chan"); - mon_args.help = arg_lit0("h", "help", "Help"); - mon_args.end = arg_end(20); + mon_args.start = arg_lit0(NULL, "start", "Start Monitor"); + mon_args.stop = arg_lit0(NULL, "stop", "Stop (STA)"); + mon_args.status = arg_lit0(NULL, "status", "Status"); + mon_args.channel = arg_int0("c", "channel", "", "Channel"); + mon_args.help = arg_lit0("h", "help", "Help"); + mon_args.end = arg_end(20); - const esp_console_cmd_t cmd = { .command = "monitor", .help = "Monitor Mode", .func = &cmd_monitor, .argtable = &mon_args }; + const esp_console_cmd_t cmd = { .command = "monitor", .help = "Switch Mode (STA/Monitor)", .func = &cmd_monitor, .argtable = &mon_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } static void register_scan_cmd(void) { scan_args.help = arg_lit0("h", "help", "Help"); - scan_args.end = arg_end(1); - const esp_console_cmd_t cmd = { .command = "scan", .help = "WiFi Scan", .func = &cmd_scan, .argtable = &scan_args }; + scan_args.end = arg_end(1); + + const esp_console_cmd_t cmd = { .command = "scan", .help = "Scan WiFi", .func = &cmd_scan, .argtable = &scan_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } -// Don't forget to keep your existing register_wifi_cmd ... +static void register_wifi_cmd(void) { + wifi_args.ssid = arg_str0("s", "ssid", "", "SSID"); + wifi_args.pass = arg_str0("p", "password", "", "Pass"); + wifi_args.ip = arg_str0("i", "ip", "", "Static IP"); + wifi_args.dhcp = arg_lit0("d", "dhcp", "DHCP"); + wifi_args.help = arg_lit0("h", "help", "Help"); + wifi_args.end = arg_end(20); + + const esp_console_cmd_t cmd = { .command = "wifi_config", .help = "Setup WiFi Creds", .func = &cmd_wifi_config, .argtable = &wifi_args }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} void app_console_register_commands(void) { register_iperf_cmd(); register_monitor_cmd(); register_scan_cmd(); - // register_wifi_cmd(); // Ensure this is linked + register_wifi_cmd(); } diff --git a/components/wifi_controller/wifi_controller.c b/components/wifi_controller/wifi_controller.c index cb924eb..245a8ba 100644 --- a/components/wifi_controller/wifi_controller.c +++ b/components/wifi_controller/wifi_controller.c @@ -4,15 +4,14 @@ #include "esp_log.h" #include "esp_wifi.h" #include "inttypes.h" +#include "wifi_cfg.h" // Required for apply_from_nvs // Dependencies #include "iperf.h" #include "status_led.h" #include "wifi_monitor.h" #include "gps_sync.h" -#include "wifi_cfg.h" -// 1. GUARDED INCLUDE #ifdef CONFIG_ESP_WIFI_CSI_ENABLED #include "csi_manager.h" #endif @@ -21,15 +20,15 @@ static const char *TAG = "WIFI_CTL"; static wifi_ctl_mode_t s_current_mode = WIFI_CTL_MODE_STA; static uint8_t s_monitor_channel = 6; +static uint8_t s_monitor_channel_staging = 6; + static bool s_monitor_enabled = false; static uint32_t s_monitor_frame_count = 0; static TaskHandle_t s_monitor_stats_task_handle = NULL; -static uint8_t s_monitor_channel_staging = 6; //RAM Staging Variable // --- Helper: Log Collapse Events --- static void log_collapse_event(float nav_duration_us, int rssi, int retry) { gps_timestamp_t ts = gps_get_timestamp(); - // CSV Format: COLLAPSE,MonoMS,GpsMS,Synced,Duration,RSSI,Retry printf("COLLAPSE,%" PRIi64 ",%" PRIi64 ",%d,%.2f,%d,%d\n", ts.monotonic_ms, ts.gps_ms, @@ -43,12 +42,9 @@ static void log_collapse_event(float nav_duration_us, int rssi, int retry) { static void monitor_frame_callback(const wifi_frame_info_t *frame, const uint8_t *payload, uint16_t len) { s_monitor_frame_count++; - - // Check for Collapse conditions (High NAV + Retry) if (frame->retry && frame->duration_id > 5000) { log_collapse_event((float)frame->duration_id, frame->rssi, frame->retry); } - if (frame->duration_id > 30000) { ESP_LOGW("MONITOR", "⚠️ VERY HIGH NAV: %u us", frame->duration_id); } @@ -71,33 +67,42 @@ static void monitor_stats_task(void *arg) { static void auto_monitor_task_func(void *arg) { uint8_t channel = (uint8_t)(uintptr_t)arg; - ESP_LOGI(TAG, "Waiting for WiFi connection before switching to monitor mode..."); - // Wait until LED indicates connected while (status_led_get_state() != LED_STATE_CONNECTED) { vTaskDelay(pdMS_TO_TICKS(500)); } - ESP_LOGI(TAG, "WiFi connected, waiting for GPS sync (2s)..."); vTaskDelay(pdMS_TO_TICKS(2000)); - ESP_LOGI(TAG, "Auto-switching to MONITOR mode on channel %d...", channel); wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20); vTaskDelete(NULL); } // --- API Implementation --- + void wifi_ctl_init(void) { s_current_mode = WIFI_CTL_MODE_STA; s_monitor_enabled = false; s_monitor_frame_count = 0; - // Load Initial Staging from NVS + // ------------------------------------------------------------- + // CRITICAL FIX: Initialize the WiFi Driver via Config + // This calls esp_wifi_init() and esp_wifi_start() + // ------------------------------------------------------------- + if (!wifi_cfg_apply_from_nvs()) { + ESP_LOGW(TAG, "No saved WiFi config found, driver initialized in defaults."); + } else { + ESP_LOGI(TAG, "WiFi driver initialized from NVS."); + } + + // Load Staging Params char mode_ignored[16]; wifi_cfg_get_mode(mode_ignored, &s_monitor_channel_staging); if (s_monitor_channel_staging == 0) s_monitor_channel_staging = 6; } +// --- Parameter Management --- + void wifi_ctl_param_set_monitor_channel(uint8_t channel) { if (channel >= 1 && channel <= 14) { s_monitor_channel_staging = channel; @@ -127,8 +132,10 @@ void wifi_ctl_param_reload(void) { bool wifi_ctl_param_is_unsaved(void) { return wifi_cfg_monitor_channel_is_unsaved(s_monitor_channel_staging); } + +// --- Actions --- + esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t bandwidth) { - // If override is 0, use Staging uint8_t channel = (channel_override > 0) ? channel_override : s_monitor_channel_staging; if (s_current_mode == WIFI_CTL_MODE_MONITOR && s_monitor_channel == channel) { @@ -136,7 +143,6 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t return ESP_OK; } - // Monitor mode typically requires 20MHz if (bandwidth != WIFI_BW_HT20) { ESP_LOGW(TAG, "Forcing bandwidth to 20MHz for monitor mode"); bandwidth = WIFI_BW_HT20; @@ -144,22 +150,17 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t ESP_LOGI(TAG, "Switching to MONITOR MODE (Ch %d)", channel); - // 1. Stop high-level apps iperf_stop(); vTaskDelay(pdMS_TO_TICKS(500)); - // 2. Disable CSI (hardware conflict) - // 2. GUARDED CALL #ifdef CONFIG_ESP_WIFI_CSI_ENABLED csi_mgr_disable(); #endif - // 3. Teardown Station esp_wifi_disconnect(); esp_wifi_stop(); vTaskDelay(pdMS_TO_TICKS(500)); - // 4. Re-init in NULL/Promiscuous Mode esp_wifi_set_mode(WIFI_MODE_NULL); if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) { @@ -174,7 +175,6 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t return ESP_FAIL; } - // 5. Update State s_monitor_enabled = true; s_current_mode = WIFI_CTL_MODE_MONITOR; s_monitor_channel = channel; @@ -195,34 +195,29 @@ esp_err_t wifi_ctl_switch_to_sta(wifi_band_mode_t band_mode) { ESP_LOGI(TAG, "Switching to STA MODE"); - // 1. Stop Monitor Tasks if (s_monitor_stats_task_handle != NULL) { vTaskDelete(s_monitor_stats_task_handle); s_monitor_stats_task_handle = NULL; } - // 2. Stop Monitor Driver if (s_monitor_enabled) { wifi_monitor_stop(); s_monitor_enabled = false; vTaskDelay(pdMS_TO_TICKS(500)); } - // 3. Re-enable Station Mode esp_wifi_set_mode(WIFI_MODE_STA); vTaskDelay(pdMS_TO_TICKS(500)); - // 4. Configure & Connect wifi_config_t wifi_config; esp_wifi_get_config(WIFI_IF_STA, &wifi_config); - wifi_config.sta.channel = 0; // Auto channel scan + wifi_config.sta.channel = 0; esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_start(); vTaskDelay(pdMS_TO_TICKS(500)); esp_wifi_connect(); - // 5. Update State s_current_mode = WIFI_CTL_MODE_STA; status_led_set_state(LED_STATE_WAITING); diff --git a/main/main.c b/main/main.c index 7636fc8..401d609 100644 --- a/main/main.c +++ b/main/main.c @@ -100,7 +100,7 @@ void app_main(void) { csi_mgr_init(); #endif - // 4. Initialize WiFi Controller (Loads config from NVS automatically) + // 4. Initialize WiFi Controller & iPerf wifi_ctl_init(); iperf_param_init(); @@ -108,7 +108,9 @@ void app_main(void) { esp_console_repl_t *repl = NULL; esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); - // CRITICAL: Point the prompt to our mutable buffer + // --------------------------------------------------------- + // CRITICAL FIX: Use the mutable buffer, NOT a string literal + // --------------------------------------------------------- repl_config.prompt = s_cli_prompt; repl_config.max_cmdline_length = 1024; @@ -121,7 +123,6 @@ void app_main(void) { app_console_register_commands(); // 7. Initial Prompt State Check - // (Sets it to "esp32*>" immediately if NVS is empty/dirty on boot) app_console_update_prompt(); // 8. Start Shell @@ -130,6 +131,5 @@ void app_main(void) { printf(" | Type 'help' for commands |\n"); printf(" ==================================================\n"); - // This function runs the REPL loop and does not return ESP_ERROR_CHECK(esp_console_start_repl(repl)); }