diff --git a/components/app_console/CMakeLists.txt b/components/app_console/CMakeLists.txt new file mode 100644 index 0000000..a87a393 --- /dev/null +++ b/components/app_console/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "app_console.c" + INCLUDE_DIRS "." + REQUIRES console + PRIV_REQUIRES wifi_controller csi_manager status_led gps_sync esp_wifi) diff --git a/components/app_console/app_console.c b/components/app_console/app_console.c new file mode 100644 index 0000000..ac3c1ee --- /dev/null +++ b/components/app_console/app_console.c @@ -0,0 +1,104 @@ +#include "app_console.h" +#include "esp_console.h" +#include "esp_log.h" +#include "argtable3/argtable3.h" +#include +#include +#include + +// Dependencies +#include "wifi_controller.h" +#include "csi_manager.h" +#include "status_led.h" +#include "gps_sync.h" + +// --- Command Handlers --- + +static int cmd_mode_monitor(int argc, char **argv) { + // Default to current channel if not provided + int channel = wifi_ctl_get_monitor_channel(); + + if (argc > 1) { + channel = atoi(argv[1]); + if (channel < 1 || channel > 165) { + printf("Error: Invalid channel %d\n", channel); + return 1; + } + } + + // Default bandwidth HT20 for monitor mode + if (wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20) != ESP_OK) { + printf("Failed to switch to monitor mode\n"); + return 1; + } + return 0; +} + +static int cmd_mode_sta(int argc, char **argv) { + // Simple switch to STA, auto band + if (wifi_ctl_switch_to_sta(WIFI_BAND_MODE_AUTO) != ESP_OK) { + printf("Failed to switch to STA mode\n"); + return 1; + } + printf("Switching to STA mode...\n"); + return 0; +} + +static int cmd_mode_status(int argc, char **argv) { + wifi_ctl_mode_t mode = wifi_ctl_get_mode(); + + printf("\n=== WiFi Mode Status ===\n"); + printf("Current mode: %s\n", mode == WIFI_CTL_MODE_STA ? "STA" : "MONITOR"); + printf("LED state: %d\n", status_led_get_state()); + printf("GPS synced: %s\n", gps_is_synced() ? "Yes" : "No"); + + if (mode == WIFI_CTL_MODE_STA) { + printf("CSI Enabled: %s\n", csi_mgr_is_enabled() ? "Yes" : "No"); + printf("CSI Packets: %lu\n", (unsigned long)csi_mgr_get_packet_count()); + } else { + printf("Monitor Ch: %d\n", wifi_ctl_get_monitor_channel()); + printf("Captured: %lu frames\n", (unsigned long)wifi_ctl_get_monitor_frame_count()); + } + return 0; +} + +static int cmd_csi_dump(int argc, char **argv) { + if (wifi_ctl_get_mode() != WIFI_CTL_MODE_STA) { + printf("Error: CSI only available in STA mode\n"); + return 1; + } + printf("Scheduling CSI dump...\n"); + csi_mgr_schedule_dump(); + return 0; +} + +// --- Registration --- + +void app_console_register_commands(void) { + const esp_console_cmd_t cmds[] = { + { + .command = "mode_monitor", + .help = "Switch to monitor mode (Usage: mode_monitor [channel])", + .func = &cmd_mode_monitor + }, + { + .command = "mode_sta", + .help = "Switch to STA mode", + .func = &cmd_mode_sta + }, + { + .command = "mode_status", + .help = "Show device status", + .func = &cmd_mode_status + }, + { + .command = "csi_dump", + .help = "Dump collected CSI data to UART", + .func = &cmd_csi_dump + }, + }; + + for (int i = 0; i < sizeof(cmds)/sizeof(cmds[0]); i++) { + ESP_ERROR_CHECK(esp_console_cmd_register(&cmds[i])); + } +} diff --git a/components/app_console/app_console.h b/components/app_console/app_console.h new file mode 100644 index 0000000..ab0d830 --- /dev/null +++ b/components/app_console/app_console.h @@ -0,0 +1,15 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Register all application-specific console commands + * (mode_monitor, mode_sta, mode_status, csi_dump) + */ +void app_console_register_commands(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/cmd_transport/#CMakeLists.txt# b/components/cmd_transport/#CMakeLists.txt# new file mode 100644 index 0000000..19e9d3e --- /dev/null +++ b/components/cmd_transport/#CMakeLists.txt# @@ -0,0 +1,7 @@ +idf_component_register(SRCS "cmd_transport.c" + INCLUDE_DIRS "." # This exposes the current dir (with the .h) to consumers + PRIV_REQUIRES esp_console driver soc) + +idf_component_register(SRCS "cmd_transport.c" + INCLUDE_DIRS "." + PRIV_REQUIRES esp_console driver soc) diff --git a/components/cmd_transport/#cmd_transport.c# b/components/cmd_transport/#cmd_transport.c# new file mode 100644 index 0000000..4585e6f --- /dev/null +++ b/components/cmd_transport/#cmd_transport.c# @@ -0,0 +1,303 @@ +// wifi_cfg.c - Refactored to use cmd_transport +#include +#include +#include +#include + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "nvs.h" +#include "esp_netif.h" +#include "esp_wifi.h" +#include "esp_event.h" +#include "esp_check.h" + +#include "wifi_cfg.h" +#include "cmd_transport.h" // Dependency + +static const char *TAG = "wifi_cfg"; +static esp_netif_t *sta_netif = NULL; +static bool cfg_dhcp = true; + +// --- NVS & Helper Functions (Kept from original) --- + +static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){ + return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key); +} + +static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw, const char* powersave, const char* mode, uint8_t mon_ch){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return; + if (ssid) nvs_set_str2(h, "ssid", ssid); + if (pass) nvs_set_str2(h, "pass", pass); + if (ip) nvs_set_str2(h, "ip", ip); + if (mask) nvs_set_str2(h, "mask", mask); + if (gw) nvs_set_str2(h, "gw", gw); + if (band) nvs_set_str2(h, "band", band); + if (bw) nvs_set_str2(h, "bw", bw); + if (powersave) nvs_set_str2(h, "powersave", powersave); + if (mode) nvs_set_str2(h, "mode", mode); + nvs_set_u8(h, "mon_ch", mon_ch); + nvs_set_u8(h, "dhcp", dhcp ? 1 : 0); + nvs_commit(h); + nvs_close(h); + cfg_dhcp = dhcp; + ESP_LOGI(TAG, "Config saved to NVS: SSID=%s Mode=%s MonCh=%d", ssid?ssid:"", mode?mode:"STA", mon_ch); +} + +// ... [Existing load_cfg, apply_ip_static, wifi_ensure_inited, wifi_cfg_apply_from_nvs implementations retained here] ... +// (Omitting full copy-paste of unchanged helper functions for brevity, assume they are present as in your original upload) + +static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, + char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz, + char* band, size_t bsz, char* bw, size_t bwsz, char* powersave, size_t pssz, + char* mode, size_t modesz, uint8_t* mon_ch, bool* dhcp){ + nvs_handle_t h; + if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; + size_t len; + esp_err_t e; + if ((e = nvs_get_str(h, "ssid", NULL, &len)) != ESP_OK){ nvs_close(h); return false; } + if (len >= ssz){ nvs_close(h); return false; } + nvs_get_str(h, "ssid", ssid, &len); + len = psz; e = nvs_get_str(h, "pass", pass, &len); if (e!=ESP_OK) pass[0]=0; + len = isz; e = nvs_get_str(h, "ip", ip, &len); if (e!=ESP_OK) ip[0]=0; + len = msz; e = nvs_get_str(h, "mask", mask, &len); if (e!=ESP_OK) mask[0]=0; + len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0; + len = bsz; e = nvs_get_str(h, "band", band, &len); if (e!=ESP_OK) strcpy(band, "2.4G"); + len = bwsz; e = nvs_get_str(h, "bw", bw, &len); if (e!=ESP_OK) strcpy(bw, "HT20"); + len = pssz; e = nvs_get_str(h, "powersave", powersave, &len); if (e!=ESP_OK) strcpy(powersave, "NONE"); + len = modesz; e = nvs_get_str(h, "mode", mode, &len); if (e!=ESP_OK) strcpy(mode, "STA"); + uint8_t ch=36; nvs_get_u8(h, "mon_ch", &ch); *mon_ch = ch; + uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0); + nvs_close(h); + return true; +} + +// ... [Include apply_ip_static, ensure_net_stack_once, wifi_ensure_inited, wifi_cfg_apply_from_nvs from original file] ... +// (You must keep these functions in the final file) + +// --- Logic for parsing the config lines --- + +static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, char *band, char *bw, char *powersave, char *mode, uint8_t *mon_ch, bool *dhcp){ + if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, 63); ssid[63]=0; return; } + if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, 63); pass[63]=0; return; } + if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, 31); ip[31]=0; return; } + if (strncmp(line, "MASK:",5)==0){ strncpy(mask, line+5, 31); mask[31]=0; return; } + if (strncmp(line, "GW:",3)==0){ strncpy(gw, line+3, 31); gw[31]=0; return; } + if (strncmp(line, "BAND:",5)==0){ strncpy(band, line+5, 15); band[15]=0; return; } + if (strncmp(line, "BW:",3)==0){ strncpy(bw, line+3, 15); bw[15]=0; return; } + if (strncmp(line, "POWERSAVE:",10)==0){ strncpy(powersave, line+10, 15); powersave[15]=0; return; } + if (strncmp(line, "MODE:",5)==0){ strncpy(mode, line+5, 15); mode[15]=0; return; } + if (strncmp(line, "MON_CH:",7)==0){ *mon_ch = atoi(line+7); return; } + if (strncmp(line, "DHCP:",5)==0){ *dhcp = atoi(line+5) ? true:false; return; } +} + +// --- The Listener Callback (Registered with cmd_transport) --- + +static bool wifi_cfg_line_handler(const char *line, cmd_transport_reply_t reply_func, void *reply_ctx) { + // State is static because we receive one line at a time from the transport task + static bool in_cfg = false; + static char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; + static char band[16]={0}, bw[16]={0}, powersave[16]={0}, mode[16]={0}; + static uint8_t mon_ch = 36; + static bool dhcp = true; + + // Check for start of config block + if (strcmp(line, "CFG") == 0) { + in_cfg = true; + // Reset buffers + ssid[0]=0; pass[0]=0; ip[0]=0; mask[0]=0; gw[0]=0; + band[0]=0; bw[0]=0; powersave[0]=0; mode[0]=0; + mon_ch = 36; dhcp = true; + return true; // We handled this line + } + + if (in_cfg) { + if (strcmp(line, "END") == 0) { + // Apply defaults + if (!band[0]) strcpy(band, "2.4G"); + if (!bw[0]) strcpy(bw, "HT20"); + if (!powersave[0]) strcpy(powersave, "NONE"); + if (!mode[0]) strcpy(mode, "STA"); + + save_cfg(ssid, pass, ip, mask, gw, dhcp, band, bw, powersave, mode, mon_ch); + + // Reply "OK" to whoever sent the commands + if (reply_func) { + reply_func("OK\n", reply_ctx); + } + + // Trigger application of new config + // Note: This might block briefly, ideally offload to event loop if heavy + // For now we assume apply_from_nvs is fast enough or acceptable + // To be safe, we could signal an event, but let's keep logic preserved. + wifi_cfg_apply_from_nvs(); + + in_cfg = false; + return true; + } + + // Parse config line + on_cfg_line(line, ssid, pass, ip, mask, gw, band, bw, powersave, mode, &mon_ch, &dhcp); + return true; // Consumed + } + + return false; // Not in config mode, let other listeners (console) handle it +} + +// --- Init --- + +void wifi_cfg_init(void){ + // Ensure NVS is ready + nvs_flash_init(); + + // Initialize the transport layer (starts UART/USB tasks) + cmd_transport_init(); + + // Register our handler + cmd_transport_register_listener(wifi_cfg_line_handler); +} + +// ... [Keep wifi_cfg_get_power_save_mode, wifi_cfg_get_bandwidth, wifi_cfg_get_mode, wifi_cfg_force_dhcp, wifi_ensure_inited] ... + +#include "cmd_transport.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_console.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/soc_caps.h" +#include +#include +#include + +#if SOC_USB_SERIAL_JTAG_SUPPORTED + #include "driver/usb_serial_jtag.h" +#endif + +static const char *TAG = "CMD_TP"; + +// Max listeners +#define MAX_LISTENERS 4 +static cmd_line_callback_t s_listeners[MAX_LISTENERS] = {0}; +static int s_listener_count = 0; +static bool s_inited = false; + +// Register a listener +void cmd_transport_register_listener(cmd_line_callback_t cb) { + if (s_listener_count < MAX_LISTENERS) { + s_listeners[s_listener_count++] = cb; + } else { + ESP_LOGE(TAG, "Max listeners reached"); + } +} + +// Helper: Trim whitespace +static void trim(char *s) { + int n = strlen(s); + while(n > 0 && (s[n-1] == '\r' || s[n-1] == '\n' || isspace((unsigned char)s[n-1]))) s[--n] = 0; + // Note: We don't trim leading whitespace to preserve command indentation if needed, + // but the original code did. We'll stick to trailing trim for safety. +} + +// Dispatch logic +static void dispatch_line(char *line, cmd_transport_reply_t reply_func, void *reply_ctx) { + bool handled = false; + + // 1. Offer to registered listeners (e.g., wifi_cfg) + for (int i = 0; i < s_listener_count; i++) { + if (s_listeners[i] && s_listeners[i](line, reply_func, reply_ctx)) { + handled = true; + break; // Consumed by a listener + } + } + + // 2. If not consumed, pass to ESP Console (for 'mode_monitor', etc.) + if (!handled && strlen(line) > 0) { + int ret; + esp_err_t err = esp_console_run(line, &ret); + if (err == ESP_ERR_NOT_FOUND) { + // Unrecognized command + // Optional: reply_func("Unrecognized command\n", reply_ctx); + } else if (err != ESP_OK) { + ESP_LOGE(TAG, "Console run error: %d", err); + } + } +} + +// ---- UART (stdin/stdout) Support ---- +static void uart_emit(const char *s, void *ctx) { + (void)ctx; + fputs(s, stdout); + fflush(stdout); +} + +static void uart_listener_task(void *arg) { + char line[256]; + // Disable buffering for immediate interaction + setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + + while (1) { + if (fgets(line, sizeof(line), stdin)) { + trim(line); + dispatch_line(line, uart_emit, NULL); + } else { + vTaskDelay(pdMS_TO_TICKS(50)); + } + } +} + +// ---- USB Serial/JTAG Support ---- +#if SOC_USB_SERIAL_JTAG_SUPPORTED +static void usb_emit(const char *s, void *ctx) { + (void)ctx; + usb_serial_jtag_write_bytes((const uint8_t*)s, strlen(s), pdMS_TO_TICKS(50)); +} + +static void usb_listener_task(void *arg) { + // Init driver + usb_serial_jtag_driver_config_t d = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT(); + if (usb_serial_jtag_driver_install(&d) != ESP_OK) { + ESP_LOGE(TAG, "Failed to install USB driver"); + vTaskDelete(NULL); + } + + char buf[256]; + size_t idx = 0; + uint8_t c; + + while (1) { + // Read byte-by-byte to construct lines + int n = usb_serial_jtag_read_bytes(&c, 1, pdMS_TO_TICKS(50)); + if (n > 0) { + if (c == '\n' || c == '\r') { + if (idx > 0) { + buf[idx] = 0; + dispatch_line(buf, usb_emit, NULL); + idx = 0; + } + } else { + if (idx < sizeof(buf) - 1) { + buf[idx++] = (char)c; + } + } + } + } +} +#endif + +void cmd_transport_init(void) { + if (s_inited) return; + s_inited = true; + + // Start UART listener (Always available) + xTaskCreatePinnedToCore(uart_listener_task, "cmd_uart", 4096, NULL, 5, NULL, tskNO_AFFINITY); + + // Start USB listener (If supported) + #if SOC_USB_SERIAL_JTAG_SUPPORTED + xTaskCreatePinnedToCore(usb_listener_task, "cmd_usb", 4096, NULL, 5, NULL, tskNO_AFFINITY); + #endif +} diff --git a/components/gps_sync/gps_sync.c b/components/gps_sync/gps_sync.c index 8731f6e..ff33321 100644 --- a/components/gps_sync/gps_sync.c +++ b/components/gps_sync/gps_sync.c @@ -78,7 +78,6 @@ static void gps_task(void* arg) { static int log_counter = 0; while (1) { - // Using dynamically stored port int len = uart_read_bytes(gps_uart_num, d_buf, sizeof(d_buf), pdMS_TO_TICKS(100)); if (len > 0) { @@ -134,8 +133,41 @@ static void gps_task(void* arg) { } void gps_sync_init(const gps_sync_config_t *config, bool use_gps_log_timestamps) { - ESP_LOGI(TAG, "Initializing GPS sync"); + ESP_LOGI(TAG, "Checking for GPS PPS signal on GPIO %d...", config->pps_pin); + // 1. Configure PPS pin as Input to sense signal + gpio_config_t pps_conf = { + .pin_bit_mask = (1ULL << config->pps_pin), + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, // High-Z to detect active driving + .intr_type = GPIO_INTR_DISABLE + }; + ESP_ERROR_CHECK(gpio_config(&pps_conf)); + + // 2. Poll for ~3 seconds to detect ANY edge transition + bool pps_detected = false; + int start_level = gpio_get_level(config->pps_pin); + + // Poll loop: 3000 iterations * 1ms = 3 seconds + for (int i = 0; i < 3000; i++) { + int current_level = gpio_get_level(config->pps_pin); + if (current_level != start_level) { + pps_detected = true; + break; // Signal found! + } + vTaskDelay(pdMS_TO_TICKS(1)); + } + + if (!pps_detected) { + printf("GPS PPS not found over GPIO with pin number %d\n", config->pps_pin); + ESP_LOGW(TAG, "GPS initialization aborted due to lack of PPS signal."); + return; // ABORT INITIALIZATION + } + + ESP_LOGI(TAG, "PPS signal detected! Initializing GPS subsystem..."); + + // 3. Proceed with Full Initialization gps_uart_num = config->uart_port; use_gps_for_logs = use_gps_log_timestamps; @@ -166,6 +198,7 @@ void gps_sync_init(const gps_sync_config_t *config, bool use_gps_log_timestamps) UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + // Re-configure PPS for Interrupts (Posedge) gpio_config_t io_conf = { .intr_type = GPIO_INTR_POSEDGE, .mode = GPIO_MODE_INPUT, @@ -184,29 +217,16 @@ void gps_sync_init(const gps_sync_config_t *config, bool use_gps_log_timestamps) config->uart_port, config->rx_pin, config->tx_pin, config->pps_pin); } - gps_timestamp_t gps_get_timestamp(void) { gps_timestamp_t ts; - - // Using clock_gettime (POSIX standard, portable) clock_gettime(CLOCK_MONOTONIC, &ts.mono_ts); - xSemaphoreTake(sync_mutex, portMAX_DELAY); - - // Convert timespec to microseconds - ts.monotonic_us = (int64_t)ts.mono_ts.tv_sec * 1000000LL + - ts.mono_ts.tv_nsec / 1000; - - // Convert to milliseconds + ts.monotonic_us = (int64_t)ts.mono_ts.tv_sec * 1000000LL + ts.mono_ts.tv_nsec / 1000; ts.monotonic_ms = ts.monotonic_us / 1000; - - // Calculate GPS time ts.gps_us = ts.monotonic_us + monotonic_offset_us; ts.gps_ms = ts.gps_us / 1000; - ts.synced = gps_has_fix; xSemaphoreGive(sync_mutex); - return ts; } diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index cfc379a..530c5cf 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -19,4 +19,5 @@ idf_component_register( status_led csi_manager wifi_controller + app_console ) diff --git a/main/main.c b/main/main.c index b133c68..def10fb 100644 --- a/main/main.c +++ b/main/main.c @@ -1,7 +1,5 @@ #include #include -#include -#include #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -15,75 +13,22 @@ #include "lwip/inet.h" // Components -#include "iperf.h" +#include "board_config.h" +#include "status_led.h" +#include "gps_sync.h" #include "wifi_cfg.h" #include "csi_log.h" -#include "gps_sync.h" -#include "status_led.h" -#include "board_config.h" #include "csi_manager.h" -#include "wifi_controller.h" // <--- New Component +#include "wifi_controller.h" +#include "app_console.h" // <--- New Component +#include "iperf.h" static const char *TAG = "MAIN"; -// --- Console Commands ---------------------------------------------- - -static int cmd_mode_monitor(int argc, char **argv) { - int channel = wifi_ctl_get_monitor_channel(); - if (argc > 1) channel = atoi(argv[1]); - - if (wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20) != ESP_OK) { - printf("Failed to switch to monitor mode\n"); - return 1; - } - return 0; -} - -static int cmd_mode_sta(int argc, char **argv) { - if (wifi_ctl_switch_to_sta(WIFI_BAND_MODE_AUTO) != ESP_OK) { - printf("Failed to switch to STA mode\n"); - return 1; - } - printf("Switching to STA mode...\n"); - return 0; -} - -static int cmd_mode_status(int argc, char **argv) { - printf("\n=== WiFi Mode Status ===\n"); - printf("Current mode: %s\n", wifi_ctl_get_mode() == WIFI_CTL_MODE_STA ? "STA" : "MONITOR"); - printf("LED state: %d\n", status_led_get_state()); - printf("GPS synced: %s\n", gps_is_synced() ? "Yes" : "No"); - - if (wifi_ctl_get_mode() == WIFI_CTL_MODE_STA) { - printf("CSI Enabled: %s\n", csi_mgr_is_enabled() ? "Yes" : "No"); - printf("CSI Packets: %lu\n", (unsigned long)csi_mgr_get_packet_count()); - } else { - printf("Monitor Channel: %d\n", wifi_ctl_get_monitor_channel()); - printf("Frames Captured: %lu\n", (unsigned long)wifi_ctl_get_monitor_frame_count()); - } - return 0; -} - -static int cmd_csi_dump(int argc, char **argv) { - if (wifi_ctl_get_mode() != WIFI_CTL_MODE_STA) { - printf("Error: CSI only available in STA mode\n"); return 1; - } - csi_mgr_schedule_dump(); - return 0; -} - -static void register_mode_commands(void) { - const esp_console_cmd_t cmds[] = { - { .command = "mode_monitor", .help = "Switch to monitor mode", .func = &cmd_mode_monitor }, - { .command = "mode_sta", .help = "Switch to STA mode", .func = &cmd_mode_sta }, - { .command = "mode_status", .help = "Show status", .func = &cmd_mode_status }, - { .command = "csi_dump", .help = "Dump CSI data", .func = &cmd_csi_dump }, - }; - for(int i=0; i<4; i++) ESP_ERROR_CHECK(esp_console_cmd_register(&cmds[i])); -} - // --- Event Handler ------------------------------------------------- static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { + // Let the controller handle mode transitions, but we handle high-level LED/App logic here + if (event_base == WIFI_EVENT) { if (event_id == WIFI_EVENT_STA_START) { if (wifi_ctl_get_mode() == WIFI_CTL_MODE_STA) { @@ -103,6 +48,8 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip)); status_led_set_state(LED_STATE_CONNECTED); + + // Start App Services csi_mgr_enable_async(); iperf_cfg_t cfg = { .flag = IPERF_FLAG_SERVER | IPERF_FLAG_TCP, .sport = 5001 }; @@ -114,17 +61,15 @@ static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_ // --- Main ---------------------------------------------------------- void app_main(void) { + // 1. System Init ESP_ERROR_CHECK(nvs_flash_init()); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); - // Init Subsystems + // 2. Hardware/Driver Init ESP_ERROR_CHECK(csi_log_init()); status_led_init(RGB_LED_GPIO, HAS_RGB_LED); - csi_mgr_init(); - wifi_ctl_init(); - // Init GPS const gps_sync_config_t gps_cfg = { .uart_port = UART_NUM_1, .tx_pin = GPS_TX_PIN, @@ -133,13 +78,12 @@ void app_main(void) { }; gps_sync_init(&gps_cfg, true); - // Register Events - ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL)); - ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL)); - - // Init Config & Console - wifi_cfg_init(); + // 3. Subsystem Init + csi_mgr_init(); + wifi_ctl_init(); + wifi_cfg_init(); // Starts cmd_transport (UART/USB) + // 4. Console/CLI Init setvbuf(stdin, NULL, _IONBF, 0); esp_console_config_t console_config = { .max_cmdline_args = 8, @@ -148,9 +92,15 @@ void app_main(void) { ESP_ERROR_CHECK(esp_console_init(&console_config)); linenoiseSetMultiLine(1); esp_console_register_help_command(); - register_mode_commands(); - // Apply Config + // Register App Commands + app_console_register_commands(); + + // 5. Register Events + ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL)); + ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL)); + + // 6. Application Start if (wifi_cfg_apply_from_nvs()) { status_led_set_state(LED_STATE_WAITING); @@ -161,5 +111,6 @@ void app_main(void) { } } else { status_led_set_state(LED_STATE_NO_CONFIG); + ESP_LOGW(TAG, "No Config Found. Waiting for setup..."); } }