diff --git a/components/app_console/CMakeLists.txt b/components/app_console/CMakeLists.txt index 2881992..f8aa771 100644 --- a/components/app_console/CMakeLists.txt +++ b/components/app_console/CMakeLists.txt @@ -1,11 +1,15 @@ -idf_component_register(SRCS "app_console.c" - "cmd_system.c" - "cmd_wifi.c" - "cmd_iperf.c" - "cmd_nvs.c" - "cmd_gps.c" - "cmd_ping.c" - "cmd_monitor.c" - "cmd_ip.c" - INCLUDE_DIRS "." - PRIV_REQUIRES console iperf wifi_cfg wifi_controller nvs_flash gps_sync lwip driver) +idf_component_register( + SRCS "app_console.c" + "cmd_wifi.c" + "cmd_iperf.c" + "cmd_system.c" + "cmd_monitor.c" + "cmd_nvs.c" + "cmd_gps.c" + "cmd_ping.c" + "cmd_ip.c" + INCLUDE_DIRS "." + REQUIRES console wifi_cfg + wifi_controller iperf status_led gps_sync + esp_wifi esp_netif nvs_flash spi_flash +) diff --git a/components/app_console/cmd_ip.c b/components/app_console/cmd_ip.c index 79555f6..cce9059 100644 --- a/components/app_console/cmd_ip.c +++ b/components/app_console/cmd_ip.c @@ -30,77 +30,161 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * cmd_ip.c + * + * Copyright (c) 2025 Umber Networks & Robert McMahon + * All rights reserved. + */ + #include #include -#include "esp_log.h" #include "esp_console.h" -#include "argtable3/argtable3.h" #include "esp_netif.h" -#include "esp_mac.h" -#include "lwip/inet.h" +#include "esp_wifi.h" +#include "argtable3/argtable3.h" +#include "wifi_cfg.h" #include "app_console.h" +// --- Arguments --- static struct { - struct arg_lit *addr; - struct arg_lit *help; + struct arg_str *ip; + struct arg_str *mask; + struct arg_str *gw; struct arg_end *end; -} ip_args; +} set_args; -static void print_iface_details(const char* key) { - esp_netif_t *netif = esp_netif_get_handle_from_ifkey(key); - if (!netif) return; +static struct { + struct arg_str *mode; // "on" or "off" + struct arg_end *end; +} dhcp_args; - const char *desc = esp_netif_get_desc(netif); - bool is_up = esp_netif_is_netif_up(netif); - - uint8_t mac[6] = {0}; - esp_netif_get_mac(netif, mac); +static void print_if_info(esp_netif_t *netif, const char *name) { + if (netif == NULL) return; esp_netif_ip_info_t ip_info; - esp_netif_get_ip_info(netif, &ip_info); + if (esp_netif_get_ip_info(netif, &ip_info) == ESP_OK) { + printf("%s:\n", name); + printf(" IP: " IPSTR "\n", IP2STR(&ip_info.ip)); + printf(" Mask: " IPSTR "\n", IP2STR(&ip_info.netmask)); + printf(" GW: " IPSTR "\n", IP2STR(&ip_info.gw)); - printf("%s (%s): <%s>\n", key, desc ? desc : "auth", is_up ? "UP" : "DOWN"); - printf(" link/ether %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + esp_netif_dhcp_status_t status; + esp_netif_dhcpc_get_status(netif, &status); + printf(" DHCP: %s\n", (status == ESP_NETIF_DHCP_STARTED) ? "ON" : "OFF"); - if (is_up && ip_info.ip.addr != 0) { - printf(" inet " IPSTR " netmask " IPSTR " broadcast " IPSTR "\n", - IP2STR(&ip_info.ip), - IP2STR(&ip_info.netmask), - IP2STR(&ip_info.gw)); + uint8_t mac[6] = {0}; + if (esp_netif_get_mac(netif, mac) == ESP_OK) { + printf(" MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + printf("\n"); } } -static int cmd_ip(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void **)&ip_args); - if (nerrors > 0) { - arg_print_errors(stderr, ip_args.end, argv[0]); - return 1; - } - - if (ip_args.help->count > 0) { - printf("Usage: ip [addr]\n"); - return 0; - } - - // Explicitly check standard interfaces - print_iface_details("WIFI_STA_DEF"); - print_iface_details("WIFI_AP_DEF"); - print_iface_details("ETH_DEF"); - +static int do_ip_addr(void) { + print_if_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), "Wi-Fi Station"); return 0; } +static int do_ip_set(int argc, char **argv) { + int nerrors = arg_parse(argc, argv, (void **)&set_args); + if (nerrors > 0) { + arg_print_errors(stderr, set_args.end, argv[0]); + return 1; + } + + const char *ip = set_args.ip->sval[0]; + const char *mask = set_args.mask->sval[0]; + const char *gw = set_args.gw->sval[0]; + + // Validate and Convert (API Fix: esp_ip4addr_aton returns uint32_t) + esp_netif_ip_info_t info = {0}; + info.ip.addr = esp_ip4addr_aton(ip); + info.netmask.addr = esp_ip4addr_aton(mask); + info.gw.addr = esp_ip4addr_aton(gw); + + // Basic validation: 0 means conversion failed (or actual 0.0.0.0) + if (info.ip.addr == 0 || info.netmask.addr == 0) { + printf("Invalid IP format.\n"); + return 1; + } + + // Save + wifi_cfg_set_ipv4(ip, mask, gw); + wifi_cfg_set_dhcp(false); // Implicitly disable DHCP + + // Apply + esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + if (netif) { + esp_netif_dhcpc_stop(netif); + esp_netif_set_ip_info(netif, &info); + printf("Static IP set. DHCP disabled.\n"); + } else { + printf("Saved. Will apply on next init.\n"); + } + return 0; +} + +static int do_ip_dhcp(int argc, char **argv) { + int nerrors = arg_parse(argc, argv, (void **)&dhcp_args); + if (nerrors > 0) { + arg_print_errors(stderr, dhcp_args.end, argv[0]); + return 1; + } + + bool enable = (strcmp(dhcp_args.mode->sval[0], "on") == 0); + wifi_cfg_set_dhcp(enable); + + esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + if (netif) { + if (enable) { + esp_netif_dhcpc_start(netif); + printf("DHCP enabled.\n"); + } else { + esp_netif_dhcpc_stop(netif); + printf("DHCP disabled.\n"); + } + } + return 0; +} + +static void print_ip_usage(void) { + printf("Usage: ip \n"); + printf("Subcommands:\n"); + printf(" addr Show config\n"); + printf(" set Set static IP (Disables DHCP)\n"); + printf(" dhcp Enable/Disable DHCP\n"); +} + +static int cmd_ip(int argc, char **argv) { + if (argc < 2) { + print_ip_usage(); + return 0; + } + if (strcmp(argv[1], "addr") == 0) return do_ip_addr(); + if (strcmp(argv[1], "set") == 0) return do_ip_set(argc - 1, &argv[1]); + if (strcmp(argv[1], "dhcp") == 0) return do_ip_dhcp(argc - 1, &argv[1]); + + print_ip_usage(); + return 1; +} + void register_ip_cmd(void) { - ip_args.addr = arg_lit0("a", "addr", "Show addresses"); - ip_args.help = arg_lit0("h", "help", "Help"); - ip_args.end = arg_end(1); + // Args + set_args.ip = arg_str1(NULL, NULL, "", "IP Address"); + set_args.mask = arg_str1(NULL, NULL, "", "Netmask"); + set_args.gw = arg_str1(NULL, NULL, "", "Gateway"); + set_args.end = arg_end(3); + + dhcp_args.mode = arg_str1(NULL, NULL, "", "Mode"); + dhcp_args.end = arg_end(1); const esp_console_cmd_t cmd = { .command = "ip", - .help = "Show network interfaces", + .help = "IP Config: addr, set, dhcp", + .hint = "", .func = &cmd_ip, - .argtable = &ip_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/components/app_console/cmd_monitor.c b/components/app_console/cmd_monitor.c index 6bac8f8..c67cf1e 100644 --- a/components/app_console/cmd_monitor.c +++ b/components/app_console/cmd_monitor.c @@ -30,105 +30,112 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #include #include -#include #include "esp_log.h" #include "esp_console.h" #include "argtable3/argtable3.h" #include "wifi_controller.h" -#include "iperf.h" #include "app_console.h" -// ============================================================================ -// COMMAND: monitor -// ============================================================================ +// --- Subcommand Arguments --- +static struct { + struct arg_int *channel; + struct arg_end *end; +} start_args; static struct { - struct arg_lit *start, *stop, *status, *save, *reload; - struct arg_lit *clear_nvs; struct arg_int *channel; - struct arg_lit *help; struct arg_end *end; -} mon_args; +} channel_args; -static int cmd_monitor(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void **)&mon_args); +static void print_monitor_usage(void) { + printf("Usage: monitor [args]\n"); + printf("Subcommands:\n"); + printf(" start [-c ] Start Monitor Mode (optional: set channel)\n"); + printf(" stop Stop Monitor Mode\n"); + printf(" status Show current status\n"); + printf(" channel Switch channel (while running)\n"); + printf(" save Save current config to NVS\n"); + printf(" reload Reload config from NVS\n"); + printf(" clear Clear NVS config\n"); +} + +// --- Subcommand Handlers --- + +static int do_monitor_start(int argc, char **argv) { + start_args.channel = arg_int0("c", "channel", "", "Channel (1-13)"); + start_args.end = arg_end(1); + + int nerrors = arg_parse(argc, argv, (void **)&start_args); if (nerrors > 0) { - arg_print_errors(stderr, mon_args.end, argv[0]); + arg_print_errors(stderr, start_args.end, argv[0]); return 1; } - if (mon_args.help->count > 0) { - printf("Usage: monitor [--start|--stop] [-c ] [--save|--reload]\n"); - return 0; + int ch = 0; + if (start_args.channel->count > 0) { + ch = start_args.channel->ival[0]; } - // --- Actions: NVS Management --- - if (mon_args.clear_nvs->count > 0) { - wifi_ctl_param_clear(); - printf("Monitor config cleared (Defaulting to Ch 6).\n"); - app_console_update_prompt(); - return 0; - } - - if (mon_args.reload->count > 0) { - wifi_ctl_param_reload(); - printf("Config reloaded from NVS.\n"); - } - - 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"); - } - - // --- Actions: Mode Switching --- - 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"); - } - - // --- Status --- - if (mon_args.status->count > 0) { - wifi_ctl_mode_t mode = wifi_ctl_get_mode(); - 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: %" PRIu32 "\n", wifi_ctl_get_monitor_frame_count()); - } - - app_console_update_prompt(); + printf("Starting Monitor Mode%s...\n", ch ? " on specific channel" : ""); + wifi_ctl_monitor_start(ch); return 0; } +static int do_monitor_channel(int argc, char **argv) { + channel_args.channel = arg_int1(NULL, NULL, "", "Channel (1-13)"); + channel_args.end = arg_end(1); + + int nerrors = arg_parse(argc, argv, (void **)&channel_args); + if (nerrors > 0) { + arg_print_errors(stderr, channel_args.end, argv[0]); + return 1; + } + + int ch = channel_args.channel->ival[0]; + printf("Switching to Channel %d...\n", ch); + wifi_ctl_set_channel(ch); + return 0; +} + +static int cmd_monitor(int argc, char **argv) { + if (argc < 2) { + print_monitor_usage(); + return 0; + } + + if (strcmp(argv[1], "start") == 0) return do_monitor_start(argc - 1, &argv[1]); + if (strcmp(argv[1], "stop") == 0) { wifi_ctl_stop(); return 0; } + if (strcmp(argv[1], "status") == 0) { wifi_ctl_status(); return 0; } + if (strcmp(argv[1], "save") == 0) { wifi_ctl_param_save(NULL); printf("Saved.\n"); return 0; } + if (strcmp(argv[1], "reload") == 0) { wifi_ctl_param_init(); printf("Reloaded.\n"); return 0; } + if (strcmp(argv[1], "clear") == 0) { wifi_ctl_param_clear(); printf("Cleared.\n"); return 0; } + + if (strcmp(argv[1], "channel") == 0) return do_monitor_channel(argc - 1, &argv[1]); + + if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0) { + print_monitor_usage(); + return 0; + } + + printf("Unknown subcommand '%s'.\n", argv[1]); + print_monitor_usage(); + return 1; +} + 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.clear_nvs = arg_lit0(NULL, "clear-nvs", "Clear NVS"); - mon_args.channel = arg_int0("c", "channel", "", "Chan"); - mon_args.help = arg_lit0("h", "help", "Help"); - mon_args.end = arg_end(20); + start_args.channel = arg_int0("c", "channel", "", "Channel"); + start_args.end = arg_end(1); + + channel_args.channel = arg_int1(NULL, NULL, "", "Channel"); + channel_args.end = arg_end(1); const esp_console_cmd_t cmd = { .command = "monitor", - .help = "Monitor Mode", + .help = "Monitor Mode: start, stop, channel, status", + .hint = "", .func = &cmd_monitor, - .argtable = &mon_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/components/app_console/cmd_nvs.c b/components/app_console/cmd_nvs.c index 3c99dab..15dce39 100644 --- a/components/app_console/cmd_nvs.c +++ b/components/app_console/cmd_nvs.c @@ -30,130 +30,187 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +/* + * cmd_nvs.c + * + * Copyright (c) 2025 Umber Networks & Robert McMahon + * All rights reserved. + */ #include #include #include #include "esp_log.h" #include "esp_console.h" -#include "argtable3/argtable3.h" -#include "nvs.h" #include "nvs_flash.h" -#include "wifi_cfg.h" -#include "iperf.h" +#include "nvs.h" +#include "argtable3/argtable3.h" #include "app_console.h" -// ============================================================================ -// COMMAND: nvs (Storage Management) -// ============================================================================ +static void print_nvs_usage(void) { + printf("Usage: nvs \n"); + printf("Subcommands:\n"); + printf(" dump Dump 'storage' namespace keys and values\n"); + printf(" clear Erase 'storage' namespace (Factory Reset)\n"); +} -static struct { - struct arg_lit *dump; - struct arg_lit *clear_all; - struct arg_lit *help; - struct arg_end *end; -} nvs_args; +static void print_value(nvs_handle_t h, const char *key, nvs_type_t type) { + esp_err_t err; -// --- Helper Functions for Dumping --- - -static void print_nvs_key_str(nvs_handle_t h, const char *key, const char *label) { - char buf[64] = {0}; - size_t len = sizeof(buf); - if (nvs_get_str(h, key, buf, &len) == ESP_OK) { - printf(" %-12s : %s\n", label, buf); - } else { - printf(" %-12s : \n", label); + switch (type) { + case NVS_TYPE_I8: { + int8_t v = 0; + err = nvs_get_i8(h, key, &v); + if (err == ESP_OK) printf("Value: %d (I8)", v); + break; + } + case NVS_TYPE_U8: { + uint8_t v = 0; + err = nvs_get_u8(h, key, &v); + if (err == ESP_OK) printf("Value: %u (U8)", v); + break; + } + case NVS_TYPE_I16: { + int16_t v = 0; + err = nvs_get_i16(h, key, &v); + if (err == ESP_OK) printf("Value: %d (I16)", v); + break; + } + case NVS_TYPE_U16: { + uint16_t v = 0; + err = nvs_get_u16(h, key, &v); + if (err == ESP_OK) printf("Value: %u (U16)", v); + break; + } + case NVS_TYPE_I32: { + int32_t v = 0; + err = nvs_get_i32(h, key, &v); + if (err == ESP_OK) printf("Value: %" PRIi32 " (I32)", v); + break; + } + case NVS_TYPE_U32: { + uint32_t v = 0; + err = nvs_get_u32(h, key, &v); + if (err == ESP_OK) printf("Value: %" PRIu32 " (U32)", v); + break; + } + case NVS_TYPE_I64: { + int64_t v = 0; + err = nvs_get_i64(h, key, &v); + if (err == ESP_OK) printf("Value: %" PRIi64 " (I64)", v); + break; + } + case NVS_TYPE_U64: { + uint64_t v = 0; + err = nvs_get_u64(h, key, &v); + if (err == ESP_OK) printf("Value: %" PRIu64 " (U64)", v); + break; + } + case NVS_TYPE_STR: { + size_t len = 0; + if (nvs_get_str(h, key, NULL, &len) == ESP_OK) { + char *str = malloc(len); + if (nvs_get_str(h, key, str, &len) == ESP_OK) { + printf("Value: \"%s\" (STR)", str); + } + free(str); + } + break; + } + case NVS_TYPE_BLOB: { + size_t len = 0; + if (nvs_get_blob(h, key, NULL, &len) == ESP_OK) { + printf("Value: [BLOB %u bytes]", (unsigned int)len); + } + break; + } + default: + printf("Value: [Unknown Type 0x%02x]", type); + break; } } -static void print_nvs_key_u32(nvs_handle_t h, const char *key, const char *label) { - uint32_t val = 0; - if (nvs_get_u32(h, key, &val) == ESP_OK) { - printf(" %-12s : %" PRIu32 "\n", label, val); - } else { - printf(" %-12s : \n", label); - } -} +static int do_nvs_dump(int argc, char **argv) { + nvs_iterator_t it = NULL; + nvs_handle_t h; -static void print_nvs_key_u8(nvs_handle_t h, const char *key, const char *label) { - uint8_t val = 0; - if (nvs_get_u8(h, key, &val) == ESP_OK) { - printf(" %-12s : %u\n", label, val); - } else { - printf(" %-12s : \n", label); - } -} - -static int cmd_nvs(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void **)&nvs_args); - if (nerrors > 0) { - arg_print_errors(stderr, nvs_args.end, argv[0]); + // 1. Open Handle (Needed to read values) + esp_err_t err = nvs_open("storage", NVS_READONLY, &h); + if (err != ESP_OK) { + printf("Error opening NVS handle: %s\n", esp_err_to_name(err)); return 1; } - if (nvs_args.help->count > 0) { - printf("Usage: nvs [--dump] [--clear-all]\n"); + // 2. Start Iterator + esp_err_t res = nvs_entry_find("nvs", "storage", NVS_TYPE_ANY, &it); + if (res != ESP_OK) { + nvs_close(h); + if (res == ESP_ERR_NVS_NOT_FOUND) { + printf("No NVS entries found in 'storage'.\n"); + } else { + printf("NVS Search Error: %s\n", esp_err_to_name(res)); + } return 0; } - // --- CLEAR ALL --- - if (nvs_args.clear_all->count > 0) { - printf("Erasing ALL settings from NVS...\n"); - wifi_cfg_clear_credentials(); - wifi_cfg_clear_monitor_channel(); - iperf_param_clear(); - printf("Done. Please reboot.\n"); - app_console_update_prompt(); - return 0; + printf("NVS Dump (Namespace: storage):\n"); + printf("%-20s | %-12s | %s\n", "Key", "Type", "Value"); + printf("------------------------------------------------------------\n"); + + while (res == ESP_OK) { + nvs_entry_info_t info; + nvs_entry_info(it, &info); + + printf("%-20s | 0x%02x | ", info.key, info.type); + print_value(h, info.key, info.type); + printf("\n"); + + res = nvs_entry_next(&it); } - // --- DUMP --- - // Note: NVS iterators are complex in ESP-IDF; explicit key listing is often simpler for known keys. - - printf("\n--- [WiFi Config (netcfg)] ---\n"); - nvs_handle_t h; - if (nvs_open("netcfg", NVS_READONLY, &h) == ESP_OK) { - print_nvs_key_str(h, "ssid", "SSID"); - print_nvs_key_str(h, "pass", "Password"); - print_nvs_key_str(h, "ip", "Static IP"); - print_nvs_key_str(h, "mask", "Netmask"); - print_nvs_key_str(h, "gw", "Gateway"); - print_nvs_key_u8 (h, "dhcp", "DHCP"); - print_nvs_key_u8 (h, "mon_ch", "Monitor Ch"); - nvs_close(h); - } else { - printf("Failed to open 'netcfg' namespace (not initialized?).\n"); - } - - printf("\n--- [iPerf Config (storage)] ---\n"); - if (nvs_open("storage", NVS_READONLY, &h) == ESP_OK) { - print_nvs_key_str(h, "iperf_dst_ip", "Dest IP"); - print_nvs_key_u32(h, "iperf_port", "Port"); - print_nvs_key_u32(h, "iperf_pps", "Target PPS"); - print_nvs_key_u32(h, "iperf_len", "Packet Len"); - print_nvs_key_u32(h, "iperf_burst", "Burst"); - print_nvs_key_u8 (h, "gps_enabled", "GPS En"); - nvs_close(h); - } else { - printf("Failed to open 'storage' namespace.\n"); - } - printf("\n"); - - app_console_update_prompt(); + nvs_release_iterator(it); + nvs_close(h); return 0; } -void register_nvs_cmd(void) { - nvs_args.dump = arg_lit0(NULL, "dump", "Show all"); - nvs_args.clear_all = arg_lit0(NULL, "clear-all", "Factory Reset"); - nvs_args.help = arg_lit0("h", "help", "Help"); - nvs_args.end = arg_end(1); +static int do_nvs_clear(int argc, char **argv) { + nvs_handle_t h; + esp_err_t err = nvs_open("storage", NVS_READWRITE, &h); + if (err != ESP_OK) { + printf("Error opening NVS: %s\n", esp_err_to_name(err)); + return 1; + } + err = nvs_erase_all(h); + if (err == ESP_OK) { + nvs_commit(h); + printf("NVS 'storage' namespace erased.\n"); + } else { + printf("Error erasing NVS: %s\n", esp_err_to_name(err)); + } + nvs_close(h); + return (err == ESP_OK) ? 0 : 1; +} + +static int cmd_nvs(int argc, char **argv) { + if (argc < 2) { + print_nvs_usage(); + return 0; + } + + if (strcmp(argv[1], "dump") == 0) return do_nvs_dump(argc - 1, &argv[1]); + if (strcmp(argv[1], "clear") == 0) return do_nvs_clear(argc - 1, &argv[1]); + + print_nvs_usage(); + return 1; +} + +void register_nvs_cmd(void) { const esp_console_cmd_t cmd = { .command = "nvs", - .help = "Storage Management", + .help = "Storage Tools: dump, clear", + .hint = "", .func = &cmd_nvs, - .argtable = &nvs_args }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/components/app_console/cmd_system.c b/components/app_console/cmd_system.c index 5109bb0..4832b4d 100644 --- a/components/app_console/cmd_system.c +++ b/components/app_console/cmd_system.c @@ -32,32 +32,22 @@ */ #include #include -#include #include "esp_log.h" #include "esp_console.h" -#include "argtable3/argtable3.h" -#include "esp_system.h" #include "esp_chip_info.h" -#include "esp_mac.h" -#include "esp_heap_caps.h" +#include "esp_flash.h" +#include "esp_system.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" +#include "argtable3/argtable3.h" #include "app_console.h" -static const char *TAG = "CMD_SYS"; - -// ============================================================================ -// COMMAND: system (Reboot, Info, Heap) -// ============================================================================ - -static struct { - struct arg_lit *reboot; - struct arg_lit *info; - struct arg_lit *heap; - struct arg_lit *help; - struct arg_end *end; -} sys_args; +// Define default version if not passed by CMake +#ifndef APP_VERSION +#define APP_VERSION "2.0.0-SHELL" +#endif +// --- Helper: Convert Model ID to String --- static const char* get_chip_model_string(esp_chip_model_t model) { switch (model) { case CHIP_ESP32: return "ESP32"; @@ -67,98 +57,111 @@ static const char* get_chip_model_string(esp_chip_model_t model) { case CHIP_ESP32C2: return "ESP32-C2"; case CHIP_ESP32C6: return "ESP32-C6"; case CHIP_ESP32H2: return "ESP32-H2"; -#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)) - case CHIP_ESP32C5: return "ESP32-C5"; // Requires recent IDF + // Explicitly handle ID 23 for C5 if macro is missing + case 23: return "ESP32-C5"; +#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)) && defined(CHIP_ESP32P4) case CHIP_ESP32P4: return "ESP32-P4"; #endif - default: return "Unknown"; +#ifdef CHIP_ESP32C5 + case CHIP_ESP32C5: return "ESP32-C5"; +#endif + default: return "Unknown"; } } -static int cmd_system(int argc, char **argv) { - int nerrors = arg_parse(argc, argv, (void **)&sys_args); - if (nerrors > 0) { - arg_print_errors(stderr, sys_args.end, argv[0]); - return 1; +// --- Command Handlers --- + +static int do_system_reboot(int argc, char **argv) { + printf("Rebooting...\n"); + esp_restart(); + return 0; +} + +static int do_version(int argc, char **argv) { + printf("APP_VERSION: %s\n", APP_VERSION); + printf("IDF_VERSION: %s\n", esp_get_idf_version()); + return 0; +} + +static int do_system_info(int argc, char **argv) { + esp_chip_info_t info; + esp_chip_info(&info); + + const char *model_str = get_chip_model_string(info.model); + + printf("IDF Version: %s\n", esp_get_idf_version()); + + if (strcmp(model_str, "Unknown") == 0) { + printf("Chip Info: Model=%s (ID=%d), Cores=%d, Revision=%d\n", + model_str, info.model, info.cores, info.revision); + } else { + printf("Chip Info: Model=%s, Cores=%d, Revision=%d\n", + model_str, info.cores, info.revision); } - if (sys_args.help->count > 0) { - printf("Usage: system [--reboot|--info|--heap]\n"); - printf(" --reboot Restart the device immediately\n"); - printf(" --info Show chip model, revision, and MAC\n"); - printf(" --heap Show current memory statistics\n"); - return 0; + uint32_t flash_size = 0; + if (esp_flash_get_size(NULL, &flash_size) == ESP_OK) { + printf("Flash Size: %" PRIu32 " MB\n", flash_size / (1024 * 1024)); + } else { + printf("Flash Size: Unknown\n"); } - // --- HEAP STATS --- - if (sys_args.heap->count > 0) { - uint32_t free_heap = esp_get_free_heap_size(); - uint32_t min_heap = esp_get_minimum_free_heap_size(); - - printf("Heap Summary:\n"); - printf(" Free Heap: %" PRIu32 " bytes\n", free_heap); - printf(" Min Free Ever: %" PRIu32 " bytes\n", min_heap); - - uint32_t internal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - uint32_t dma = heap_caps_get_free_size(MALLOC_CAP_DMA); - printf(" Internal (SRAM): %" PRIu32 " bytes\n", internal); - printf(" DMA Capable: %" PRIu32 " bytes\n", dma); - } - - // --- CHIP INFO --- - if (sys_args.info->count > 0) { - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); - - printf("Hardware Info:\n"); - printf(" Model: %s\n", get_chip_model_string(chip_info.model)); - printf(" Cores: %d\n", chip_info.cores); - // Revision format is typically MXX (Major, Minor) - printf(" Revision: v%d.%02d\n", chip_info.revision / 100, chip_info.revision % 100); - - printf(" Features: "); - if (chip_info.features & CHIP_FEATURE_WIFI_BGN) printf("WiFi-BGN "); - if (chip_info.features & CHIP_FEATURE_BLE) printf("BLE "); - if (chip_info.features & CHIP_FEATURE_BT) printf("BT "); - if (chip_info.features & CHIP_FEATURE_EMB_FLASH) printf("Emb-Flash "); - if (chip_info.features & CHIP_FEATURE_IEEE802154) printf("802.15.4 (Zigbee/Thread) "); - printf("\n"); - - uint8_t mac[6]; - if (esp_read_mac(mac, ESP_MAC_WIFI_STA) == ESP_OK) { - printf(" MAC (STA): %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - } - - if (esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP) == ESP_OK) { - printf(" MAC (AP): %02x:%02x:%02x:%02x:%02x:%02x\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - } - } - - // --- REBOOT --- - if (sys_args.reboot->count > 0) { - ESP_LOGW(TAG, "Reboot requested by user."); - printf("Rebooting system in 1 second...\n"); - vTaskDelay(pdMS_TO_TICKS(1000)); - esp_restart(); - } + printf("Features: %s%s%s%s%s\n", + (info.features & CHIP_FEATURE_WIFI_BGN) ? "802.11bgn " : "", + (info.features & CHIP_FEATURE_BLE) ? "BLE " : "", + (info.features & CHIP_FEATURE_BT) ? "BT " : "", + (info.features & CHIP_FEATURE_IEEE802154) ? "802.15.4 " : "", + (info.features & CHIP_FEATURE_EMB_FLASH) ? "Embedded-Flash " : ""); return 0; } -void register_system_cmd(void) { - sys_args.reboot = arg_lit0(NULL, "reboot", "Reboot device"); - sys_args.info = arg_lit0(NULL, "info", "Chip Info"); - sys_args.heap = arg_lit0(NULL, "heap", "Memory Info"); - sys_args.help = arg_lit0("h", "help", "Help"); - sys_args.end = arg_end(1); +static int do_system_heap(int argc, char **argv) { + printf("Heap Info:\n"); + printf(" Free: %" PRIu32 " bytes\n", esp_get_free_heap_size()); + printf(" Min Free: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size()); + return 0; +} +static int cmd_system(int argc, char **argv) { + if (argc < 2) { + printf("Usage: system \n"); + return 0; + } + if (strcmp(argv[1], "reboot") == 0) return do_system_reboot(argc - 1, &argv[1]); + if (strcmp(argv[1], "info") == 0) return do_system_info(argc - 1, &argv[1]); + if (strcmp(argv[1], "heap") == 0) return do_system_heap(argc - 1, &argv[1]); + + printf("Unknown subcommand '%s'.\n", argv[1]); + return 1; +} + +// --- Registration --- + +void register_system_cmd(void) { const esp_console_cmd_t cmd = { .command = "system", - .help = "System Management (Reboot, Info, Heap)", + .help = "System Tools: reboot, info, heap", + .hint = "", .func = &cmd_system, - .argtable = &sys_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +void register_reset_cmd(void) { + const esp_console_cmd_t cmd = { + .command = "reset", + .help = "Software reset of the device", + .func = &do_system_reboot, + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +void register_version_cmd(void) { + const esp_console_cmd_t cmd = { + .command = "version", + .help = "Get firmware version", + .func = &do_version, }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/components/app_console/cmd_wifi.c b/components/app_console/cmd_wifi.c index b35a7b2..ba7a010 100644 --- a/components/app_console/cmd_wifi.c +++ b/components/app_console/cmd_wifi.c @@ -35,362 +35,185 @@ #include "esp_log.h" #include "esp_console.h" #include "argtable3/argtable3.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" #include "esp_wifi.h" -#include "esp_netif.h" #include "wifi_cfg.h" #include "wifi_controller.h" #include "app_console.h" -// --- Forward Declarations --- -static int wifi_do_scan(int argc, char **argv); -static int wifi_do_connect(int argc, char **argv); -static int wifi_do_disconnect(int argc, char **argv); -static int wifi_do_link(int argc, char **argv); -static int wifi_do_power(int argc, char **argv); -static int wifi_do_mode(int argc, char **argv); +// --- Arguments --- +static struct { + struct arg_str *ssid; + struct arg_str *password; + struct arg_end *end; +} connect_args; -// ============================================================================ -// COMMAND: wifi (Dispatcher) -// ============================================================================ +static struct { + struct arg_str *mode; // "sta", "monitor", "ap" + struct arg_int *channel; + struct arg_end *end; +} mode_args; + +static struct { + struct arg_int *tx_power; + struct arg_end *end; +} power_args; static void print_wifi_usage(void) { printf("Usage: wifi [args]\n"); printf("Subcommands:\n"); - printf(" scan Scan for networks\n"); - printf(" connect Connect to an AP (alias: join)\n"); - printf(" disconnect Disconnect from AP\n"); - printf(" status Show connection status (alias: link)\n"); - printf(" power Set power save (on/off)\n"); - printf(" mode Set mode (sta/monitor)\n"); - printf("\nType 'wifi --help' for details.\n"); + printf(" scan Scan for networks\n"); + printf(" connect [] Connect to AP\n"); + printf(" status Show connection info\n"); + printf(" mode [-c ] Switch Mode\n"); + printf(" power Set TX Power (8-84, 0.25dB units)\n"); } -static int cmd_wifi(int argc, char **argv) { - if (argc < 2 || strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { - print_wifi_usage(); - return 0; - } - - if (strcmp(argv[1], "scan") == 0) return wifi_do_scan(argc - 1, &argv[1]); - if (strcmp(argv[1], "connect") == 0) return wifi_do_connect(argc - 1, &argv[1]); - if (strcmp(argv[1], "join") == 0) return wifi_do_connect(argc - 1, &argv[1]); - if (strcmp(argv[1], "disconnect") == 0) return wifi_do_disconnect(argc - 1, &argv[1]); - if (strcmp(argv[1], "status") == 0) return wifi_do_link(argc - 1, &argv[1]); - if (strcmp(argv[1], "link") == 0) return wifi_do_link(argc - 1, &argv[1]); - if (strcmp(argv[1], "power") == 0) return wifi_do_power(argc - 1, &argv[1]); - if (strcmp(argv[1], "mode") == 0) return wifi_do_mode(argc - 1, &argv[1]); - - printf("Unknown subcommand '%s'.\n", argv[1]); - print_wifi_usage(); - return 1; -} - -// ---------------------------------------------------------------------------- -// Sub-command: wifi status / link -// ---------------------------------------------------------------------------- -static struct { - struct arg_lit *help; - struct arg_end *end; -} link_args; - -static int wifi_do_link(int argc, char **argv) { - link_args.help = arg_lit0("h", "help", "Help"); - link_args.end = arg_end(1); - - if (arg_parse(argc, argv, (void **)&link_args) == 0) { - if (link_args.help->count > 0) { - printf("Usage: wifi status\nDescription: Show connection status.\n"); - goto exit; - } - } - - wifi_ap_record_t ap_info; - if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { - printf("Connected to %02x:%02x:%02x:%02x:%02x:%02x (on esp32)\n", - ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], - ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]); - printf("\tSSID: %s\n", ap_info.ssid); - printf("\tfreq: %d (Primary)\n", ap_info.primary); - printf("\tsignal: %d dBm\n", ap_info.rssi); - - esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); - esp_netif_ip_info_t ip; - if (netif && esp_netif_get_ip_info(netif, &ip) == ESP_OK) { - printf("\tIP: " IPSTR "\n", IP2STR(&ip.ip)); - } - } else { - printf("Not connected.\n"); - } - - wifi_ps_type_t ps_type; - if (esp_wifi_get_ps(&ps_type) == ESP_OK) { - printf("\tPower Save: %s\n", (ps_type == WIFI_PS_NONE) ? "off" : "on"); - } - -exit: - return 0; -} - -// ---------------------------------------------------------------------------- -// Sub-command: wifi power -// ---------------------------------------------------------------------------- -static struct { - struct arg_lit *on; - struct arg_lit *off; - struct arg_lit *help; - struct arg_end *end; -} power_args; - -static int wifi_do_power(int argc, char **argv) { - power_args.on = arg_lit0(NULL, "on", "Enable Power Save"); - power_args.off = arg_lit0(NULL, "off", "Disable Power Save"); - power_args.help = arg_lit0("h", "help", "Help"); - power_args.end = arg_end(1); - - int nerrors = arg_parse(argc, argv, (void **)&power_args); - if (nerrors > 0) { - arg_print_errors(stderr, power_args.end, argv[0]); - return 1; - } - if (power_args.help->count > 0) { - printf("Usage: wifi power [on|off]\n"); - return 0; - } - if (power_args.on->count > 0) { - esp_wifi_set_ps(WIFI_PS_MIN_MODEM); - printf("Power save enabled (WIFI_PS_MIN_MODEM).\n"); - } else if (power_args.off->count > 0) { - esp_wifi_set_ps(WIFI_PS_NONE); - printf("Power save disabled (WIFI_PS_NONE).\n"); - } else { - wifi_ps_type_t ps_type; - esp_wifi_get_ps(&ps_type); - printf("Current Power Save Mode: %s\n", (ps_type == WIFI_PS_NONE) ? "OFF" : "ON"); - } - return 0; -} - -// ---------------------------------------------------------------------------- -// Sub-command: wifi mode -// ---------------------------------------------------------------------------- -static struct { - struct arg_lit *sta; - struct arg_lit *monitor; - struct arg_lit *help; - struct arg_end *end; -} mode_args; - -static int wifi_do_mode(int argc, char **argv) { - mode_args.sta = arg_lit0(NULL, "sta", "Station Mode"); - mode_args.monitor = arg_lit0(NULL, "monitor", "Monitor Mode"); - mode_args.help = arg_lit0("h", "help", "Help"); - mode_args.end = arg_end(1); - - int nerrors = arg_parse(argc, argv, (void **)&mode_args); - if (nerrors > 0) { - arg_print_errors(stderr, mode_args.end, argv[0]); - return 1; - } - if (mode_args.help->count > 0) { - printf("Usage: wifi mode [sta|monitor]\n"); - return 0; - } - if (mode_args.sta->count > 0) { - wifi_ctl_switch_to_sta(WIFI_BW_HT20); - printf("Switched to STATION mode.\n"); - } else if (mode_args.monitor->count > 0) { - wifi_ctl_switch_to_monitor(0, WIFI_BW_HT20); - printf("Switched to MONITOR mode.\n"); - } else { - wifi_ctl_mode_t mode = wifi_ctl_get_mode(); - printf("Current Mode: %s\n", (mode == WIFI_CTL_MODE_MONITOR) ? "MONITOR" : "STATION"); - } - return 0; -} - -// ---------------------------------------------------------------------------- -// Sub-command: wifi scan -// ---------------------------------------------------------------------------- -static struct { - struct arg_lit *help; - struct arg_end *end; -} scan_args; +// --- Handlers --- static int wifi_do_scan(int argc, char **argv) { - scan_args.help = arg_lit0("h", "help", "Help"); - scan_args.end = arg_end(1); - - if (arg_parse(argc, argv, (void **)&scan_args) == 0) { - if (scan_args.help->count > 0) { - printf("Usage: wifi scan\n"); - return 0; - } - } - if (wifi_ctl_get_mode() == WIFI_CTL_MODE_MONITOR) { - printf("Error: Cannot scan while in Monitor Mode.\n"); - return 1; - } - wifi_scan_config_t scan_config = {0}; - scan_config.show_hidden = true; printf("Scanning...\n"); - esp_err_t err = esp_wifi_scan_start(&scan_config, true); - if (err == ESP_ERR_WIFI_STATE) { - printf("WARN: Interface busy. Forcing disconnect for scan...\n"); - esp_wifi_disconnect(); - vTaskDelay(pdMS_TO_TICKS(100)); - err = esp_wifi_scan_start(&scan_config, true); - } - if (err != ESP_OK) { - printf("Scan failed: %s\n", esp_err_to_name(err)); - return 1; - } - uint16_t ap_count = 0; - esp_wifi_scan_get_ap_num(&ap_count); - if (ap_count == 0) { - printf("No networks found.\n"); - return 0; - } - wifi_ap_record_t *ap_info = (wifi_ap_record_t *)malloc(sizeof(wifi_ap_record_t) * ap_count); - if (!ap_info) { - printf("Out of memory.\n"); - return 1; - } - ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_count, ap_info)); - printf("Found %u unique BSSIDs\n", ap_count); + wifi_scan_config_t scan_config = {0}; + esp_wifi_scan_start(&scan_config, true); // Block until done - // FORMATTING: Using exact width specifiers for Header and Data to ensure alignment - // SSID: 32 chars | BSSID: 17 chars | RSSI: 4 chars | Ch: 3 chars | Auth - printf("%-32s | %-17s | %4s | %3s | %s\n", "SSID", "BSSID", "RSSI", "Ch", "Auth"); - printf("--------------------------------------------------------------------------------------\n"); + uint16_t ap_num = 0; + esp_wifi_scan_get_ap_num(&ap_num); - for (int i = 0; i < ap_count; i++) { - char *authmode = "UNK"; - switch (ap_info[i].authmode) { - case WIFI_AUTH_OPEN: authmode = "OPEN"; break; - case WIFI_AUTH_WEP: authmode = "WEP"; break; - case WIFI_AUTH_WPA_PSK: authmode = "WPA"; break; - case WIFI_AUTH_WPA2_PSK: authmode = "WPA2"; break; - case WIFI_AUTH_WPA_WPA2_PSK: authmode = "WPA/2"; break; - case WIFI_AUTH_WPA3_PSK: authmode = "WPA3"; break; - case WIFI_AUTH_WPA2_WPA3_PSK: authmode = "W2/W3"; break; - default: break; - } + wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(ap_num * sizeof(wifi_ap_record_t)); + ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, ap_list)); - printf("%-32.32s | %02x:%02x:%02x:%02x:%02x:%02x | %4d | %3d | %s\n", - ap_info[i].ssid, - ap_info[i].bssid[0], ap_info[i].bssid[1], ap_info[i].bssid[2], - ap_info[i].bssid[3], ap_info[i].bssid[4], ap_info[i].bssid[5], - ap_info[i].rssi, ap_info[i].primary, authmode); + printf("Found %d APs:\n", ap_num); + printf("%-32s | %-4s | %-4s | %-18s\n", "SSID", "RSSI", "CH", "BSSID"); + for (int i = 0; i < ap_num; i++) { + printf("%-32s | %-4d | %-4d | %02x:%02x:%02x:%02x:%02x:%02x\n", + ap_list[i].ssid, ap_list[i].rssi, ap_list[i].primary, + ap_list[i].bssid[0], ap_list[i].bssid[1], ap_list[i].bssid[2], + ap_list[i].bssid[3], ap_list[i].bssid[4], ap_list[i].bssid[5]); } - printf("--------------------------------------------------------------------------------------\n"); - free(ap_info); + free(ap_list); return 0; } -// ---------------------------------------------------------------------------- -// Sub-command: wifi connect / join -// ---------------------------------------------------------------------------- -static struct { - struct arg_str *ssid; - struct arg_str *password; - struct arg_str *bssid; - struct arg_lit *help; - struct arg_end *end; -} connect_args; - -// ... [Keep existing includes and declarations] ... - static int wifi_do_connect(int argc, char **argv) { - // Initialize argtable members - connect_args.ssid = arg_str1(NULL, NULL, "", "SSID"); - connect_args.password = arg_str0(NULL, NULL, "", "Password"); - connect_args.bssid = arg_str0("b", "bssid", "", "Lock BSSID"); - connect_args.help = arg_lit0("h", "help", "Help"); - connect_args.end = arg_end(2); - int nerrors = arg_parse(argc, argv, (void **)&connect_args); if (nerrors > 0) { arg_print_errors(stderr, connect_args.end, argv[0]); return 1; } - if (connect_args.help->count > 0) { - printf("Usage: wifi connect [password] [-b ]\n"); - return 0; - } - const char *ssid = connect_args.ssid->sval[0]; const char *pass = (connect_args.password->count > 0) ? connect_args.password->sval[0] : ""; - const char *bssid = (connect_args.bssid->count > 0) ? connect_args.bssid->sval[0] : ""; - // 1. Ensure we are in Station Mode + // Ensure we are in STA mode first wifi_ctl_mode_t current_mode = wifi_ctl_get_mode(); if (current_mode != WIFI_CTL_MODE_STA) { printf("Switching to Station Mode first...\n"); - wifi_ctl_switch_to_sta(WIFI_BW_HT20); + wifi_ctl_switch_to_sta(); // Fixed: Removed argument } - printf("Connecting to '%s' (BSSID: %s)...\n", ssid, bssid[0] ? bssid : "Any"); + printf("Connecting to '%s'...\n", ssid); - // 2. Save to NVS (Persistent) - wifi_cfg_set_credentials(ssid, pass, bssid); - wifi_cfg_set_dhcp(true); + // Save to NVS + wifi_cfg_set_ssid(ssid); + wifi_cfg_set_password(pass); - // 3. Apply to Runtime Driver (Hot Reload) + // Apply wifi_config_t wifi_config = {0}; - strlcpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); - strlcpy((char *)wifi_config.sta.password, pass, sizeof(wifi_config.sta.password)); + strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); + strncpy((char *)wifi_config.sta.password, pass, sizeof(wifi_config.sta.password)); - // Default security settings - wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; - wifi_config.sta.pmf_cfg.capable = true; - wifi_config.sta.pmf_cfg.required = false; + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); + ESP_ERROR_CHECK(esp_wifi_connect()); - // Handle BSSID Locking - if (bssid[0]) { - unsigned int mac[6]; - if (sscanf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x", - &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6) { - for(int i=0; i<6; i++) wifi_config.sta.bssid[i] = (uint8_t)mac[i]; - wifi_config.sta.bssid_set = true; - } else { - printf("Warning: Invalid BSSID format ignored.\n"); - } + return 0; +} + +static int wifi_do_status(int argc, char **argv) { + wifi_ctl_status(); + return 0; +} + +static int wifi_do_mode(int argc, char **argv) { + int nerrors = arg_parse(argc, argv, (void **)&mode_args); + if (nerrors > 0) { + arg_print_errors(stderr, mode_args.end, argv[0]); + return 1; } - // Force Disconnect -> Set Config -> Reconnect - esp_wifi_disconnect(); - esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifi_config); - if (err == ESP_OK) { - esp_wifi_connect(); - printf("Connection initiated (Check 'wifi status').\n"); + const char *mode_str = mode_args.mode->sval[0]; + int channel = (mode_args.channel->count > 0) ? mode_args.channel->ival[0] : 0; + + if (strcmp(mode_str, "sta") == 0) { + wifi_ctl_switch_to_sta(); // Fixed: Removed argument + } else if (strcmp(mode_str, "monitor") == 0) { + wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20); } else { - printf("Failed to apply configuration: %s\n", esp_err_to_name(err)); + printf("Unknown mode '%s'. Use 'sta' or 'monitor'.\n", mode_str); + return 1; + } + return 0; +} + +static int wifi_do_power(int argc, char **argv) { + int nerrors = arg_parse(argc, argv, (void **)&power_args); + if (nerrors > 0) { + arg_print_errors(stderr, power_args.end, argv[0]); + return 1; } + int pwr = power_args.tx_power->ival[0]; + esp_err_t err = esp_wifi_set_max_tx_power(pwr); + if (err == ESP_OK) { + printf("TX Power set to %d (approx %.2f dBm)\n", pwr, pwr * 0.25); + } else { + printf("Failed to set TX power: %s\n", esp_err_to_name(err)); + } return 0; } -// ---------------------------------------------------------------------------- -// Sub-command: wifi disconnect -// ---------------------------------------------------------------------------- -static int wifi_do_disconnect(int argc, char **argv) { - printf("Disconnecting...\n"); - esp_wifi_disconnect(); - return 0; -} +static int cmd_wifi(int argc, char **argv) { + if (argc < 2) { + print_wifi_usage(); + return 0; + } -// ---------------------------------------------------------------------------- -// Registration -// ---------------------------------------------------------------------------- + if (strcmp(argv[1], "scan") == 0) return wifi_do_scan(argc - 1, &argv[1]); + if (strcmp(argv[1], "connect") == 0) return wifi_do_connect(argc - 1, &argv[1]); + if (strcmp(argv[1], "status") == 0) return wifi_do_status(argc - 1, &argv[1]); + if (strcmp(argv[1], "mode") == 0) return wifi_do_mode(argc - 1, &argv[1]); + if (strcmp(argv[1], "power") == 0) return wifi_do_power(argc - 1, &argv[1]); + + if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0) { + print_wifi_usage(); + return 0; + } + + printf("Unknown subcommand '%s'.\n", argv[1]); + print_wifi_usage(); + return 1; +} void register_wifi_cmd(void) { + // Connect Args + connect_args.ssid = arg_str1(NULL, NULL, "", "SSID"); + connect_args.password = arg_str0(NULL, NULL, "", "Password"); + connect_args.end = arg_end(2); + + // Mode Args + mode_args.mode = arg_str1(NULL, NULL, "", "sta | monitor"); + mode_args.channel = arg_int0("c", "channel", "", "Channel (Monitor only)"); + mode_args.end = arg_end(2); + + // Power Args + power_args.tx_power = arg_int1(NULL, NULL, "", "Power (8-84)"); + power_args.end = arg_end(1); + const esp_console_cmd_t cmd = { .command = "wifi", - .help = "Wi-Fi Tool: scan, connect, status, power, mode", - .hint = " [args]", + .help = "Wi-Fi Utils: scan, connect, mode, status, power", + .hint = "", .func = &cmd_wifi, - .argtable = NULL }; ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); } diff --git a/components/wifi_cfg/wifi_cfg.c b/components/wifi_cfg/wifi_cfg.c index 56076dd..19feb7f 100644 --- a/components/wifi_cfg/wifi_cfg.c +++ b/components/wifi_cfg/wifi_cfg.c @@ -37,235 +37,179 @@ * All rights reserved. */ -#include +#include "wifi_cfg.h" #include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" #include "esp_log.h" +#include "esp_wifi.h" #include "nvs_flash.h" #include "nvs.h" -#include "esp_netif.h" -#include "esp_wifi.h" -#include "esp_event.h" -#include "wifi_cfg.h" -static esp_netif_t *sta_netif = NULL; +static const char *TAG = "WIFI_CFG"; +static const char *NVS_NS = "storage"; // Shared namespace for all settings -// --- Helper: NVS Write --- -static void nvs_write_str(const char *key, const char *val) { - nvs_handle_t h; - if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) { - if (val && strlen(val) > 0) nvs_set_str(h, key, val); - else nvs_erase_key(h, key); - nvs_commit(h); - nvs_close(h); - } +// --- Defaults --- +#define DEFAULT_MONITOR_CHANNEL 6 + +// --- Initialization --- + +void wifi_cfg_init(void) { + // NVS is usually initialized in app_main, but we can double check here + // or just leave it empty if no specific module init is needed. } -static void nvs_write_u8(const char *key, uint8_t val) { +// --- Apply Configuration --- + +bool wifi_cfg_apply_from_nvs(void) { nvs_handle_t h; - if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) { - nvs_set_u8(h, key, val); - nvs_commit(h); - nvs_close(h); + if (nvs_open(NVS_NS, NVS_READONLY, &h) != ESP_OK) { + return false; // No config found } + + // 1. Load SSID/Pass + size_t len = 0; + if (nvs_get_str(h, "wifi_ssid", NULL, &len) == ESP_OK && len > 0) { + char *ssid = malloc(len); + char *pass = NULL; + nvs_get_str(h, "wifi_ssid", ssid, &len); + + if (nvs_get_str(h, "wifi_pass", NULL, &len) == ESP_OK && len > 0) { + pass = malloc(len); + nvs_get_str(h, "wifi_pass", pass, &len); + } + + wifi_config_t wifi_config = {0}; + strncpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid)); + if (pass) { + strncpy((char *)wifi_config.sta.password, pass, sizeof(wifi_config.sta.password)); + } + + ESP_LOGI(TAG, "Applying WiFi Config: SSID=%s", ssid); + esp_wifi_set_config(WIFI_IF_STA, &wifi_config); + + free(ssid); + if (pass) free(pass); + } + + nvs_close(h); + return true; } -// --- Helper: MAC Parser --- -static bool parse_bssid(const char *str, uint8_t *out_bssid) { - if (!str || strlen(str) != 17) return false; - unsigned int bytes[6]; - int count = sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x", - &bytes[0], &bytes[1], &bytes[2], &bytes[3], &bytes[4], &bytes[5]); - if (count == 6) { - for (int i = 0; i < 6; i++) out_bssid[i] = (uint8_t)bytes[i]; - return true; - } +// --- Getters --- + +bool wifi_cfg_get_mode(char *mode_out, uint8_t *channel_out) { + // This function seems to be used to retrieve saved "mode" strings + // For now, we default to whatever is implicit, or implement saving "wifi_mode" later. + // Returning false implies default behavior. return false; } -// --- Public Setters --- +// --- Setters (Credentials) --- -void wifi_cfg_set_credentials(const char* ssid, const char* pass, const char* bssid) { - nvs_write_str("ssid", ssid); - nvs_write_str("pass", pass); - nvs_write_str("bssid", bssid); // Save BSSID to NVS -} - -void wifi_cfg_set_static_ip(const char* ip, const char* mask, const char* gw) { - nvs_write_str("ip", ip); - nvs_write_str("mask", mask); - nvs_write_str("gw", gw); -} - -void wifi_cfg_set_dhcp(bool enable) { - nvs_write_u8("dhcp", enable ? 1 : 0); -} - -// --- Clearing --- -void wifi_cfg_clear_credentials(void) { +bool wifi_cfg_set_ssid(const char *ssid) { nvs_handle_t h; - if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) { - nvs_erase_key(h, "ssid"); - nvs_erase_key(h, "pass"); - nvs_erase_key(h, "bssid"); - nvs_erase_key(h, "ip"); - nvs_erase_key(h, "mask"); - nvs_erase_key(h, "gw"); - nvs_erase_key(h, "dhcp"); - nvs_commit(h); - nvs_close(h); + if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false; + + esp_err_t err = nvs_set_str(h, "wifi_ssid", ssid); + if (err == ESP_OK) nvs_commit(h); + + nvs_close(h); + return (err == ESP_OK); +} + +bool wifi_cfg_set_password(const char *password) { + nvs_handle_t h; + if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false; + + esp_err_t err; + if (password && strlen(password) > 0) { + err = nvs_set_str(h, "wifi_pass", password); + } else { + err = nvs_erase_key(h, "wifi_pass"); // Clear if empty } + + if (err == ESP_OK) nvs_commit(h); + nvs_close(h); + return (err == ESP_OK); +} + +// --- Monitor Channel Settings --- + +bool wifi_cfg_set_monitor_channel(uint8_t channel) { + nvs_handle_t h; + if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false; + + esp_err_t err = nvs_set_u8(h, "mon_chan", channel); + if (err == ESP_OK) nvs_commit(h); + + nvs_close(h); + return (err == ESP_OK); } void wifi_cfg_clear_monitor_channel(void) { nvs_handle_t h; - if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) { - nvs_erase_key(h, "mon_ch"); + if (nvs_open(NVS_NS, NVS_READWRITE, &h) == ESP_OK) { + nvs_erase_key(h, "mon_chan"); nvs_commit(h); nvs_close(h); } } -// --- Init & Load --- - -void wifi_cfg_init(void) { - nvs_flash_init(); -} - -static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, char* bssid, size_t bsz, - char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz, - char* band, size_t bsz_band, char* bw, size_t bwsz, char* powersave, size_t pssz, - char* mode, size_t modesz, uint8_t* mon_ch, bool* dhcp){ +bool wifi_cfg_monitor_channel_is_unsaved(uint8_t current_val) { nvs_handle_t h; - if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; + uint8_t saved_val = DEFAULT_MONITOR_CHANNEL; - size_t len; - // Load SSID (Mandatory) - len = ssz; - if (nvs_get_str(h, "ssid", ssid, &len) != ESP_OK) { nvs_close(h); return false; } - - // Load Optionals - len = psz; if (nvs_get_str(h, "pass", pass, &len) != ESP_OK) pass[0]=0; - len = bsz; if (nvs_get_str(h, "bssid", bssid, &len) != ESP_OK) bssid[0]=0; - len = isz; if (nvs_get_str(h, "ip", ip, &len) != ESP_OK) ip[0]=0; - len = msz; if (nvs_get_str(h, "mask", mask, &len) != ESP_OK) mask[0]=0; - len = gsz; if (nvs_get_str(h, "gw", gw, &len) != ESP_OK) gw[0]=0; - - // Defaults - len = bsz_band; if (nvs_get_str(h, "band", band, &len) != ESP_OK) strcpy(band, "2.4G"); - len = bwsz; if (nvs_get_str(h, "bw", bw, &len) != ESP_OK) strcpy(bw, "HT20"); - len = pssz; if (nvs_get_str(h, "powersave", powersave, &len) != ESP_OK) strcpy(powersave, "NONE"); - len = modesz; if (nvs_get_str(h, "mode", mode, &len) != 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; -} - -static void apply_ip_static(const char* ip, const char* mask, const char* gw){ - if (!sta_netif) return; - if (!ip || !ip[0]) return; - - esp_netif_ip_info_t info = {0}; - esp_netif_dhcpc_stop(sta_netif); - - info.ip.addr = esp_ip4addr_aton(ip); - info.netmask.addr = (mask && mask[0]) ? esp_ip4addr_aton(mask) : esp_ip4addr_aton("255.255.255.0"); - info.gw.addr = (gw && gw[0]) ? esp_ip4addr_aton(gw) : 0; - - esp_netif_set_ip_info(sta_netif, &info); -} - -bool wifi_cfg_apply_from_nvs(void) { - char ssid[64]={0}, pass[64]={0}, bssid_str[20]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0}; - char band[16]={0}, bw[16]={0}, powersave[16]={0}, mode[16]={0}; - uint8_t mon_ch = 36; bool dhcp = true; - - if (!load_cfg(ssid,sizeof(ssid), pass,sizeof(pass), bssid_str,sizeof(bssid_str), - ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw), - band,sizeof(band), bw,sizeof(bw), powersave,sizeof(powersave), - mode,sizeof(mode), &mon_ch, &dhcp)){ - return false; + if (nvs_open(NVS_NS, NVS_READONLY, &h) == ESP_OK) { + nvs_get_u8(h, "mon_chan", &saved_val); + nvs_close(h); } - - if (sta_netif == NULL) sta_netif = esp_netif_create_default_wifi_sta(); - - wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); - esp_wifi_init(&cfg); - - wifi_config_t wcfg = {0}; - strlcpy((char*)wcfg.sta.ssid, ssid, sizeof(wcfg.sta.ssid)); - strlcpy((char*)wcfg.sta.password, pass, sizeof(wcfg.sta.password)); - wcfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK; - wcfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH; - wcfg.sta.scan_method = WIFI_ALL_CHANNEL_SCAN; - - // Apply BSSID Lock if present - if (bssid_str[0] != 0) { - if (parse_bssid(bssid_str, wcfg.sta.bssid)) { - wcfg.sta.bssid_set = true; - ESP_LOGI("WIFI_CFG", "Locking to BSSID: %s", bssid_str); - } else { - ESP_LOGW("WIFI_CFG", "Invalid BSSID format in NVS: %s", bssid_str); - } - } - - esp_wifi_set_mode(WIFI_MODE_STA); - esp_wifi_set_config(WIFI_IF_STA, &wcfg); - - if (!dhcp && ip[0]) apply_ip_static(ip, mask, gw); - else esp_netif_dhcpc_start(sta_netif); - - esp_wifi_start(); - esp_wifi_connect(); - return true; + return (saved_val != current_val); } -wifi_ps_type_t wifi_cfg_get_power_save_mode(void) { - return WIFI_PS_NONE; // Default implementation -} +// ... existing code ... -bool wifi_cfg_get_bandwidth(char *buf, size_t buf_size) { - if (buf) strncpy(buf, "HT20", buf_size); - return true; -} +// --- IP Configuration --- -bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch) { +bool wifi_cfg_set_ipv4(const char *ip, const char *mask, const char *gw) { nvs_handle_t h; - if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false; - size_t len = 16; - if (nvs_get_str(h, "mode", mode, &len) != ESP_OK) strcpy(mode, "STA"); - nvs_get_u8(h, "mon_ch", mon_ch); - nvs_close(h); - return true; -} + if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false; -bool wifi_cfg_monitor_channel_is_unsaved(uint8_t ram_value) { - nvs_handle_t h; - if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return true; - uint8_t nvs_val = 0; - esp_err_t err = nvs_get_u8(h, "mon_ch", &nvs_val); - nvs_close(h); - if (err != ESP_OK) return true; - return (nvs_val != ram_value); -} + nvs_set_str(h, "static_ip", ip); + nvs_set_str(h, "static_mask", mask); + nvs_set_str(h, "static_gw", gw); -bool wifi_cfg_set_monitor_channel(uint8_t channel) { - nvs_handle_t h; - if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return false; - uint8_t current = 0; - if (nvs_get_u8(h, "mon_ch", ¤t) == ESP_OK) { - if (current == channel) { - nvs_close(h); - return false; - } - } - nvs_set_u8(h, "mon_ch", channel); nvs_commit(h); nvs_close(h); return true; } + +bool wifi_cfg_get_ipv4(char *ip, char *mask, char *gw) { + nvs_handle_t h; + if (nvs_open(NVS_NS, NVS_READONLY, &h) != ESP_OK) return false; + + size_t len = 16; + bool exists = (nvs_get_str(h, "static_ip", ip, &len) == ESP_OK); + len = 16; nvs_get_str(h, "static_mask", mask, &len); + len = 16; nvs_get_str(h, "static_gw", gw, &len); + + nvs_close(h); + return exists; +} + +bool wifi_cfg_set_dhcp(bool enable) { + nvs_handle_t h; + if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false; + nvs_set_u8(h, "dhcp_en", enable ? 1 : 0); + nvs_commit(h); + nvs_close(h); + return true; +} + +bool wifi_cfg_get_dhcp(void) { + nvs_handle_t h; + uint8_t val = 1; // Default to Enabled + if (nvs_open(NVS_NS, NVS_READONLY, &h) == ESP_OK) { + nvs_get_u8(h, "dhcp_en", &val); + nvs_close(h); + } + return (val != 0); +} diff --git a/components/wifi_cfg/wifi_cfg.h b/components/wifi_cfg/wifi_cfg.h index 7e7b70f..5002c15 100644 --- a/components/wifi_cfg/wifi_cfg.h +++ b/components/wifi_cfg/wifi_cfg.h @@ -30,42 +30,39 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WIFI_CFG_H -#define WIFI_CFG_H +// IP Configuration +#pragma once -#include "esp_wifi.h" #include +#include #ifdef __cplusplus extern "C" { #endif -// --- Initialization --- +// Init void wifi_cfg_init(void); -// --- Getters --- +// Apply bool wifi_cfg_apply_from_nvs(void); -wifi_ps_type_t wifi_cfg_get_power_save_mode(void); -bool wifi_cfg_get_bandwidth(char *buf, size_t buf_size); -bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch); -// --- State Checkers --- -bool wifi_cfg_monitor_channel_is_unsaved(uint8_t ram_value); +// Getters +bool wifi_cfg_get_mode(char *mode_out, uint8_t *channel_out); -// --- Setters --- -// UPDATED: Now accepts optional bssid (pass NULL if not used) -void wifi_cfg_set_credentials(const char* ssid, const char* pass, const char* bssid); +// Setters (These were missing) +bool wifi_cfg_set_ssid(const char *ssid); +bool wifi_cfg_set_password(const char *password); -void wifi_cfg_set_static_ip(const char* ip, const char* mask, const char* gw); -void wifi_cfg_set_dhcp(bool enable); +// Monitor Specific bool wifi_cfg_set_monitor_channel(uint8_t channel); - -// --- Clearing --- -void wifi_cfg_clear_credentials(void); void wifi_cfg_clear_monitor_channel(void); +bool wifi_cfg_monitor_channel_is_unsaved(uint8_t current_val); + +bool wifi_cfg_set_ipv4(const char *ip, const char *mask, const char *gw); +bool wifi_cfg_get_ipv4(char *ip_out, char *mask_out, char *gw_out); // buffers must be 16 bytes +bool wifi_cfg_set_dhcp(bool enable); +bool wifi_cfg_get_dhcp(void); #ifdef __cplusplus } #endif - -#endif // WIFI_CFG_H diff --git a/components/wifi_controller/wifi_controller.c b/components/wifi_controller/wifi_controller.c index f3931ca..84f9a5c 100644 --- a/components/wifi_controller/wifi_controller.c +++ b/components/wifi_controller/wifi_controller.c @@ -30,13 +30,13 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #include "wifi_controller.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "esp_wifi.h" -#include "esp_event.h" // Added +#include "esp_event.h" +#include "esp_netif.h" #include "inttypes.h" #include "wifi_cfg.h" @@ -53,7 +53,7 @@ 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_active = 6; static uint8_t s_monitor_channel_staging = 6; static bool s_monitor_enabled = false; @@ -66,30 +66,25 @@ static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t e ESP_LOGI(TAG, "Got IP -> LED Connected"); status_led_set_state(LED_STATE_CONNECTED); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - status_led_set_state(LED_STATE_NO_CONFIG); // Or WAITING if retrying + if (s_current_mode == WIFI_CTL_MODE_STA) { + status_led_set_state(LED_STATE_NO_CONFIG); + } } } -// ... [Helper: Log Collapse Events (Same as before)] ... +// ... [Log Collapse / Monitor Callback Logic] ... static void log_collapse_event(uint32_t nav_duration_us, int rssi, int retry) { gps_timestamp_t ts = gps_get_timestamp(); - // Use gps_us for timestamp, convert to ms for display int64_t now_ms = ts.gps_us / 1000; - - // Log to CSV or similar ESP_LOGI(TAG, "COLLAPSE: Time=%" PRId64 "ms, Sync=%d, Dur=%lu us, RSSI=%d, Retry=%d", now_ms, ts.synced ? 1 : 0, nav_duration_us, rssi, retry); } -// ... [Monitor Callbacks (Same as before)] ... static void monitor_frame_callback(const wifi_frame_info_t *frame, const uint8_t *payload, uint16_t len) { s_monitor_frame_count++; 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); - } } static void monitor_stats_task(void *arg) { @@ -99,41 +94,71 @@ static void monitor_stats_task(void *arg) { if (wifi_monitor_get_stats(&stats) == ESP_OK) { ESP_LOGI("MONITOR", "--- Stats: %lu frames, Retry: %.2f%%, Avg NAV: %u us ---", (unsigned long)stats.total_frames, stats.retry_rate, stats.avg_nav); - if (wifi_monitor_is_collapsed()) ESP_LOGW("MONITOR", "⚠️ ⚠️ COLLAPSE DETECTED! ⚠️ ⚠️"); + if (wifi_monitor_is_collapsed()) ESP_LOGW("MONITOR", "⚠️ COLLAPSE DETECTED! ⚠️"); } } } -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..."); - while (status_led_get_state() != LED_STATE_CONNECTED) { - vTaskDelay(pdMS_TO_TICKS(500)); +// --- Helper to apply IP settings --- +static void apply_ip_settings(void) { + esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + if (!netif) return; + + if (wifi_cfg_get_dhcp()) { + esp_netif_dhcpc_start(netif); + } else { + esp_netif_dhcpc_stop(netif); + + char ip[16], mask[16], gw[16]; + if (wifi_cfg_get_ipv4(ip, mask, gw)) { + esp_netif_ip_info_t info = {0}; + // API Fix: esp_ip4addr_aton returns uint32_t + info.ip.addr = esp_ip4addr_aton(ip); + info.netmask.addr = esp_ip4addr_aton(mask); + info.gw.addr = esp_ip4addr_aton(gw); + + esp_netif_set_ip_info(netif, &info); + ESP_LOGI(TAG, "Static IP applied: %s", ip); + } } - 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 --- +// ============================================================================ +// PUBLIC API IMPLEMENTATION +// ============================================================================ void wifi_ctl_init(void) { s_current_mode = WIFI_CTL_MODE_STA; s_monitor_enabled = false; s_monitor_frame_count = 0; - // Register Event Handlers for LED feedback + // 1. Initialize Network Interface + esp_netif_create_default_wifi_sta(); + + // 2. Apply IP Settings (Static vs DHCP) + apply_ip_settings(); + + // 3. Initialize Wi-Fi Driver + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + // 4. Register Events ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL)); ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &wifi_event_handler, NULL, NULL)); + // 5. Configure Storage & Mode + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); + + // 6. Apply Saved Config if (!wifi_cfg_apply_from_nvs()) { ESP_LOGW(TAG, "No saved WiFi config found, driver initialized in defaults."); status_led_set_state(LED_STATE_NO_CONFIG); } else { ESP_LOGI(TAG, "WiFi driver initialized from NVS."); - status_led_set_state(LED_STATE_WAITING); // Waiting for connection + status_led_set_state(LED_STATE_WAITING); + esp_wifi_connect(); } // Load Staging Params @@ -142,63 +167,20 @@ void wifi_ctl_init(void) { 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; -} +// --- Mode Control (Core) --- -uint8_t wifi_ctl_param_get_monitor_channel(void) { - return s_monitor_channel_staging; -} +esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel, wifi_bandwidth_t bw) { + if (channel == 0) channel = s_monitor_channel_staging; -bool wifi_ctl_param_save(void) { - bool changed = wifi_cfg_set_monitor_channel(s_monitor_channel_staging); - if (changed) ESP_LOGI(TAG, "Monitor channel (%d) saved to NVS", s_monitor_channel_staging); - return changed; -} - -void wifi_ctl_param_reload(void) { - char mode_ignored[16]; - uint8_t ch = 0; - wifi_cfg_get_mode(mode_ignored, &ch); - if (ch > 0) s_monitor_channel_staging = ch; - ESP_LOGI(TAG, "Reloaded monitor channel: %d", s_monitor_channel_staging); -} - -void wifi_ctl_param_clear(void) { - // 1. Erase NVS - wifi_cfg_clear_monitor_channel(); - - // 2. Reset RAM Staging to Default (6) - s_monitor_channel_staging = 6; - - ESP_LOGI(TAG, "Monitor configuration cleared (Defaulting to Ch 6)."); -} - -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) { - uint8_t channel = (channel_override > 0) ? channel_override : s_monitor_channel_staging; - - if (s_current_mode == WIFI_CTL_MODE_MONITOR && s_monitor_channel == channel) { - ESP_LOGW(TAG, "Already in monitor mode"); + if (s_current_mode == WIFI_CTL_MODE_MONITOR && s_monitor_channel_active == channel) { + ESP_LOGW(TAG, "Already in monitor mode (Ch %d)", channel); return ESP_OK; } - if (bandwidth != WIFI_BW_HT20) { - ESP_LOGW(TAG, "Forcing bandwidth to 20MHz for monitor mode"); - bandwidth = WIFI_BW_HT20; - } - ESP_LOGI(TAG, "Switching to MONITOR MODE (Ch %d)", channel); iperf_stop(); vTaskDelay(pdMS_TO_TICKS(500)); - #ifdef CONFIG_ESP_WIFI_CSI_ENABLED csi_mgr_disable(); #endif @@ -208,13 +190,12 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t vTaskDelay(pdMS_TO_TICKS(500)); esp_wifi_set_mode(WIFI_MODE_NULL); - if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) { ESP_LOGE(TAG, "Failed to init monitor mode"); return ESP_FAIL; } - esp_wifi_set_bandwidth(WIFI_IF_STA, bandwidth); + esp_wifi_set_bandwidth(WIFI_IF_STA, bw); if (wifi_monitor_start() != ESP_OK) { ESP_LOGE(TAG, "Failed to start monitor mode"); @@ -223,7 +204,7 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t s_monitor_enabled = true; s_current_mode = WIFI_CTL_MODE_MONITOR; - s_monitor_channel = channel; + s_monitor_channel_active = channel; status_led_set_state(LED_STATE_MONITORING); if (s_monitor_stats_task_handle == NULL) { @@ -233,9 +214,9 @@ esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t return ESP_OK; } -esp_err_t wifi_ctl_switch_to_sta(wifi_band_mode_t band_mode) { +esp_err_t wifi_ctl_switch_to_sta(void) { if (s_current_mode == WIFI_CTL_MODE_STA) { - ESP_LOGW(TAG, "Already in STA mode"); + ESP_LOGI(TAG, "Already in STA mode"); return ESP_OK; } @@ -255,13 +236,7 @@ esp_err_t wifi_ctl_switch_to_sta(wifi_band_mode_t band_mode) { esp_wifi_set_mode(WIFI_MODE_STA); vTaskDelay(pdMS_TO_TICKS(500)); - wifi_config_t wifi_config; - esp_wifi_get_config(WIFI_IF_STA, &wifi_config); - 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(); s_current_mode = WIFI_CTL_MODE_STA; @@ -270,18 +245,101 @@ esp_err_t wifi_ctl_switch_to_sta(wifi_band_mode_t band_mode) { return ESP_OK; } +// --- Wrappers for cmd_monitor.c --- + +void wifi_ctl_monitor_start(int channel) { + wifi_ctl_switch_to_monitor((uint8_t)channel, WIFI_BW_HT20); +} + +void wifi_ctl_stop(void) { + wifi_ctl_switch_to_sta(); +} + +void wifi_ctl_start_station(void) { + wifi_ctl_switch_to_sta(); +} + +void wifi_ctl_start_ap(void) { + ESP_LOGW(TAG, "AP Mode not fully implemented, using STA"); + wifi_ctl_switch_to_sta(); +} + +// --- Settings --- + +void wifi_ctl_set_channel(int channel) { + if (channel < 1 || channel > 14) { + ESP_LOGE(TAG, "Invalid channel %d", channel); + return; + } + s_monitor_channel_staging = (uint8_t)channel; + + if (s_current_mode == WIFI_CTL_MODE_MONITOR) { + ESP_LOGI(TAG, "Switching live channel to %d", channel); + esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); + s_monitor_channel_active = (uint8_t)channel; + } +} + +void wifi_ctl_status(void) { + const char *mode_str = (s_current_mode == WIFI_CTL_MODE_MONITOR) ? "MONITOR" : + (s_current_mode == WIFI_CTL_MODE_AP) ? "AP" : "STATION"; + + printf("WiFi Status:\n"); + printf(" Mode: %s\n", mode_str); + if (s_current_mode == WIFI_CTL_MODE_MONITOR) { + printf(" Channel: %d\n", s_monitor_channel_active); + printf(" Frames: %lu\n", (unsigned long)s_monitor_frame_count); + } + printf(" Staging Ch: %d\n", s_monitor_channel_staging); +} + +// --- Params (NVS) --- + +bool wifi_ctl_param_is_unsaved(void) { + return wifi_cfg_monitor_channel_is_unsaved(s_monitor_channel_staging); +} + +void wifi_ctl_param_save(const char *dummy) { + (void)dummy; + if (wifi_cfg_set_monitor_channel(s_monitor_channel_staging)) { + ESP_LOGI(TAG, "Monitor channel (%d) saved to NVS", s_monitor_channel_staging); + } else { + ESP_LOGI(TAG, "No changes to save."); + } +} + +void wifi_ctl_param_init(void) { + char mode_ignored[16]; + uint8_t ch = 0; + wifi_cfg_get_mode(mode_ignored, &ch); + if (ch > 0) s_monitor_channel_staging = ch; + ESP_LOGI(TAG, "Reloaded monitor channel: %d", s_monitor_channel_staging); +} + +void wifi_ctl_param_clear(void) { + wifi_cfg_clear_monitor_channel(); + s_monitor_channel_staging = 6; + ESP_LOGI(TAG, "Monitor config cleared (Defaulting to Ch 6)."); +} + +// --- Getters --- + +wifi_ctl_mode_t wifi_ctl_get_mode(void) { return s_current_mode; } +int wifi_ctl_get_channel(void) { return s_monitor_channel_active; } + +// --- Deprecated --- +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..."); + 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)); + wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20); + vTaskDelete(NULL); +} + void wifi_ctl_auto_monitor_start(uint8_t channel) { xTaskCreate(auto_monitor_task_func, "auto_monitor", 4096, (void*)(uintptr_t)channel, 5, NULL); } - -wifi_ctl_mode_t wifi_ctl_get_mode(void) { - return s_current_mode; -} - -uint8_t wifi_ctl_get_monitor_channel(void) { - return s_monitor_channel; -} - -uint32_t wifi_ctl_get_monitor_frame_count(void) { - return s_monitor_frame_count; -} diff --git a/components/wifi_controller/wifi_controller.h b/components/wifi_controller/wifi_controller.h index a2f70bf..47f2cc8 100644 --- a/components/wifi_controller/wifi_controller.h +++ b/components/wifi_controller/wifi_controller.h @@ -30,41 +30,52 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - #pragma once -#include "esp_err.h" -#include "esp_wifi.h" #include +#include "esp_err.h" +#include "esp_wifi_types.h" // Needed for wifi_bandwidth_t #ifdef __cplusplus extern "C" { #endif +// Types typedef enum { - WIFI_CTL_MODE_STA, + WIFI_CTL_MODE_STA, // Changed from _STATION to _STA to match cmd_wifi.c + WIFI_CTL_MODE_AP, WIFI_CTL_MODE_MONITOR } wifi_ctl_mode_t; +// Init void wifi_ctl_init(void); -// --- Parameter Management --- -void wifi_ctl_param_set_monitor_channel(uint8_t channel); -uint8_t wifi_ctl_param_get_monitor_channel(void); -bool wifi_ctl_param_save(void); -void wifi_ctl_param_reload(void); +// Mode Control (Advanced) +esp_err_t wifi_ctl_switch_to_sta(void); +esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel, wifi_bandwidth_t bw); + +// Simple Wrappers (for cmd_monitor.c) +void wifi_ctl_start_station(void); +void wifi_ctl_start_ap(void); +void wifi_ctl_monitor_start(int channel); +void wifi_ctl_stop(void); + +// Settings +void wifi_ctl_set_channel(int channel); +void wifi_ctl_status(void); + +// Params (NVS) bool wifi_ctl_param_is_unsaved(void); +void wifi_ctl_param_save(const char *dummy); +void wifi_ctl_param_init(void); void wifi_ctl_param_clear(void); -// --- Actions --- -esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel_override, wifi_bandwidth_t bandwidth); -esp_err_t wifi_ctl_switch_to_sta(wifi_band_mode_t band_mode); -void wifi_ctl_auto_monitor_start(uint8_t channel); - -// --- Getters --- +// Getters wifi_ctl_mode_t wifi_ctl_get_mode(void); -uint8_t wifi_ctl_get_monitor_channel(void); -uint32_t wifi_ctl_get_monitor_frame_count(void); +int wifi_ctl_get_channel(void); + +// Deprecated / Compatibility +void wifi_ctl_auto_monitor_start(uint8_t channel); #ifdef __cplusplus }