final fixes for commands
This commit is contained in:
parent
2590a96b15
commit
4ed4391068
|
|
@ -1,11 +1,15 @@
|
||||||
idf_component_register(SRCS "app_console.c"
|
idf_component_register(
|
||||||
"cmd_system.c"
|
SRCS "app_console.c"
|
||||||
"cmd_wifi.c"
|
"cmd_wifi.c"
|
||||||
"cmd_iperf.c"
|
"cmd_iperf.c"
|
||||||
|
"cmd_system.c"
|
||||||
|
"cmd_monitor.c"
|
||||||
"cmd_nvs.c"
|
"cmd_nvs.c"
|
||||||
"cmd_gps.c"
|
"cmd_gps.c"
|
||||||
"cmd_ping.c"
|
"cmd_ping.c"
|
||||||
"cmd_monitor.c"
|
|
||||||
"cmd_ip.c"
|
"cmd_ip.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
PRIV_REQUIRES console iperf wifi_cfg wifi_controller nvs_flash gps_sync lwip driver)
|
REQUIRES console wifi_cfg
|
||||||
|
wifi_controller iperf status_led gps_sync
|
||||||
|
esp_wifi esp_netif nvs_flash spi_flash
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -30,77 +30,161 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* cmd_ip.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 Umber Networks & Robert McMahon
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "argtable3/argtable3.h"
|
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
#include "esp_mac.h"
|
#include "esp_wifi.h"
|
||||||
#include "lwip/inet.h"
|
#include "argtable3/argtable3.h"
|
||||||
|
#include "wifi_cfg.h"
|
||||||
#include "app_console.h"
|
#include "app_console.h"
|
||||||
|
|
||||||
|
// --- Arguments ---
|
||||||
static struct {
|
static struct {
|
||||||
struct arg_lit *addr;
|
struct arg_str *ip;
|
||||||
struct arg_lit *help;
|
struct arg_str *mask;
|
||||||
|
struct arg_str *gw;
|
||||||
struct arg_end *end;
|
struct arg_end *end;
|
||||||
} ip_args;
|
} set_args;
|
||||||
|
|
||||||
static void print_iface_details(const char* key) {
|
static struct {
|
||||||
esp_netif_t *netif = esp_netif_get_handle_from_ifkey(key);
|
struct arg_str *mode; // "on" or "off"
|
||||||
if (!netif) return;
|
struct arg_end *end;
|
||||||
|
} dhcp_args;
|
||||||
|
|
||||||
const char *desc = esp_netif_get_desc(netif);
|
static void print_if_info(esp_netif_t *netif, const char *name) {
|
||||||
bool is_up = esp_netif_is_netif_up(netif);
|
if (netif == NULL) return;
|
||||||
|
|
||||||
uint8_t mac[6] = {0};
|
|
||||||
esp_netif_get_mac(netif, mac);
|
|
||||||
|
|
||||||
esp_netif_ip_info_t ip_info;
|
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");
|
esp_netif_dhcp_status_t status;
|
||||||
printf(" link/ether %02x:%02x:%02x:%02x:%02x:%02x\n",
|
esp_netif_dhcpc_get_status(netif, &status);
|
||||||
|
printf(" DHCP: %s\n", (status == ESP_NETIF_DHCP_STARTED) ? "ON" : "OFF");
|
||||||
|
|
||||||
|
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]);
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||||
|
}
|
||||||
if (is_up && ip_info.ip.addr != 0) {
|
printf("\n");
|
||||||
printf(" inet " IPSTR " netmask " IPSTR " broadcast " IPSTR "\n",
|
|
||||||
IP2STR(&ip_info.ip),
|
|
||||||
IP2STR(&ip_info.netmask),
|
|
||||||
IP2STR(&ip_info.gw));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_ip(int argc, char **argv) {
|
static int do_ip_addr(void) {
|
||||||
int nerrors = arg_parse(argc, argv, (void **)&ip_args);
|
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) {
|
if (nerrors > 0) {
|
||||||
arg_print_errors(stderr, ip_args.end, argv[0]);
|
arg_print_errors(stderr, set_args.end, argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip_args.help->count > 0) {
|
const char *ip = set_args.ip->sval[0];
|
||||||
printf("Usage: ip [addr]\n");
|
const char *mask = set_args.mask->sval[0];
|
||||||
return 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explicitly check standard interfaces
|
// Save
|
||||||
print_iface_details("WIFI_STA_DEF");
|
wifi_cfg_set_ipv4(ip, mask, gw);
|
||||||
print_iface_details("WIFI_AP_DEF");
|
wifi_cfg_set_dhcp(false); // Implicitly disable DHCP
|
||||||
print_iface_details("ETH_DEF");
|
|
||||||
|
|
||||||
|
// 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;
|
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 <subcommand>\n");
|
||||||
|
printf("Subcommands:\n");
|
||||||
|
printf(" addr Show config\n");
|
||||||
|
printf(" set <ip> <mask> <gw> Set static IP (Disables DHCP)\n");
|
||||||
|
printf(" dhcp <on|off> 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) {
|
void register_ip_cmd(void) {
|
||||||
ip_args.addr = arg_lit0("a", "addr", "Show addresses");
|
// Args
|
||||||
ip_args.help = arg_lit0("h", "help", "Help");
|
set_args.ip = arg_str1(NULL, NULL, "<ip>", "IP Address");
|
||||||
ip_args.end = arg_end(1);
|
set_args.mask = arg_str1(NULL, NULL, "<mask>", "Netmask");
|
||||||
|
set_args.gw = arg_str1(NULL, NULL, "<gw>", "Gateway");
|
||||||
|
set_args.end = arg_end(3);
|
||||||
|
|
||||||
|
dhcp_args.mode = arg_str1(NULL, NULL, "<on|off>", "Mode");
|
||||||
|
dhcp_args.end = arg_end(1);
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "ip",
|
.command = "ip",
|
||||||
.help = "Show network interfaces",
|
.help = "IP Config: addr, set, dhcp",
|
||||||
|
.hint = "<subcommand>",
|
||||||
.func = &cmd_ip,
|
.func = &cmd_ip,
|
||||||
.argtable = &ip_args
|
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,105 +30,112 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "argtable3/argtable3.h"
|
#include "argtable3/argtable3.h"
|
||||||
#include "wifi_controller.h"
|
#include "wifi_controller.h"
|
||||||
#include "iperf.h"
|
|
||||||
#include "app_console.h"
|
#include "app_console.h"
|
||||||
|
|
||||||
// ============================================================================
|
// --- Subcommand Arguments ---
|
||||||
// COMMAND: monitor
|
static struct {
|
||||||
// ============================================================================
|
struct arg_int *channel;
|
||||||
|
struct arg_end *end;
|
||||||
|
} start_args;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct arg_lit *start, *stop, *status, *save, *reload;
|
|
||||||
struct arg_lit *clear_nvs;
|
|
||||||
struct arg_int *channel;
|
struct arg_int *channel;
|
||||||
struct arg_lit *help;
|
|
||||||
struct arg_end *end;
|
struct arg_end *end;
|
||||||
} mon_args;
|
} channel_args;
|
||||||
|
|
||||||
static int cmd_monitor(int argc, char **argv) {
|
static void print_monitor_usage(void) {
|
||||||
int nerrors = arg_parse(argc, argv, (void **)&mon_args);
|
printf("Usage: monitor <subcommand> [args]\n");
|
||||||
|
printf("Subcommands:\n");
|
||||||
|
printf(" start [-c <n>] Start Monitor Mode (optional: set channel)\n");
|
||||||
|
printf(" stop Stop Monitor Mode\n");
|
||||||
|
printf(" status Show current status\n");
|
||||||
|
printf(" channel <n> 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", "<n>", "Channel (1-13)");
|
||||||
|
start_args.end = arg_end(1);
|
||||||
|
|
||||||
|
int nerrors = arg_parse(argc, argv, (void **)&start_args);
|
||||||
if (nerrors > 0) {
|
if (nerrors > 0) {
|
||||||
arg_print_errors(stderr, mon_args.end, argv[0]);
|
arg_print_errors(stderr, start_args.end, argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mon_args.help->count > 0) {
|
int ch = 0;
|
||||||
printf("Usage: monitor [--start|--stop] [-c <ch>] [--save|--reload]\n");
|
if (start_args.channel->count > 0) {
|
||||||
|
ch = start_args.channel->ival[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
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, "<n>", "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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Actions: NVS Management ---
|
if (strcmp(argv[1], "start") == 0) return do_monitor_start(argc - 1, &argv[1]);
|
||||||
if (mon_args.clear_nvs->count > 0) {
|
if (strcmp(argv[1], "stop") == 0) { wifi_ctl_stop(); return 0; }
|
||||||
wifi_ctl_param_clear();
|
if (strcmp(argv[1], "status") == 0) { wifi_ctl_status(); return 0; }
|
||||||
printf("Monitor config cleared (Defaulting to Ch 6).\n");
|
if (strcmp(argv[1], "save") == 0) { wifi_ctl_param_save(NULL); printf("Saved.\n"); return 0; }
|
||||||
app_console_update_prompt();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mon_args.reload->count > 0) {
|
printf("Unknown subcommand '%s'.\n", argv[1]);
|
||||||
wifi_ctl_param_reload();
|
print_monitor_usage();
|
||||||
printf("Config reloaded from NVS.\n");
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_monitor_cmd(void) {
|
void register_monitor_cmd(void) {
|
||||||
mon_args.start = arg_lit0(NULL, "start", "Start");
|
start_args.channel = arg_int0("c", "channel", "<n>", "Channel");
|
||||||
mon_args.stop = arg_lit0(NULL, "stop", "Stop");
|
start_args.end = arg_end(1);
|
||||||
mon_args.status = arg_lit0(NULL, "status", "Status");
|
|
||||||
mon_args.save = arg_lit0(NULL, "save", "Save");
|
channel_args.channel = arg_int1(NULL, NULL, "<n>", "Channel");
|
||||||
mon_args.reload = arg_lit0(NULL, "reload", "Reload");
|
channel_args.end = arg_end(1);
|
||||||
mon_args.clear_nvs = arg_lit0(NULL, "clear-nvs", "Clear NVS");
|
|
||||||
mon_args.channel = arg_int0("c", "channel", "<n>", "Chan");
|
|
||||||
mon_args.help = arg_lit0("h", "help", "Help");
|
|
||||||
mon_args.end = arg_end(20);
|
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "monitor",
|
.command = "monitor",
|
||||||
.help = "Monitor Mode",
|
.help = "Monitor Mode: start, stop, channel, status",
|
||||||
|
.hint = "<subcommand>",
|
||||||
.func = &cmd_monitor,
|
.func = &cmd_monitor,
|
||||||
.argtable = &mon_args
|
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,130 +30,187 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* cmd_nvs.c
|
||||||
|
*
|
||||||
|
* Copyright (c) 2025 Umber Networks & Robert McMahon
|
||||||
|
* All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "argtable3/argtable3.h"
|
|
||||||
#include "nvs.h"
|
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "wifi_cfg.h"
|
#include "nvs.h"
|
||||||
#include "iperf.h"
|
#include "argtable3/argtable3.h"
|
||||||
#include "app_console.h"
|
#include "app_console.h"
|
||||||
|
|
||||||
// ============================================================================
|
static void print_nvs_usage(void) {
|
||||||
// COMMAND: nvs (Storage Management)
|
printf("Usage: nvs <subcommand>\n");
|
||||||
// ============================================================================
|
printf("Subcommands:\n");
|
||||||
|
printf(" dump Dump 'storage' namespace keys and values\n");
|
||||||
|
printf(" clear Erase 'storage' namespace (Factory Reset)\n");
|
||||||
|
}
|
||||||
|
|
||||||
static struct {
|
static void print_value(nvs_handle_t h, const char *key, nvs_type_t type) {
|
||||||
struct arg_lit *dump;
|
esp_err_t err;
|
||||||
struct arg_lit *clear_all;
|
|
||||||
struct arg_lit *help;
|
|
||||||
struct arg_end *end;
|
|
||||||
} nvs_args;
|
|
||||||
|
|
||||||
// --- Helper Functions for Dumping ---
|
switch (type) {
|
||||||
|
case NVS_TYPE_I8: {
|
||||||
static void print_nvs_key_str(nvs_handle_t h, const char *key, const char *label) {
|
int8_t v = 0;
|
||||||
char buf[64] = {0};
|
err = nvs_get_i8(h, key, &v);
|
||||||
size_t len = sizeof(buf);
|
if (err == ESP_OK) printf("Value: %d (I8)", v);
|
||||||
if (nvs_get_str(h, key, buf, &len) == ESP_OK) {
|
break;
|
||||||
printf(" %-12s : %s\n", label, buf);
|
}
|
||||||
} else {
|
case NVS_TYPE_U8: {
|
||||||
printf(" %-12s : <empty>\n", label);
|
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) {
|
static int do_nvs_dump(int argc, char **argv) {
|
||||||
uint32_t val = 0;
|
nvs_iterator_t it = NULL;
|
||||||
if (nvs_get_u32(h, key, &val) == ESP_OK) {
|
nvs_handle_t h;
|
||||||
printf(" %-12s : %" PRIu32 "\n", label, val);
|
|
||||||
} else {
|
|
||||||
printf(" %-12s : <empty>\n", label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_nvs_key_u8(nvs_handle_t h, const char *key, const char *label) {
|
// 1. Open Handle (Needed to read values)
|
||||||
uint8_t val = 0;
|
esp_err_t err = nvs_open("storage", NVS_READONLY, &h);
|
||||||
if (nvs_get_u8(h, key, &val) == ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
printf(" %-12s : %u\n", label, val);
|
printf("Error opening NVS handle: %s\n", esp_err_to_name(err));
|
||||||
} else {
|
|
||||||
printf(" %-12s : <empty>\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]);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nvs_args.help->count > 0) {
|
// 2. Start Iterator
|
||||||
printf("Usage: nvs [--dump] [--clear-all]\n");
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- CLEAR ALL ---
|
printf("NVS Dump (Namespace: storage):\n");
|
||||||
if (nvs_args.clear_all->count > 0) {
|
printf("%-20s | %-12s | %s\n", "Key", "Type", "Value");
|
||||||
printf("Erasing ALL settings from NVS...\n");
|
printf("------------------------------------------------------------\n");
|
||||||
wifi_cfg_clear_credentials();
|
|
||||||
wifi_cfg_clear_monitor_channel();
|
|
||||||
iperf_param_clear();
|
|
||||||
printf("Done. Please reboot.\n");
|
|
||||||
app_console_update_prompt();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- DUMP ---
|
while (res == ESP_OK) {
|
||||||
// Note: NVS iterators are complex in ESP-IDF; explicit key listing is often simpler for known keys.
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(it, &info);
|
||||||
|
|
||||||
printf("\n--- [WiFi Config (netcfg)] ---\n");
|
printf("%-20s | 0x%02x | ", info.key, info.type);
|
||||||
nvs_handle_t h;
|
print_value(h, info.key, info.type);
|
||||||
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");
|
printf("\n");
|
||||||
|
|
||||||
app_console_update_prompt();
|
res = nvs_entry_next(&it);
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_release_iterator(it);
|
||||||
|
nvs_close(h);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
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);
|
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "nvs",
|
.command = "nvs",
|
||||||
.help = "Storage Management",
|
.help = "Storage Tools: dump, clear",
|
||||||
|
.hint = "<subcommand>",
|
||||||
.func = &cmd_nvs,
|
.func = &cmd_nvs,
|
||||||
.argtable = &nvs_args
|
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,32 +32,22 @@
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "argtable3/argtable3.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "esp_chip_info.h"
|
#include "esp_chip_info.h"
|
||||||
#include "esp_mac.h"
|
#include "esp_flash.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_system.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "argtable3/argtable3.h"
|
||||||
#include "app_console.h"
|
#include "app_console.h"
|
||||||
|
|
||||||
static const char *TAG = "CMD_SYS";
|
// Define default version if not passed by CMake
|
||||||
|
#ifndef APP_VERSION
|
||||||
// ============================================================================
|
#define APP_VERSION "2.0.0-SHELL"
|
||||||
// COMMAND: system (Reboot, Info, Heap)
|
#endif
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
static struct {
|
|
||||||
struct arg_lit *reboot;
|
|
||||||
struct arg_lit *info;
|
|
||||||
struct arg_lit *heap;
|
|
||||||
struct arg_lit *help;
|
|
||||||
struct arg_end *end;
|
|
||||||
} sys_args;
|
|
||||||
|
|
||||||
|
// --- Helper: Convert Model ID to String ---
|
||||||
static const char* get_chip_model_string(esp_chip_model_t model) {
|
static const char* get_chip_model_string(esp_chip_model_t model) {
|
||||||
switch (model) {
|
switch (model) {
|
||||||
case CHIP_ESP32: return "ESP32";
|
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_ESP32C2: return "ESP32-C2";
|
||||||
case CHIP_ESP32C6: return "ESP32-C6";
|
case CHIP_ESP32C6: return "ESP32-C6";
|
||||||
case CHIP_ESP32H2: return "ESP32-H2";
|
case CHIP_ESP32H2: return "ESP32-H2";
|
||||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0))
|
// Explicitly handle ID 23 for C5 if macro is missing
|
||||||
case CHIP_ESP32C5: return "ESP32-C5"; // Requires recent IDF
|
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";
|
case CHIP_ESP32P4: return "ESP32-P4";
|
||||||
|
#endif
|
||||||
|
#ifdef CHIP_ESP32C5
|
||||||
|
case CHIP_ESP32C5: return "ESP32-C5";
|
||||||
#endif
|
#endif
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_system(int argc, char **argv) {
|
// --- Command Handlers ---
|
||||||
int nerrors = arg_parse(argc, argv, (void **)&sys_args);
|
|
||||||
if (nerrors > 0) {
|
|
||||||
arg_print_errors(stderr, sys_args.end, argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sys_args.help->count > 0) {
|
static int do_system_reboot(int argc, char **argv) {
|
||||||
printf("Usage: system [--reboot|--info|--heap]\n");
|
printf("Rebooting...\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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 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();
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_system_cmd(void) {
|
static int do_system_heap(int argc, char **argv) {
|
||||||
sys_args.reboot = arg_lit0(NULL, "reboot", "Reboot device");
|
printf("Heap Info:\n");
|
||||||
sys_args.info = arg_lit0(NULL, "info", "Chip Info");
|
printf(" Free: %" PRIu32 " bytes\n", esp_get_free_heap_size());
|
||||||
sys_args.heap = arg_lit0(NULL, "heap", "Memory Info");
|
printf(" Min Free: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
|
||||||
sys_args.help = arg_lit0("h", "help", "Help");
|
return 0;
|
||||||
sys_args.end = arg_end(1);
|
}
|
||||||
|
|
||||||
|
static int cmd_system(int argc, char **argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: system <reboot|info|heap>\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 = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "system",
|
.command = "system",
|
||||||
.help = "System Management (Reboot, Info, Heap)",
|
.help = "System Tools: reboot, info, heap",
|
||||||
|
.hint = "<subcommand>",
|
||||||
.func = &cmd_system,
|
.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));
|
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,362 +35,185 @@
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "argtable3/argtable3.h"
|
#include "argtable3/argtable3.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "esp_netif.h"
|
|
||||||
#include "wifi_cfg.h"
|
#include "wifi_cfg.h"
|
||||||
#include "wifi_controller.h"
|
#include "wifi_controller.h"
|
||||||
#include "app_console.h"
|
#include "app_console.h"
|
||||||
|
|
||||||
// --- Forward Declarations ---
|
// --- Arguments ---
|
||||||
static int wifi_do_scan(int argc, char **argv);
|
static struct {
|
||||||
static int wifi_do_connect(int argc, char **argv);
|
struct arg_str *ssid;
|
||||||
static int wifi_do_disconnect(int argc, char **argv);
|
struct arg_str *password;
|
||||||
static int wifi_do_link(int argc, char **argv);
|
struct arg_end *end;
|
||||||
static int wifi_do_power(int argc, char **argv);
|
} connect_args;
|
||||||
static int wifi_do_mode(int argc, char **argv);
|
|
||||||
|
|
||||||
// ============================================================================
|
static struct {
|
||||||
// COMMAND: wifi (Dispatcher)
|
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) {
|
static void print_wifi_usage(void) {
|
||||||
printf("Usage: wifi <subcommand> [args]\n");
|
printf("Usage: wifi <subcommand> [args]\n");
|
||||||
printf("Subcommands:\n");
|
printf("Subcommands:\n");
|
||||||
printf(" scan Scan for networks\n");
|
printf(" scan Scan for networks\n");
|
||||||
printf(" connect Connect to an AP (alias: join)\n");
|
printf(" connect <ssid> [<pass>] Connect to AP\n");
|
||||||
printf(" disconnect Disconnect from AP\n");
|
printf(" status Show connection info\n");
|
||||||
printf(" status Show connection status (alias: link)\n");
|
printf(" mode <sta|monitor> [-c <ch>] Switch Mode\n");
|
||||||
printf(" power Set power save (on/off)\n");
|
printf(" power <dBm> Set TX Power (8-84, 0.25dB units)\n");
|
||||||
printf(" mode Set mode (sta/monitor)\n");
|
|
||||||
printf("\nType 'wifi <subcommand> --help' for details.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmd_wifi(int argc, char **argv) {
|
// --- Handlers ---
|
||||||
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;
|
|
||||||
|
|
||||||
static int wifi_do_scan(int argc, char **argv) {
|
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");
|
printf("Scanning...\n");
|
||||||
esp_err_t err = esp_wifi_scan_start(&scan_config, true);
|
wifi_scan_config_t scan_config = {0};
|
||||||
if (err == ESP_ERR_WIFI_STATE) {
|
esp_wifi_scan_start(&scan_config, true); // Block until done
|
||||||
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);
|
|
||||||
|
|
||||||
// FORMATTING: Using exact width specifiers for Header and Data to ensure alignment
|
uint16_t ap_num = 0;
|
||||||
// SSID: 32 chars | BSSID: 17 chars | RSSI: 4 chars | Ch: 3 chars | Auth
|
esp_wifi_scan_get_ap_num(&ap_num);
|
||||||
printf("%-32s | %-17s | %4s | %3s | %s\n", "SSID", "BSSID", "RSSI", "Ch", "Auth");
|
|
||||||
printf("--------------------------------------------------------------------------------------\n");
|
|
||||||
|
|
||||||
for (int i = 0; i < ap_count; i++) {
|
wifi_ap_record_t *ap_list = (wifi_ap_record_t *)malloc(ap_num * sizeof(wifi_ap_record_t));
|
||||||
char *authmode = "UNK";
|
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_num, ap_list));
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%-32.32s | %02x:%02x:%02x:%02x:%02x:%02x | %4d | %3d | %s\n",
|
printf("Found %d APs:\n", ap_num);
|
||||||
ap_info[i].ssid,
|
printf("%-32s | %-4s | %-4s | %-18s\n", "SSID", "RSSI", "CH", "BSSID");
|
||||||
ap_info[i].bssid[0], ap_info[i].bssid[1], ap_info[i].bssid[2],
|
for (int i = 0; i < ap_num; i++) {
|
||||||
ap_info[i].bssid[3], ap_info[i].bssid[4], ap_info[i].bssid[5],
|
printf("%-32s | %-4d | %-4d | %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
ap_info[i].rssi, ap_info[i].primary, authmode);
|
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_list);
|
||||||
free(ap_info);
|
|
||||||
return 0;
|
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) {
|
static int wifi_do_connect(int argc, char **argv) {
|
||||||
// Initialize argtable members
|
|
||||||
connect_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID");
|
|
||||||
connect_args.password = arg_str0(NULL, NULL, "<pass>", "Password");
|
|
||||||
connect_args.bssid = arg_str0("b", "bssid", "<xx:xx...>", "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);
|
int nerrors = arg_parse(argc, argv, (void **)&connect_args);
|
||||||
if (nerrors > 0) {
|
if (nerrors > 0) {
|
||||||
arg_print_errors(stderr, connect_args.end, argv[0]);
|
arg_print_errors(stderr, connect_args.end, argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (connect_args.help->count > 0) {
|
|
||||||
printf("Usage: wifi connect <ssid> [password] [-b <bssid>]\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *ssid = connect_args.ssid->sval[0];
|
const char *ssid = connect_args.ssid->sval[0];
|
||||||
const char *pass = (connect_args.password->count > 0) ? connect_args.password->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();
|
wifi_ctl_mode_t current_mode = wifi_ctl_get_mode();
|
||||||
if (current_mode != WIFI_CTL_MODE_STA) {
|
if (current_mode != WIFI_CTL_MODE_STA) {
|
||||||
printf("Switching to Station Mode first...\n");
|
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)
|
// Save to NVS
|
||||||
wifi_cfg_set_credentials(ssid, pass, bssid);
|
wifi_cfg_set_ssid(ssid);
|
||||||
wifi_cfg_set_dhcp(true);
|
wifi_cfg_set_password(pass);
|
||||||
|
|
||||||
// 3. Apply to Runtime Driver (Hot Reload)
|
// Apply
|
||||||
wifi_config_t wifi_config = {0};
|
wifi_config_t wifi_config = {0};
|
||||||
strlcpy((char *)wifi_config.sta.ssid, ssid, sizeof(wifi_config.sta.ssid));
|
strncpy((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.password, pass, sizeof(wifi_config.sta.password));
|
||||||
|
|
||||||
// Default security settings
|
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||||
wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
|
ESP_ERROR_CHECK(esp_wifi_connect());
|
||||||
wifi_config.sta.pmf_cfg.capable = true;
|
|
||||||
wifi_config.sta.pmf_cfg.required = false;
|
|
||||||
|
|
||||||
// Handle BSSID Locking
|
return 0;
|
||||||
if (bssid[0]) {
|
}
|
||||||
unsigned int mac[6];
|
|
||||||
if (sscanf(bssid, "%02x:%02x:%02x:%02x:%02x:%02x",
|
static int wifi_do_status(int argc, char **argv) {
|
||||||
&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]) == 6) {
|
wifi_ctl_status();
|
||||||
for(int i=0; i<6; i++) wifi_config.sta.bssid[i] = (uint8_t)mac[i];
|
return 0;
|
||||||
wifi_config.sta.bssid_set = true;
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
} else {
|
||||||
printf("Warning: Invalid BSSID format ignored.\n");
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force Disconnect -> Set Config -> Reconnect
|
int pwr = power_args.tx_power->ival[0];
|
||||||
esp_wifi_disconnect();
|
esp_err_t err = esp_wifi_set_max_tx_power(pwr);
|
||||||
esp_err_t err = esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
|
||||||
if (err == ESP_OK) {
|
if (err == ESP_OK) {
|
||||||
esp_wifi_connect();
|
printf("TX Power set to %d (approx %.2f dBm)\n", pwr, pwr * 0.25);
|
||||||
printf("Connection initiated (Check 'wifi status').\n");
|
|
||||||
} else {
|
} else {
|
||||||
printf("Failed to apply configuration: %s\n", esp_err_to_name(err));
|
printf("Failed to set TX power: %s\n", esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_wifi(int argc, char **argv) {
|
||||||
|
if (argc < 2) {
|
||||||
|
print_wifi_usage();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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], "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) {
|
||||||
// Sub-command: wifi disconnect
|
print_wifi_usage();
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
static int wifi_do_disconnect(int argc, char **argv) {
|
|
||||||
printf("Disconnecting...\n");
|
|
||||||
esp_wifi_disconnect();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
printf("Unknown subcommand '%s'.\n", argv[1]);
|
||||||
// Registration
|
print_wifi_usage();
|
||||||
// ----------------------------------------------------------------------------
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void register_wifi_cmd(void) {
|
void register_wifi_cmd(void) {
|
||||||
|
// Connect Args
|
||||||
|
connect_args.ssid = arg_str1(NULL, NULL, "<ssid>", "SSID");
|
||||||
|
connect_args.password = arg_str0(NULL, NULL, "<pass>", "Password");
|
||||||
|
connect_args.end = arg_end(2);
|
||||||
|
|
||||||
|
// Mode Args
|
||||||
|
mode_args.mode = arg_str1(NULL, NULL, "<mode>", "sta | monitor");
|
||||||
|
mode_args.channel = arg_int0("c", "channel", "<n>", "Channel (Monitor only)");
|
||||||
|
mode_args.end = arg_end(2);
|
||||||
|
|
||||||
|
// Power Args
|
||||||
|
power_args.tx_power = arg_int1(NULL, NULL, "<dBm>", "Power (8-84)");
|
||||||
|
power_args.end = arg_end(1);
|
||||||
|
|
||||||
const esp_console_cmd_t cmd = {
|
const esp_console_cmd_t cmd = {
|
||||||
.command = "wifi",
|
.command = "wifi",
|
||||||
.help = "Wi-Fi Tool: scan, connect, status, power, mode",
|
.help = "Wi-Fi Utils: scan, connect, mode, status, power",
|
||||||
.hint = "<subcommand> [args]",
|
.hint = "<subcommand>",
|
||||||
.func = &cmd_wifi,
|
.func = &cmd_wifi,
|
||||||
.argtable = NULL
|
|
||||||
};
|
};
|
||||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,235 +37,179 @@
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "wifi_cfg.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "nvs.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 ---
|
// --- Defaults ---
|
||||||
static void nvs_write_str(const char *key, const char *val) {
|
#define DEFAULT_MONITOR_CHANNEL 6
|
||||||
nvs_handle_t h;
|
|
||||||
if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) {
|
// --- Initialization ---
|
||||||
if (val && strlen(val) > 0) nvs_set_str(h, key, val);
|
|
||||||
else nvs_erase_key(h, key);
|
void wifi_cfg_init(void) {
|
||||||
nvs_commit(h);
|
// NVS is usually initialized in app_main, but we can double check here
|
||||||
nvs_close(h);
|
// 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 ---
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Helper: MAC Parser ---
|
bool wifi_cfg_apply_from_nvs(void) {
|
||||||
static bool parse_bssid(const char *str, uint8_t *out_bssid) {
|
nvs_handle_t h;
|
||||||
if (!str || strlen(str) != 17) return false;
|
if (nvs_open(NVS_NS, NVS_READONLY, &h) != ESP_OK) {
|
||||||
unsigned int bytes[6];
|
return false; // No config found
|
||||||
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) {
|
// 1. Load SSID/Pass
|
||||||
for (int i = 0; i < 6; i++) out_bssid[i] = (uint8_t)bytes[i];
|
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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Public Setters ---
|
// --- Setters (Credentials) ---
|
||||||
|
|
||||||
void wifi_cfg_set_credentials(const char* ssid, const char* pass, const char* bssid) {
|
bool wifi_cfg_set_ssid(const char *ssid) {
|
||||||
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) {
|
|
||||||
nvs_handle_t h;
|
nvs_handle_t h;
|
||||||
if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) {
|
if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false;
|
||||||
nvs_erase_key(h, "ssid");
|
|
||||||
nvs_erase_key(h, "pass");
|
esp_err_t err = nvs_set_str(h, "wifi_ssid", ssid);
|
||||||
nvs_erase_key(h, "bssid");
|
if (err == ESP_OK) nvs_commit(h);
|
||||||
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);
|
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) {
|
void wifi_cfg_clear_monitor_channel(void) {
|
||||||
nvs_handle_t h;
|
nvs_handle_t h;
|
||||||
if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) {
|
if (nvs_open(NVS_NS, NVS_READWRITE, &h) == ESP_OK) {
|
||||||
nvs_erase_key(h, "mon_ch");
|
nvs_erase_key(h, "mon_chan");
|
||||||
nvs_commit(h);
|
nvs_commit(h);
|
||||||
nvs_close(h);
|
nvs_close(h);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Init & Load ---
|
bool wifi_cfg_monitor_channel_is_unsaved(uint8_t current_val) {
|
||||||
|
nvs_handle_t h;
|
||||||
|
uint8_t saved_val = DEFAULT_MONITOR_CHANNEL;
|
||||||
|
|
||||||
void wifi_cfg_init(void) {
|
if (nvs_open(NVS_NS, NVS_READONLY, &h) == ESP_OK) {
|
||||||
nvs_flash_init();
|
nvs_get_u8(h, "mon_chan", &saved_val);
|
||||||
|
nvs_close(h);
|
||||||
|
}
|
||||||
|
return (saved_val != current_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz, char* bssid, size_t bsz,
|
// ... existing code ...
|
||||||
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,
|
// --- IP Configuration ---
|
||||||
char* mode, size_t modesz, uint8_t* mon_ch, bool* dhcp){
|
|
||||||
|
bool wifi_cfg_set_ipv4(const char *ip, const char *mask, const char *gw) {
|
||||||
nvs_handle_t h;
|
nvs_handle_t h;
|
||||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false;
|
if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false;
|
||||||
|
|
||||||
size_t len;
|
nvs_set_str(h, "static_ip", ip);
|
||||||
// Load SSID (Mandatory)
|
nvs_set_str(h, "static_mask", mask);
|
||||||
len = ssz;
|
nvs_set_str(h, "static_gw", gw);
|
||||||
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_commit(h);
|
||||||
nvs_close(h);
|
nvs_close(h);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apply_ip_static(const char* ip, const char* mask, const char* gw){
|
bool wifi_cfg_get_ipv4(char *ip, char *mask, 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 (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
wifi_ps_type_t wifi_cfg_get_power_save_mode(void) {
|
|
||||||
return WIFI_PS_NONE; // Default implementation
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wifi_cfg_get_bandwidth(char *buf, size_t buf_size) {
|
|
||||||
if (buf) strncpy(buf, "HT20", buf_size);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch) {
|
|
||||||
nvs_handle_t h;
|
nvs_handle_t h;
|
||||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false;
|
if (nvs_open(NVS_NS, NVS_READONLY, &h) != ESP_OK) return false;
|
||||||
|
|
||||||
size_t len = 16;
|
size_t len = 16;
|
||||||
if (nvs_get_str(h, "mode", mode, &len) != ESP_OK) strcpy(mode, "STA");
|
bool exists = (nvs_get_str(h, "static_ip", ip, &len) == ESP_OK);
|
||||||
nvs_get_u8(h, "mon_ch", mon_ch);
|
len = 16; nvs_get_str(h, "static_mask", mask, &len);
|
||||||
|
len = 16; nvs_get_str(h, "static_gw", gw, &len);
|
||||||
|
|
||||||
nvs_close(h);
|
nvs_close(h);
|
||||||
return true;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wifi_cfg_monitor_channel_is_unsaved(uint8_t ram_value) {
|
bool wifi_cfg_set_dhcp(bool enable) {
|
||||||
nvs_handle_t h;
|
nvs_handle_t h;
|
||||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return true;
|
if (nvs_open(NVS_NS, NVS_READWRITE, &h) != ESP_OK) return false;
|
||||||
uint8_t nvs_val = 0;
|
nvs_set_u8(h, "dhcp_en", enable ? 1 : 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_commit(h);
|
||||||
nvs_close(h);
|
nvs_close(h);
|
||||||
return true;
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,42 +30,39 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
#ifndef WIFI_CFG_H
|
// IP Configuration
|
||||||
#define WIFI_CFG_H
|
#pragma once
|
||||||
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Initialization ---
|
// Init
|
||||||
void wifi_cfg_init(void);
|
void wifi_cfg_init(void);
|
||||||
|
|
||||||
// --- Getters ---
|
// Apply
|
||||||
bool wifi_cfg_apply_from_nvs(void);
|
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 ---
|
// Getters
|
||||||
bool wifi_cfg_monitor_channel_is_unsaved(uint8_t ram_value);
|
bool wifi_cfg_get_mode(char *mode_out, uint8_t *channel_out);
|
||||||
|
|
||||||
// --- Setters ---
|
// Setters (These were missing)
|
||||||
// UPDATED: Now accepts optional bssid (pass NULL if not used)
|
bool wifi_cfg_set_ssid(const char *ssid);
|
||||||
void wifi_cfg_set_credentials(const char* ssid, const char* pass, const char* bssid);
|
bool wifi_cfg_set_password(const char *password);
|
||||||
|
|
||||||
void wifi_cfg_set_static_ip(const char* ip, const char* mask, const char* gw);
|
// Monitor Specific
|
||||||
void wifi_cfg_set_dhcp(bool enable);
|
|
||||||
bool wifi_cfg_set_monitor_channel(uint8_t channel);
|
bool wifi_cfg_set_monitor_channel(uint8_t channel);
|
||||||
|
|
||||||
// --- Clearing ---
|
|
||||||
void wifi_cfg_clear_credentials(void);
|
|
||||||
void wifi_cfg_clear_monitor_channel(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // WIFI_CFG_H
|
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,13 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "wifi_controller.h"
|
#include "wifi_controller.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "esp_event.h" // Added
|
#include "esp_event.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
#include "inttypes.h"
|
#include "inttypes.h"
|
||||||
#include "wifi_cfg.h"
|
#include "wifi_cfg.h"
|
||||||
|
|
||||||
|
|
@ -53,7 +53,7 @@
|
||||||
static const char *TAG = "WIFI_CTL";
|
static const char *TAG = "WIFI_CTL";
|
||||||
|
|
||||||
static wifi_ctl_mode_t s_current_mode = WIFI_CTL_MODE_STA;
|
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 uint8_t s_monitor_channel_staging = 6;
|
||||||
|
|
||||||
static bool s_monitor_enabled = false;
|
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");
|
ESP_LOGI(TAG, "Got IP -> LED Connected");
|
||||||
status_led_set_state(LED_STATE_CONNECTED);
|
status_led_set_state(LED_STATE_CONNECTED);
|
||||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
} 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) {
|
static void log_collapse_event(uint32_t nav_duration_us, int rssi, int retry) {
|
||||||
gps_timestamp_t ts = gps_get_timestamp();
|
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;
|
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",
|
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);
|
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) {
|
static void monitor_frame_callback(const wifi_frame_info_t *frame, const uint8_t *payload, uint16_t len) {
|
||||||
s_monitor_frame_count++;
|
s_monitor_frame_count++;
|
||||||
if (frame->retry && frame->duration_id > 5000) {
|
if (frame->retry && frame->duration_id > 5000) {
|
||||||
log_collapse_event((float)frame->duration_id, frame->rssi, frame->retry);
|
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) {
|
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) {
|
if (wifi_monitor_get_stats(&stats) == ESP_OK) {
|
||||||
ESP_LOGI("MONITOR", "--- Stats: %lu frames, Retry: %.2f%%, Avg NAV: %u us ---",
|
ESP_LOGI("MONITOR", "--- Stats: %lu frames, Retry: %.2f%%, Avg NAV: %u us ---",
|
||||||
(unsigned long)stats.total_frames, stats.retry_rate, stats.avg_nav);
|
(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) {
|
// --- Helper to apply IP settings ---
|
||||||
uint8_t channel = (uint8_t)(uintptr_t)arg;
|
static void apply_ip_settings(void) {
|
||||||
ESP_LOGI(TAG, "Waiting for WiFi connection before switching to monitor mode...");
|
esp_netif_t *netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");
|
||||||
while (status_led_get_state() != LED_STATE_CONNECTED) {
|
if (!netif) return;
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
|
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) {
|
void wifi_ctl_init(void) {
|
||||||
s_current_mode = WIFI_CTL_MODE_STA;
|
s_current_mode = WIFI_CTL_MODE_STA;
|
||||||
s_monitor_enabled = false;
|
s_monitor_enabled = false;
|
||||||
s_monitor_frame_count = 0;
|
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(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));
|
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()) {
|
if (!wifi_cfg_apply_from_nvs()) {
|
||||||
ESP_LOGW(TAG, "No saved WiFi config found, driver initialized in defaults.");
|
ESP_LOGW(TAG, "No saved WiFi config found, driver initialized in defaults.");
|
||||||
status_led_set_state(LED_STATE_NO_CONFIG);
|
status_led_set_state(LED_STATE_NO_CONFIG);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGI(TAG, "WiFi driver initialized from NVS.");
|
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
|
// Load Staging Params
|
||||||
|
|
@ -142,63 +167,20 @@ void wifi_ctl_init(void) {
|
||||||
if (s_monitor_channel_staging == 0) s_monitor_channel_staging = 6;
|
if (s_monitor_channel_staging == 0) s_monitor_channel_staging = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Parameter Management ---
|
// --- Mode Control (Core) ---
|
||||||
void wifi_ctl_param_set_monitor_channel(uint8_t channel) {
|
|
||||||
if (channel >= 1 && channel <= 14) s_monitor_channel_staging = channel;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t wifi_ctl_param_get_monitor_channel(void) {
|
esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel, wifi_bandwidth_t bw) {
|
||||||
return s_monitor_channel_staging;
|
if (channel == 0) channel = s_monitor_channel_staging;
|
||||||
}
|
|
||||||
|
|
||||||
bool wifi_ctl_param_save(void) {
|
if (s_current_mode == WIFI_CTL_MODE_MONITOR && s_monitor_channel_active == channel) {
|
||||||
bool changed = wifi_cfg_set_monitor_channel(s_monitor_channel_staging);
|
ESP_LOGW(TAG, "Already in monitor mode (Ch %d)", channel);
|
||||||
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");
|
|
||||||
return ESP_OK;
|
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);
|
ESP_LOGI(TAG, "Switching to MONITOR MODE (Ch %d)", channel);
|
||||||
|
|
||||||
iperf_stop();
|
iperf_stop();
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
|
||||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||||
csi_mgr_disable();
|
csi_mgr_disable();
|
||||||
#endif
|
#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));
|
vTaskDelay(pdMS_TO_TICKS(500));
|
||||||
|
|
||||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||||
|
|
||||||
if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) {
|
if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to init monitor mode");
|
ESP_LOGE(TAG, "Failed to init monitor mode");
|
||||||
return ESP_FAIL;
|
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) {
|
if (wifi_monitor_start() != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "Failed to start monitor mode");
|
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_monitor_enabled = true;
|
||||||
s_current_mode = WIFI_CTL_MODE_MONITOR;
|
s_current_mode = WIFI_CTL_MODE_MONITOR;
|
||||||
s_monitor_channel = channel;
|
s_monitor_channel_active = channel;
|
||||||
status_led_set_state(LED_STATE_MONITORING);
|
status_led_set_state(LED_STATE_MONITORING);
|
||||||
|
|
||||||
if (s_monitor_stats_task_handle == NULL) {
|
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;
|
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) {
|
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;
|
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);
|
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
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();
|
esp_wifi_start();
|
||||||
vTaskDelay(pdMS_TO_TICKS(500));
|
|
||||||
esp_wifi_connect();
|
esp_wifi_connect();
|
||||||
|
|
||||||
s_current_mode = WIFI_CTL_MODE_STA;
|
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;
|
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) {
|
void wifi_ctl_auto_monitor_start(uint8_t channel) {
|
||||||
xTaskCreate(auto_monitor_task_func, "auto_monitor", 4096, (void*)(uintptr_t)channel, 5, NULL);
|
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;
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -30,41 +30,52 @@
|
||||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_wifi.h"
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_wifi_types.h" // Needed for wifi_bandwidth_t
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Types
|
||||||
typedef enum {
|
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_MONITOR
|
||||||
} wifi_ctl_mode_t;
|
} wifi_ctl_mode_t;
|
||||||
|
|
||||||
|
// Init
|
||||||
void wifi_ctl_init(void);
|
void wifi_ctl_init(void);
|
||||||
|
|
||||||
// --- Parameter Management ---
|
// Mode Control (Advanced)
|
||||||
void wifi_ctl_param_set_monitor_channel(uint8_t channel);
|
esp_err_t wifi_ctl_switch_to_sta(void);
|
||||||
uint8_t wifi_ctl_param_get_monitor_channel(void);
|
esp_err_t wifi_ctl_switch_to_monitor(uint8_t channel, wifi_bandwidth_t bw);
|
||||||
bool wifi_ctl_param_save(void);
|
|
||||||
void wifi_ctl_param_reload(void);
|
// 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);
|
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);
|
void wifi_ctl_param_clear(void);
|
||||||
|
|
||||||
// --- Actions ---
|
// Getters
|
||||||
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 ---
|
|
||||||
wifi_ctl_mode_t wifi_ctl_get_mode(void);
|
wifi_ctl_mode_t wifi_ctl_get_mode(void);
|
||||||
uint8_t wifi_ctl_get_monitor_channel(void);
|
int wifi_ctl_get_channel(void);
|
||||||
uint32_t wifi_ctl_get_monitor_frame_count(void);
|
|
||||||
|
// Deprecated / Compatibility
|
||||||
|
void wifi_ctl_auto_monitor_start(uint8_t channel);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue