up to build for console work
This commit is contained in:
parent
954075ea6e
commit
fa3e8509fb
|
|
@ -1,4 +1,3 @@
|
|||
idf_component_register(SRCS "app_console.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES console
|
||||
PRIV_REQUIRES wifi_controller csi_manager status_led gps_sync esp_wifi iperf)
|
||||
PRIV_REQUIRES console wifi_cfg iperf)
|
||||
|
|
|
|||
|
|
@ -2,111 +2,161 @@
|
|||
#include "esp_console.h"
|
||||
#include "esp_log.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// Dependencies
|
||||
#include "wifi_controller.h"
|
||||
#include "status_led.h"
|
||||
#include "gps_sync.h"
|
||||
#include "wifi_cfg.h"
|
||||
#include "iperf.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
#include "csi_manager.h"
|
||||
#endif
|
||||
|
||||
// --- Command Handlers ---
|
||||
// ============================================================================
|
||||
// COMMAND: iperf
|
||||
// ============================================================================
|
||||
static struct {
|
||||
struct arg_lit *start;
|
||||
struct arg_lit *stop;
|
||||
struct arg_lit *status;
|
||||
struct arg_int *pps;
|
||||
struct arg_lit *help;
|
||||
struct arg_end *end;
|
||||
} iperf_args;
|
||||
|
||||
static int cmd_iperf(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: iperf <start|stop|pps|status>\n");
|
||||
int nerrors = arg_parse(argc, argv, (void **)&iperf_args);
|
||||
if (nerrors > 0) {
|
||||
arg_print_errors(stderr, iperf_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "start") == 0) {
|
||||
iperf_cfg_t cfg = { .time = 0 }; // Infinite
|
||||
iperf_start(&cfg);
|
||||
// iperf_start already logs "IPERF_STARTED" via printf in iperf.c,
|
||||
// but keeping it here is fine/redundant.
|
||||
// To be safe and clean, we rely on iperf.c's output or just return success.
|
||||
if (iperf_args.help->count > 0) {
|
||||
printf("Usage: iperf [start|stop|status] [--pps <n>]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[1], "stop") == 0) {
|
||||
if (iperf_args.stop->count > 0) {
|
||||
iperf_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[1], "pps") == 0) {
|
||||
// Syntax: iperf pps 100
|
||||
if (argc < 3) {
|
||||
printf("Error: Missing value. Usage: iperf pps <rate>\n");
|
||||
return 1;
|
||||
if (iperf_args.pps->count > 0) {
|
||||
int val = iperf_args.pps->ival[0];
|
||||
if (val > 0) {
|
||||
iperf_set_pps((uint32_t)val);
|
||||
} else {
|
||||
printf("Error: PPS must be > 0\n");
|
||||
}
|
||||
int pps = atoi(argv[2]);
|
||||
if (pps <= 0) {
|
||||
printf("Error: Invalid PPS.\n");
|
||||
return 1;
|
||||
}
|
||||
iperf_set_pps((uint32_t)pps);
|
||||
// iperf_set_pps prints "IPERF_PPS_UPDATED: ..."
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
// [FIXED] Use the new API to print detailed stats
|
||||
if (iperf_args.status->count > 0) {
|
||||
iperf_print_status();
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf("Error: Unknown subcommand '%s'.\n", argv[1]);
|
||||
if (iperf_args.start->count > 0) {
|
||||
// Start using saved NVS config
|
||||
iperf_cfg_t cfg = { .time = 0 };
|
||||
iperf_start(&cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_iperf_cmd(void) {
|
||||
iperf_args.start = arg_lit0(NULL, "start", "Start iperf traffic");
|
||||
iperf_args.stop = arg_lit0(NULL, "stop", "Stop iperf traffic");
|
||||
iperf_args.status = arg_lit0(NULL, "status", "Show current statistics");
|
||||
iperf_args.pps = arg_int0(NULL, "pps", "<n>", "Set packets per second");
|
||||
iperf_args.help = arg_lit0(NULL, "help", "Show help");
|
||||
iperf_args.end = arg_end(20);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "iperf",
|
||||
.help = "Control iperf traffic generator",
|
||||
.hint = NULL,
|
||||
.func = &cmd_iperf,
|
||||
.argtable = &iperf_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// COMMAND: wifi_config
|
||||
// ============================================================================
|
||||
static struct {
|
||||
struct arg_str *ssid;
|
||||
struct arg_str *pass;
|
||||
struct arg_str *ip;
|
||||
struct arg_lit *dhcp;
|
||||
struct arg_lit *help;
|
||||
struct arg_end *end;
|
||||
} wifi_args;
|
||||
|
||||
static int cmd_wifi_config(int argc, char **argv) {
|
||||
int nerrors = arg_parse(argc, argv, (void **)&wifi_args);
|
||||
if (nerrors > 0) {
|
||||
arg_print_errors(stderr, wifi_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cmd_mode_monitor(int argc, char **argv) {
|
||||
int channel = wifi_ctl_get_monitor_channel();
|
||||
if (argc > 1) channel = atoi(argv[1]);
|
||||
if (wifi_ctl_switch_to_monitor(channel, WIFI_BW_HT20) != ESP_OK) {
|
||||
printf("Failed to switch to monitor mode\n");
|
||||
if (wifi_args.help->count > 0) {
|
||||
printf("Usage: wifi_config -s <ssid> -p <pass> [-i <ip>] [-d]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wifi_args.ssid->count == 0) {
|
||||
printf("Error: SSID is required (-s)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* ssid = wifi_args.ssid->sval[0];
|
||||
const char* pass = (wifi_args.pass->count > 0) ? wifi_args.pass->sval[0] : "";
|
||||
|
||||
const char* ip = (wifi_args.ip->count > 0) ? wifi_args.ip->sval[0] : NULL;
|
||||
bool dhcp = (wifi_args.dhcp->count > 0);
|
||||
|
||||
printf("Saving WiFi Config: SSID='%s' DHCP=%d\n", ssid, dhcp);
|
||||
|
||||
wifi_cfg_set_credentials(ssid, pass);
|
||||
|
||||
if (ip) {
|
||||
char mask[] = "255.255.255.0";
|
||||
char gw[32];
|
||||
|
||||
// FIXED: Use strlcpy instead of strncpy to prevent truncation warnings
|
||||
strlcpy(gw, ip, sizeof(gw));
|
||||
|
||||
char *last_dot = strrchr(gw, '.');
|
||||
if (last_dot) strcpy(last_dot, ".1");
|
||||
|
||||
wifi_cfg_set_static_ip(ip, mask, gw);
|
||||
wifi_cfg_set_dhcp(false);
|
||||
} else {
|
||||
wifi_cfg_set_dhcp(dhcp);
|
||||
}
|
||||
|
||||
printf("Config saved. Rebooting to apply...\n");
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_mode_sta(int argc, char **argv) {
|
||||
if (wifi_ctl_switch_to_sta(WIFI_BAND_MODE_AUTO) != ESP_OK) {
|
||||
printf("Failed to switch to STA mode\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static void register_wifi_cmd(void) {
|
||||
wifi_args.ssid = arg_str0("s", "ssid", "<ssid>", "WiFi SSID");
|
||||
wifi_args.pass = arg_str0("p", "password", "<pass>", "WiFi Password");
|
||||
wifi_args.ip = arg_str0("i", "ip", "<ip>", "Static IP");
|
||||
wifi_args.dhcp = arg_lit0("d", "dhcp", "Enable DHCP");
|
||||
wifi_args.help = arg_lit0("h", "help", "Show help");
|
||||
wifi_args.end = arg_end(20);
|
||||
|
||||
static int cmd_mode_status(int argc, char **argv) {
|
||||
wifi_ctl_mode_t mode = wifi_ctl_get_mode();
|
||||
printf("\n=== WiFi Mode Status ===\n");
|
||||
printf("Current mode: %s\n", mode == WIFI_CTL_MODE_STA ? "STA" : "MONITOR");
|
||||
printf("LED state: %d\n", status_led_get_state());
|
||||
printf("GPS synced: %s\n", gps_is_synced() ? "Yes" : "No");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_csi_dump(int argc, char **argv) {
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
csi_mgr_schedule_dump();
|
||||
#else
|
||||
printf("Error: CSI feature is disabled in this firmware build.\n");
|
||||
#endif
|
||||
return 0;
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "wifi_config",
|
||||
.help = "Configure WiFi credentials",
|
||||
.hint = NULL,
|
||||
.func = &cmd_wifi_config,
|
||||
.argtable = &wifi_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void app_console_register_commands(void) {
|
||||
const esp_console_cmd_t cmds[] = {
|
||||
{ .command = "mode_monitor", .help = "Switch to monitor mode", .func = &cmd_mode_monitor },
|
||||
{ .command = "mode_sta", .help = "Switch to STA mode", .func = &cmd_mode_sta },
|
||||
{ .command = "mode_status", .help = "Show device status", .func = &cmd_mode_status },
|
||||
{ .command = "csi_dump", .help = "Dump collected CSI data", .func = &cmd_csi_dump },
|
||||
{ .command = "iperf", .help = "Control iperf (start, stop, pps, status)", .func = &cmd_iperf },
|
||||
};
|
||||
|
||||
for (int i = 0; i < sizeof(cmds)/sizeof(cmds[0]); i++) {
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmds[i]));
|
||||
}
|
||||
register_iperf_cmd();
|
||||
register_wifi_cmd();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
/**
|
||||
* @brief Register all application-specific console commands
|
||||
* (mode_monitor, mode_sta, mode_status, csi_dump)
|
||||
* @brief Register application-specific console commands
|
||||
*/
|
||||
void app_console_register_commands(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
idf_component_register(SRCS "cmd_transport.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES console driver soc esp_driver_usb_serial_jtag)
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
#include "cmd_transport.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
#include "driver/usb_serial_jtag.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "CMD_TP";
|
||||
|
||||
#define MAX_LISTENERS 4
|
||||
static cmd_line_handler_t s_listeners[MAX_LISTENERS] = {0};
|
||||
static int s_listener_count = 0;
|
||||
static bool s_inited = false;
|
||||
|
||||
void cmd_transport_register_listener(cmd_line_handler_t handler) {
|
||||
if (s_listener_count < MAX_LISTENERS) {
|
||||
s_listeners[s_listener_count++] = handler;
|
||||
}
|
||||
}
|
||||
|
||||
static void trim_trailing(char *s) {
|
||||
int n = strlen(s);
|
||||
while (n > 0 && (s[n-1] == '\r' || s[n-1] == '\n' || isspace((unsigned char)s[n-1]))) {
|
||||
s[--n] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// --- UPDATED DISPATCH LOGIC ---
|
||||
static void dispatch_line(char *line, cmd_reply_func_t reply_func, void *reply_ctx) {
|
||||
bool handled = false;
|
||||
|
||||
// 1. Offer to registered listeners (e.g. wifi_cfg)
|
||||
// Note: The listener (wifi_cfg) is now responsible for sending "OK" if it handles the line.
|
||||
for (int i = 0; i < s_listener_count; i++) {
|
||||
if (s_listeners[i] && s_listeners[i](line, reply_func, reply_ctx)) {
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. If not handled, pass to system console
|
||||
if (!handled && strlen(line) > 0) {
|
||||
int ret;
|
||||
esp_err_t err = esp_console_run(line, &ret);
|
||||
|
||||
if (err == ESP_ERR_NOT_FOUND) {
|
||||
// Robustness: Always reply, even for unknown commands
|
||||
if (reply_func) reply_func("ERROR: Unknown Command\n", reply_ctx);
|
||||
} else if (err == ESP_OK) {
|
||||
if (ret == 0) {
|
||||
// Command Success -> Send ACK so Python knows to proceed
|
||||
if (reply_func) reply_func("OK\n", reply_ctx);
|
||||
} else {
|
||||
// Command logic failed (e.g., iperf returned 1)
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof(buf), "ERROR: Command failed (ret=%d)\n", ret);
|
||||
if (reply_func) reply_func(buf, reply_ctx);
|
||||
}
|
||||
} else {
|
||||
if (reply_func) reply_func("ERROR: System execution failed\n", reply_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- UART (stdin/stdout) Support ---
|
||||
static void uart_reply(const char *msg, void *ctx) {
|
||||
(void)ctx;
|
||||
printf("%s", msg);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static void uart_listener_task(void *arg) {
|
||||
char line[256];
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
while (1) {
|
||||
if (fgets(line, sizeof(line), stdin)) {
|
||||
trim_trailing(line);
|
||||
dispatch_line(line, uart_reply, NULL);
|
||||
} else {
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- USB Serial/JTAG Support ---
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
static void usb_reply(const char *msg, void *ctx) {
|
||||
(void)ctx;
|
||||
usb_serial_jtag_write_bytes((const uint8_t*)msg, strlen(msg), pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
static void usb_listener_task(void *arg) {
|
||||
usb_serial_jtag_driver_config_t d = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT();
|
||||
if (usb_serial_jtag_driver_install(&d) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to install USB-Serial/JTAG driver");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
char buf[256];
|
||||
size_t idx = 0;
|
||||
uint8_t c;
|
||||
|
||||
while (1) {
|
||||
int n = usb_serial_jtag_read_bytes(&c, 1, pdMS_TO_TICKS(20));
|
||||
if (n > 0) {
|
||||
if (c == '\n' || c == '\r') {
|
||||
if (idx > 0) {
|
||||
buf[idx] = 0;
|
||||
dispatch_line(buf, usb_reply, NULL);
|
||||
idx = 0;
|
||||
}
|
||||
} else {
|
||||
if (idx < sizeof(buf) - 1) {
|
||||
buf[idx++] = (char)c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void cmd_transport_init(void) {
|
||||
if (s_inited) return;
|
||||
s_inited = true;
|
||||
xTaskCreatePinnedToCore(uart_listener_task, "cmd_uart", 4096, NULL, 5, NULL, tskNO_AFFINITY);
|
||||
#if SOC_USB_SERIAL_JTAG_SUPPORTED
|
||||
xTaskCreatePinnedToCore(usb_listener_task, "cmd_usb", 4096, NULL, 5, NULL, tskNO_AFFINITY);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Function pointer structure for replying to the command source
|
||||
*/
|
||||
typedef void (*cmd_reply_func_t)(const char *msg, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief Callback for handling incoming lines
|
||||
* * @param line The received line (null-terminated, trimmed of trailing CR/LF)
|
||||
* @param reply_func Function to call to send a response back to the source
|
||||
* @param reply_ctx Context pointer to pass to reply_func
|
||||
* @return true if the line was consumed/handled
|
||||
* @return false if the line should be passed to the next listener (or system console)
|
||||
*/
|
||||
typedef bool (*cmd_line_handler_t)(const char *line, cmd_reply_func_t reply_func, void *reply_ctx);
|
||||
|
||||
/**
|
||||
* @brief Initialize the command transport (starts UART and USB listener tasks)
|
||||
*/
|
||||
void cmd_transport_init(void);
|
||||
|
||||
/**
|
||||
* @brief Register a listener for console input
|
||||
* @param handler The callback function
|
||||
*/
|
||||
void cmd_transport_register_listener(cmd_line_handler_t handler);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
idf_component_register(SRCS "wifi_cfg.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES nvs_flash esp_wifi esp_netif driver cmd_transport csi_manager)
|
||||
REQUIRES nvs_flash esp_wifi esp_netif)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdatomic.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
|
|
@ -11,149 +9,98 @@
|
|||
#include "esp_netif.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#include "wifi_cfg.h"
|
||||
#include "cmd_transport.h"
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
#include "csi_manager.h"
|
||||
#endif
|
||||
// Removed unused TAG
|
||||
|
||||
static const char *TAG = "wifi_cfg";
|
||||
static esp_netif_t *sta_netif = NULL;
|
||||
static bool cfg_dhcp = true;
|
||||
|
||||
// --- NVS Helper ---
|
||||
static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){
|
||||
return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key);
|
||||
}
|
||||
|
||||
// --- NVS Save Functions ---
|
||||
|
||||
// 1. Save Network Settings (Namespace: "netcfg")
|
||||
static void save_net_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw, const char* powersave, const char* mode, uint8_t mon_ch){
|
||||
// --- Helper: NVS Write ---
|
||||
static void nvs_write_str(const char *key, const char *val) {
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return;
|
||||
|
||||
if (ssid) nvs_set_str2(h, "ssid", ssid);
|
||||
if (pass) nvs_set_str2(h, "pass", pass);
|
||||
if (ip) nvs_set_str2(h, "ip", ip);
|
||||
if (mask) nvs_set_str2(h, "mask", mask);
|
||||
if (gw) nvs_set_str2(h, "gw", gw);
|
||||
if (band) nvs_set_str2(h, "band", band);
|
||||
if (bw) nvs_set_str2(h, "bw", bw);
|
||||
if (powersave) nvs_set_str2(h, "powersave", powersave);
|
||||
if (mode) nvs_set_str2(h, "mode", mode);
|
||||
nvs_set_u8(h, "mon_ch", mon_ch);
|
||||
nvs_set_u8(h, "dhcp", dhcp ? 1 : 0);
|
||||
|
||||
if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) {
|
||||
if (val) nvs_set_str(h, key, val);
|
||||
else nvs_erase_key(h, key);
|
||||
nvs_commit(h);
|
||||
nvs_close(h);
|
||||
cfg_dhcp = dhcp;
|
||||
ESP_LOGI(TAG, "Net Config Saved: SSID=%s IP=%s DHCP=%d", ssid?ssid:"", ip?ip:"", dhcp);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Save Iperf Settings (Namespace: "storage") -> Matches iperf.c keys
|
||||
static void save_iperf_cfg(const char* dst_ip, const char* role, const char* proto, uint32_t period, uint32_t burst, uint32_t len, uint32_t port, bool enable){
|
||||
static void nvs_write_u8(const char *key, uint8_t val) {
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("storage", NVS_READWRITE, &h) != ESP_OK) return;
|
||||
|
||||
// Note: Keys must match what iperf.c reads (NVS_KEY_IPERF_DST_IP etc)
|
||||
if (dst_ip && dst_ip[0]) nvs_set_str(h, "iperf_dst_ip", dst_ip);
|
||||
if (role && role[0]) nvs_set_str(h, "iperf_role", role);
|
||||
if (proto && proto[0]) nvs_set_str(h, "iperf_proto", proto);
|
||||
|
||||
nvs_set_u32(h, "iperf_period", period);
|
||||
nvs_set_u32(h, "iperf_burst", burst);
|
||||
nvs_set_u32(h, "iperf_len", len);
|
||||
nvs_set_u32(h, "iperf_port", port);
|
||||
nvs_set_u8(h, "iperf_enabled", enable ? 1 : 0);
|
||||
|
||||
if (nvs_open("netcfg", NVS_READWRITE, &h) == ESP_OK) {
|
||||
nvs_set_u8(h, key, val);
|
||||
nvs_commit(h);
|
||||
nvs_close(h);
|
||||
ESP_LOGI(TAG, "Iperf Config Saved: Target=%s Role=%s Period=%lu", dst_ip?dst_ip:"", role?role:"", (unsigned long)period);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Public Setters ---
|
||||
|
||||
void wifi_cfg_set_credentials(const char* ssid, const char* pass) {
|
||||
nvs_write_str("ssid", ssid);
|
||||
nvs_write_str("pass", pass);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// --- Init & Load ---
|
||||
|
||||
void wifi_cfg_init(void) {
|
||||
nvs_flash_init();
|
||||
}
|
||||
|
||||
// --- Load Logic (Network Only - Iperf loads itself) ---
|
||||
static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz,
|
||||
char* ip, size_t isz, char* mask, size_t msz, char* gw, size_t gsz,
|
||||
char* band, size_t bsz, char* bw, size_t bwsz, char* powersave, size_t pssz,
|
||||
char* mode, size_t modesz, uint8_t* mon_ch, bool* dhcp){
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false;
|
||||
|
||||
size_t len;
|
||||
esp_err_t e;
|
||||
if ((e = nvs_get_str(h, "ssid", NULL, &len)) != ESP_OK){ nvs_close(h); return false; }
|
||||
if (len >= ssz){ nvs_close(h); return false; }
|
||||
nvs_get_str(h, "ssid", ssid, &len);
|
||||
len = psz; e = nvs_get_str(h, "pass", pass, &len); if (e!=ESP_OK) pass[0]=0;
|
||||
len = isz; e = nvs_get_str(h, "ip", ip, &len); if (e!=ESP_OK) ip[0]=0;
|
||||
len = msz; e = nvs_get_str(h, "mask", mask, &len); if (e!=ESP_OK) mask[0]=0;
|
||||
len = gsz; e = nvs_get_str(h, "gw", gw, &len); if (e!=ESP_OK) gw[0]=0;
|
||||
len = bsz; e = nvs_get_str(h, "band", band, &len); if (e!=ESP_OK) strcpy(band, "2.4G");
|
||||
len = bwsz; e = nvs_get_str(h, "bw", bw, &len); if (e!=ESP_OK) strcpy(bw, "HT20");
|
||||
len = pssz; e = nvs_get_str(h, "powersave", powersave, &len); if (e!=ESP_OK) strcpy(powersave, "NONE");
|
||||
len = modesz; e = nvs_get_str(h, "mode", mode, &len); if (e!=ESP_OK) strcpy(mode, "STA");
|
||||
// Load SSID (Mandatory)
|
||||
len = ssz;
|
||||
if (nvs_get_str(h, "ssid", ssid, &len) != ESP_OK) { nvs_close(h); return false; }
|
||||
|
||||
// Load Optionals
|
||||
len = psz; if (nvs_get_str(h, "pass", pass, &len) != ESP_OK) pass[0]=0;
|
||||
len = 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; if (nvs_get_str(h, "band", band, &len) != ESP_OK) strcpy(band, "2.4G");
|
||||
len = bwsz; if (nvs_get_str(h, "bw", bw, &len) != ESP_OK) strcpy(bw, "HT20");
|
||||
len = pssz; if (nvs_get_str(h, "powersave", powersave, &len) != ESP_OK) strcpy(powersave, "NONE");
|
||||
len = modesz; if (nvs_get_str(h, "mode", mode, &len) != ESP_OK) strcpy(mode, "STA");
|
||||
|
||||
uint8_t ch=36; nvs_get_u8(h, "mon_ch", &ch); *mon_ch = ch;
|
||||
uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0);
|
||||
|
||||
nvs_close(h);
|
||||
return true;
|
||||
}
|
||||
|
||||
void wifi_cfg_force_dhcp(bool enable){ cfg_dhcp = enable; }
|
||||
|
||||
bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch) {
|
||||
if (!mode || !mon_ch) return false;
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) {
|
||||
strcpy(mode, "STA"); *mon_ch = 36; return false;
|
||||
}
|
||||
size_t len = 16;
|
||||
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;
|
||||
nvs_close(h);
|
||||
return true;
|
||||
}
|
||||
|
||||
static atomic_bool s_net_stack_ready = false;
|
||||
static esp_err_t ensure_net_stack_once(void) {
|
||||
bool expected = false;
|
||||
if (atomic_compare_exchange_strong(&s_net_stack_ready, &expected, true)) {
|
||||
ESP_RETURN_ON_ERROR(esp_netif_init(), TAG, "esp_netif_init");
|
||||
esp_err_t err = esp_event_loop_create_default();
|
||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "event loop create");
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static atomic_bool s_wifi_inited = false;
|
||||
esp_err_t wifi_ensure_inited(void) {
|
||||
bool expected = false;
|
||||
if (!atomic_compare_exchange_strong(&s_wifi_inited, &expected, true)) return ESP_OK;
|
||||
ESP_RETURN_ON_ERROR(ensure_net_stack_once(), TAG, "net stack");
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
esp_err_t err = esp_wifi_init(&cfg);
|
||||
if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) {
|
||||
atomic_store(&s_wifi_inited, false);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "esp_wifi_init");
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void apply_ip_static(const char* ip, const char* mask, const char* gw){
|
||||
if (!sta_netif) return;
|
||||
if (!ip || !ip[0] || !mask || !mask[0] || !gw || !gw[0]) 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 = esp_ip4addr_aton(mask);
|
||||
info.gw.addr = esp_ip4addr_aton(gw);
|
||||
ESP_ERROR_CHECK( esp_netif_set_ip_info(sta_netif, &info) );
|
||||
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) {
|
||||
|
|
@ -165,16 +112,11 @@ bool wifi_cfg_apply_from_nvs(void) {
|
|||
band,sizeof(band), bw,sizeof(bw), powersave,sizeof(powersave), mode,sizeof(mode), &mon_ch, &dhcp)){
|
||||
return false;
|
||||
}
|
||||
if (ssid[0] == '\0') return false;
|
||||
|
||||
static bool inited = false;
|
||||
if (!inited){
|
||||
nvs_flash_init();
|
||||
ensure_net_stack_once();
|
||||
if (sta_netif == NULL) sta_netif = esp_netif_create_default_wifi_sta();
|
||||
wifi_ensure_inited();
|
||||
inited = true;
|
||||
}
|
||||
|
||||
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));
|
||||
|
|
@ -183,200 +125,32 @@ bool wifi_cfg_apply_from_nvs(void) {
|
|||
wcfg.sta.sae_pwe_h2e = WPA3_SAE_PWE_BOTH;
|
||||
wcfg.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||
|
||||
if (strcmp(band, "5G") == 0) wcfg.sta.channel = 0;
|
||||
else wcfg.sta.channel = 0;
|
||||
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6
|
||||
wifi_protocols_t protocols = {
|
||||
.ghz_2g = WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N,
|
||||
.ghz_5g = WIFI_PROTOCOL_11A | WIFI_PROTOCOL_11N | WIFI_PROTOCOL_11AC | WIFI_PROTOCOL_11AX,
|
||||
};
|
||||
esp_wifi_set_protocols(WIFI_IF_STA, &protocols);
|
||||
#else
|
||||
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
|
||||
#endif
|
||||
|
||||
esp_wifi_set_config(WIFI_IF_STA, &wcfg);
|
||||
|
||||
if (!dhcp && ip[0]) apply_ip_static(ip, mask, gw);
|
||||
else if (sta_netif) esp_netif_dhcpc_start(sta_netif);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C6
|
||||
wifi_bandwidths_t bandwidths = {.ghz_2g = WIFI_BW_HT20, .ghz_5g = WIFI_BW_HT20};
|
||||
if (strcmp(bw, "VHT80") == 0) { bandwidths.ghz_2g = WIFI_BW_HT40; bandwidths.ghz_5g = WIFI_BW80; }
|
||||
else if (strcmp(bw, "HT40") == 0) { bandwidths.ghz_2g = WIFI_BW_HT40; bandwidths.ghz_5g = WIFI_BW_HT40; }
|
||||
esp_wifi_set_bandwidths(WIFI_IF_STA, &bandwidths);
|
||||
#else
|
||||
wifi_bandwidth_t bandwidth = WIFI_BW_HT20;
|
||||
if (strcmp(bw, "HT40") == 0) bandwidth = WIFI_BW_HT40;
|
||||
esp_wifi_set_bandwidth(WIFI_IF_STA, bandwidth);
|
||||
#endif
|
||||
else esp_netif_dhcpc_start(sta_netif);
|
||||
|
||||
esp_wifi_start();
|
||||
|
||||
wifi_ps_type_t ps_mode = WIFI_PS_NONE;
|
||||
if (strcmp(powersave, "MIN") == 0) ps_mode = WIFI_PS_MIN_MODEM;
|
||||
else if (strcmp(powersave, "MAX") == 0) ps_mode = WIFI_PS_MAX_MODEM;
|
||||
esp_wifi_set_ps(ps_mode);
|
||||
|
||||
esp_wifi_connect();
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Parsing State ---
|
||||
typedef struct {
|
||||
// Network
|
||||
char ssid[64];
|
||||
char pass[64];
|
||||
char ip[32];
|
||||
char mask[32];
|
||||
char gw[32];
|
||||
char band[16];
|
||||
char bw[16];
|
||||
char powersave[16];
|
||||
char mode[16];
|
||||
uint8_t mon_ch;
|
||||
bool dhcp;
|
||||
bool csi_enable;
|
||||
|
||||
// Iperf
|
||||
char iperf_dest[32];
|
||||
char iperf_role[16];
|
||||
char iperf_proto[8];
|
||||
uint32_t iperf_period_us;
|
||||
uint32_t iperf_burst;
|
||||
uint32_t iperf_len;
|
||||
uint32_t iperf_port;
|
||||
bool iperf_enable;
|
||||
} cfg_state_t;
|
||||
|
||||
static void on_cfg_line(const char *line, cfg_state_t *s){
|
||||
// Network Parsing
|
||||
if (strncmp(line, "SSID:",5)==0){ strncpy(s->ssid, line+5, 63); s->ssid[63]=0; return; }
|
||||
if (strncmp(line, "PASS:",5)==0){ strncpy(s->pass, line+5, 63); s->pass[63]=0; return; }
|
||||
if (strncmp(line, "IP:",3)==0){ strncpy(s->ip, line+3, 31); s->ip[31]=0; return; }
|
||||
if (strncmp(line, "MASK:",5)==0){ strncpy(s->mask, line+5, 31); s->mask[31]=0; return; }
|
||||
if (strncmp(line, "GW:",3)==0){ strncpy(s->gw, line+3, 31); s->gw[31]=0; return; }
|
||||
if (strncmp(line, "BAND:",5)==0){ strncpy(s->band, line+5, 15); s->band[15]=0; return; }
|
||||
if (strncmp(line, "BW:",3)==0){ strncpy(s->bw, line+3, 15); s->bw[15]=0; return; }
|
||||
if (strncmp(line, "POWERSAVE:",10)==0){ strncpy(s->powersave, line+10, 15); s->powersave[15]=0; return; }
|
||||
if (strncmp(line, "MODE:",5)==0){ strncpy(s->mode, line+5, 15); s->mode[15]=0; return; }
|
||||
if (strncmp(line, "MON_CH:",7)==0){ s->mon_ch = atoi(line+7); return; }
|
||||
if (strncmp(line, "DHCP:",5)==0){ s->dhcp = atoi(line+5) ? true:false; return; }
|
||||
|
||||
// Iperf Parsing (Matches Python Script Keys)
|
||||
// Support both DEST and DST to be safe
|
||||
if (strncmp(line, "IPERF_DEST_IP:", 14) == 0) { strncpy(s->iperf_dest, line+14, 31); s->iperf_dest[31]=0; return; }
|
||||
if (strncmp(line, "IPERF_DST_IP:", 13) == 0) { strncpy(s->iperf_dest, line+13, 31); s->iperf_dest[31]=0; return; }
|
||||
|
||||
if (strncmp(line, "IPERF_ROLE:", 11) == 0) { strncpy(s->iperf_role, line+11, 15); s->iperf_role[15]=0; return; }
|
||||
if (strncmp(line, "IPERF_PROTO:", 12) == 0) { strncpy(s->iperf_proto, line+12, 7); s->iperf_proto[7]=0; return; }
|
||||
|
||||
if (strncmp(line, "IPERF_PERIOD_US:", 16) == 0) { s->iperf_period_us = atoi(line+16); return; }
|
||||
if (strncmp(line, "IPERF_BURST:", 12) == 0) { s->iperf_burst = atoi(line+12); return; }
|
||||
if (strncmp(line, "IPERF_LEN:", 10) == 0) { s->iperf_len = atoi(line+10); return; }
|
||||
if (strncmp(line, "IPERF_PORT:", 11) == 0) { s->iperf_port = atoi(line+11); return; }
|
||||
if (strncmp(line, "IPERF_ENABLED:", 14) == 0) { s->iperf_enable = atoi(line+14) ? true:false; return; }
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
if (strncmp(line, "CSI:",4)==0){ s->csi_enable = atoi(line+4) ? true:false; return; }
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool wifi_cfg_cmd_handler(const char *line, cmd_reply_func_t reply_func, void *reply_ctx) {
|
||||
static bool in_cfg = false;
|
||||
static cfg_state_t s;
|
||||
|
||||
if (!in_cfg) {
|
||||
if (strcmp(line, "CFG") == 0) {
|
||||
in_cfg = true;
|
||||
// Clear all buffers
|
||||
memset(&s, 0, sizeof(s));
|
||||
// Set Defaults
|
||||
s.mon_ch = 36;
|
||||
s.dhcp = true;
|
||||
s.csi_enable = false;
|
||||
s.iperf_period_us = 10000;
|
||||
s.iperf_burst = 1;
|
||||
s.iperf_len = 1470;
|
||||
s.iperf_port = 5001;
|
||||
s.iperf_enable = true;
|
||||
strcpy(s.iperf_dest, "192.168.1.50");
|
||||
strcpy(s.iperf_role, "CLIENT");
|
||||
strcpy(s.iperf_proto, "UDP");
|
||||
|
||||
// --- NEW: ACK Start of CFG ---
|
||||
if (reply_func) reply_func("OK\n", reply_ctx);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(line, "END") == 0) {
|
||||
// Apply Network Defaults if missing
|
||||
if (!s.band[0]) strcpy(s.band, "2.4G");
|
||||
if (!s.bw[0]) strcpy(s.bw, "HT20");
|
||||
if (!s.powersave[0]) strcpy(s.powersave, "NONE");
|
||||
if (!s.mode[0]) strcpy(s.mode, "STA");
|
||||
|
||||
// 1. Save Network
|
||||
save_net_cfg(s.ssid, s.pass, s.ip, s.mask, s.gw, s.dhcp, s.band, s.bw, s.powersave, s.mode, s.mon_ch);
|
||||
|
||||
// 2. Save Iperf
|
||||
save_iperf_cfg(s.iperf_dest, s.iperf_role, s.iperf_proto, s.iperf_period_us, s.iperf_burst, s.iperf_len, s.iperf_port, s.iperf_enable);
|
||||
|
||||
// 3. Save CSI
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
csi_mgr_save_enable_state(s.csi_enable);
|
||||
#endif
|
||||
|
||||
// --- NEW: ACK End of CFG ---
|
||||
if (reply_func) reply_func("OK Config Saved\n", reply_ctx);
|
||||
|
||||
// Apply changes immediately
|
||||
wifi_cfg_apply_from_nvs();
|
||||
|
||||
in_cfg = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
on_cfg_line(line, &s);
|
||||
|
||||
// --- NEW: ACK Intermediate Line ---
|
||||
if (reply_func) reply_func("OK\n", reply_ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wifi_cfg_init(void){
|
||||
nvs_flash_init();
|
||||
cmd_transport_init();
|
||||
cmd_transport_register_listener(wifi_cfg_cmd_handler);
|
||||
}
|
||||
|
||||
wifi_ps_type_t wifi_cfg_get_power_save_mode(void) {
|
||||
char powersave[16] = {0};
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return WIFI_PS_NONE;
|
||||
size_t len = sizeof(powersave);
|
||||
nvs_get_str(h, "powersave", powersave, &len);
|
||||
nvs_close(h);
|
||||
|
||||
if (strcmp(powersave, "MIN") == 0) return WIFI_PS_MIN_MODEM;
|
||||
if (strcmp(powersave, "MAX") == 0) return WIFI_PS_MAX_MODEM;
|
||||
return WIFI_PS_NONE;
|
||||
}
|
||||
|
||||
bool wifi_cfg_get_bandwidth(char *buf, size_t buf_size) {
|
||||
if (!buf || buf_size < 1) return false;
|
||||
if (buf) strncpy(buf, "HT20", buf_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch) {
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) {
|
||||
strncpy(buf, "Unknown", buf_size); return false;
|
||||
}
|
||||
size_t len = buf_size;
|
||||
esp_err_t err = nvs_get_str(h, "bw", buf, &len);
|
||||
if (nvs_open("netcfg", NVS_READONLY, &h) != ESP_OK) return false;
|
||||
size_t len = 16;
|
||||
if (nvs_get_str(h, "mode", mode, &len) != ESP_OK) strcpy(mode, "STA");
|
||||
nvs_get_u8(h, "mon_ch", mon_ch);
|
||||
nvs_close(h);
|
||||
return (err == ESP_OK);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,59 +8,19 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the WiFi configuration system
|
||||
*
|
||||
* Spawns listener tasks for both UART and USB-Serial/JTAG interfaces
|
||||
* to receive configuration commands.
|
||||
*/
|
||||
// --- Initialization ---
|
||||
void wifi_cfg_init(void);
|
||||
|
||||
/**
|
||||
* @brief Apply WiFi configuration from NVS
|
||||
*
|
||||
* @return true if configuration was found and applied, false otherwise
|
||||
*/
|
||||
// --- Getters (Used by Controller) ---
|
||||
bool wifi_cfg_apply_from_nvs(void);
|
||||
|
||||
/**
|
||||
* @brief Force DHCP mode enable/disable
|
||||
*
|
||||
* @param enable true to enable DHCP, false to disable
|
||||
*/
|
||||
void wifi_cfg_force_dhcp(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Get the configured power save mode from NVS
|
||||
*
|
||||
* @return wifi_ps_type_t Power save mode (WIFI_PS_NONE, WIFI_PS_MIN_MODEM, or WIFI_PS_MAX_MODEM)
|
||||
*/
|
||||
wifi_ps_type_t wifi_cfg_get_power_save_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Get the configured bandwidth from NVS
|
||||
*
|
||||
* @param buf Buffer to store bandwidth string (e.g., "HT20", "HT40", "VHT80")
|
||||
* @param buf_size Size of buffer
|
||||
* @return true if bandwidth was retrieved, false otherwise
|
||||
*/
|
||||
bool wifi_cfg_get_bandwidth(char *buf, size_t buf_size);
|
||||
|
||||
/**
|
||||
* @brief Get operating mode and monitor channel from NVS
|
||||
*
|
||||
* @param mode Output buffer for mode string (min 16 bytes)
|
||||
* @param mon_ch Output pointer for monitor channel
|
||||
* @return true if mode retrieved, false if no config in NVS
|
||||
*/
|
||||
bool wifi_cfg_get_mode(char *mode, uint8_t *mon_ch);
|
||||
|
||||
/**
|
||||
* @brief Ensure WiFi driver is initialized (thread-safe, idempotent)
|
||||
*
|
||||
* @return ESP_OK on success, error code otherwise
|
||||
*/
|
||||
esp_err_t wifi_ensure_inited(void);
|
||||
// --- Setters (Used by Console) ---
|
||||
void wifi_cfg_set_credentials(const char* ssid, const char* pass);
|
||||
void wifi_cfg_set_static_ip(const char* ip, const char* mask, const char* gw);
|
||||
void wifi_cfg_set_dhcp(bool enable);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,3 @@
|
|||
idf_component_register(
|
||||
SRCS "main.c"
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
nvs_flash
|
||||
esp_wifi
|
||||
esp_netif
|
||||
esp_event
|
||||
lwip
|
||||
console
|
||||
driver # <--- Added (For GPIO definitions)
|
||||
cmd_transport # <--- Added (For cmd_transport.h)
|
||||
iperf
|
||||
wifi_cfg
|
||||
csi_log
|
||||
wifi_monitor
|
||||
gps_sync
|
||||
led_strip
|
||||
status_led
|
||||
csi_manager
|
||||
wifi_controller
|
||||
app_console
|
||||
)
|
||||
PRIV_REQUIRES nvs_flash esp_netif wifi_controller wifi_cfg app_console iperf status_led gps_sync console)
|
||||
|
|
|
|||
|
|
@ -1,37 +1,45 @@
|
|||
#pragma once
|
||||
#include "driver/gpio.h"
|
||||
#ifndef BOARD_CONFIG_H
|
||||
#define BOARD_CONFIG_H
|
||||
|
||||
// --- Hardware Configuration ---
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
// ESP32-S3
|
||||
// ============================================================================
|
||||
// ESP32-C5 (DevKitC-1)
|
||||
// ============================================================================
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C5
|
||||
#define RGB_LED_GPIO 8 // Common addressable LED pin for C5
|
||||
#define HAS_RGB_LED 1
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// ESP32-S3 (DevKitC-1)
|
||||
// ============================================================================
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||
// Most S3 DevKits use GPIO 48 for the addressable RGB LED.
|
||||
// If yours uses GPIO 38, change this value.
|
||||
#define RGB_LED_GPIO 48
|
||||
#define HAS_RGB_LED 1
|
||||
#define GPS_TX_PIN GPIO_NUM_5
|
||||
#define GPS_RX_PIN GPIO_NUM_4
|
||||
#define GPS_PPS_PIN GPIO_NUM_6
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32C5)
|
||||
// ESP32-C5
|
||||
#define RGB_LED_GPIO 27
|
||||
#define HAS_RGB_LED 1
|
||||
#define GPS_TX_PIN GPIO_NUM_24
|
||||
#define GPS_RX_PIN GPIO_NUM_23
|
||||
#define GPS_PPS_PIN GPIO_NUM_25
|
||||
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32)
|
||||
// ESP32 (Original)
|
||||
#define RGB_LED_GPIO 2 // Standard Blue LED
|
||||
#define HAS_RGB_LED 0 // Not RGB
|
||||
#define GPS_TX_PIN GPIO_NUM_17
|
||||
#define GPS_RX_PIN GPIO_NUM_16
|
||||
#define GPS_PPS_PIN GPIO_NUM_4
|
||||
|
||||
#else
|
||||
// Fallback
|
||||
#define RGB_LED_GPIO 8
|
||||
#define HAS_RGB_LED 1
|
||||
#define GPS_TX_PIN GPIO_NUM_1
|
||||
#define GPS_RX_PIN GPIO_NUM_3
|
||||
#define GPS_PPS_PIN GPIO_NUM_5
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// ESP32 (Original / Standard)
|
||||
// ============================================================================
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
// Standard ESP32 DevKits usually have a single blue LED on GPIO 2.
|
||||
// They rarely have an addressable RGB LED built-in.
|
||||
#define RGB_LED_GPIO 2
|
||||
#define HAS_RGB_LED 0
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
// Fallbacks (Prevent Compilation Errors)
|
||||
// ============================================================================
|
||||
#ifndef RGB_LED_GPIO
|
||||
#define RGB_LED_GPIO 2
|
||||
#endif
|
||||
|
||||
#ifndef HAS_RGB_LED
|
||||
#define HAS_RGB_LED 0
|
||||
#endif
|
||||
|
||||
#endif // BOARD_CONFIG_H
|
||||
|
|
|
|||
173
main/main.c
173
main/main.c
|
|
@ -1,161 +1,110 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_console.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "driver/uart.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "esp_event.h"
|
||||
|
||||
// Components
|
||||
#include "board_config.h"
|
||||
#include "status_led.h"
|
||||
#include "gps_sync.h"
|
||||
#include "wifi_cfg.h"
|
||||
#include "board_config.h"
|
||||
#include "wifi_controller.h"
|
||||
#include "wifi_cfg.h"
|
||||
#include "app_console.h"
|
||||
#include "iperf.h"
|
||||
|
||||
// GUARDED INCLUDE
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
#include "csi_log.h"
|
||||
#include "csi_manager.h"
|
||||
#endif
|
||||
|
||||
// --- VERSION DEFINITION ---
|
||||
#define APP_VERSION "1.1.0"
|
||||
#define APP_VERSION "2.0.0-SHELL"
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
// --- Version Command -----------------------------------------------
|
||||
static int cmd_version(int argc, char **argv) {
|
||||
printf("APP_VERSION: %s\n", APP_VERSION);
|
||||
// --- System Commands ---
|
||||
|
||||
static int cmd_restart(int argc, char **argv) {
|
||||
ESP_LOGI(TAG, "Restarting...");
|
||||
esp_restart();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- Event Handler -------------------------------------------------
|
||||
static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
if (event_base == WIFI_EVENT) {
|
||||
if (event_id == WIFI_EVENT_STA_START) {
|
||||
if (wifi_ctl_get_mode() == WIFI_CTL_MODE_STA) {
|
||||
status_led_set_state(LED_STATE_WAITING);
|
||||
}
|
||||
}
|
||||
else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (wifi_ctl_get_mode() == WIFI_CTL_MODE_STA) {
|
||||
status_led_set_state(LED_STATE_FAILED);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
if (wifi_ctl_get_mode() != WIFI_CTL_MODE_STA) return;
|
||||
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
|
||||
status_led_set_state(LED_STATE_CONNECTED);
|
||||
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
if (csi_mgr_should_enable()) {
|
||||
ESP_LOGI(TAG, "CSI enabled in config - starting capture");
|
||||
csi_mgr_enable_async();
|
||||
csi_mgr_schedule_dump();
|
||||
} else {
|
||||
ESP_LOGI(TAG, "CSI disabled in config - skipping capture");
|
||||
}
|
||||
#endif
|
||||
|
||||
// iperf_start() will fill this from NVS (including Dest IP and Role)
|
||||
iperf_cfg_t cfg = { 0 };
|
||||
iperf_start(&cfg);
|
||||
}
|
||||
static int cmd_version(int argc, char **argv) {
|
||||
printf("APP_VERSION: %s\n", APP_VERSION);
|
||||
printf("IDF_VERSION: %s\n", esp_get_idf_version());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- Main ----------------------------------------------------------
|
||||
static void register_system_common(void) {
|
||||
const esp_console_cmd_t restart_cmd = {
|
||||
.command = "reset",
|
||||
.help = "Software reset of the device",
|
||||
.func = &cmd_restart
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&restart_cmd));
|
||||
|
||||
const esp_console_cmd_t version_cmd = {
|
||||
.command = "version",
|
||||
.help = "Get firmware version",
|
||||
.func = &cmd_version
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&version_cmd));
|
||||
}
|
||||
|
||||
// --- Main Application ---
|
||||
|
||||
void app_main(void) {
|
||||
// 1. System Init
|
||||
// 1. Initialize NVS
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
ret = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
// 2. Initialize Netif & Event Loop
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// 2. Hardware/Driver Init
|
||||
// 3. Hardware Init
|
||||
status_led_init(RGB_LED_GPIO, HAS_RGB_LED);
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
ESP_ERROR_CHECK(csi_log_init());
|
||||
#endif
|
||||
status_led_init(RGB_LED_GPIO, HAS_RGB_LED);
|
||||
|
||||
const gps_sync_config_t gps_cfg = {
|
||||
.uart_port = UART_NUM_1,
|
||||
.tx_pin = GPS_TX_PIN,
|
||||
.rx_pin = GPS_RX_PIN,
|
||||
.pps_pin = GPS_PPS_PIN,
|
||||
};
|
||||
gps_sync_init(&gps_cfg, true);
|
||||
|
||||
// 3. Subsystem Init
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
csi_mgr_init();
|
||||
#endif
|
||||
|
||||
// 4. Initialize WiFi Controller (Loads config from NVS automatically)
|
||||
wifi_ctl_init();
|
||||
wifi_cfg_init();
|
||||
|
||||
// 4. Console Registry Init
|
||||
esp_console_config_t console_config = {
|
||||
.max_cmdline_args = 8,
|
||||
.max_cmdline_length = 256,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_init(&console_config));
|
||||
esp_console_register_help_command();
|
||||
// 5. Initialize Console
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
|
||||
// Register App Commands
|
||||
// This prompt is the anchor for your Python script
|
||||
repl_config.prompt = "esp32> ";
|
||||
repl_config.max_cmdline_length = 1024;
|
||||
|
||||
// Install UART driver for Console (Standard IO)
|
||||
esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl));
|
||||
|
||||
// 6. Register Commands
|
||||
register_system_common();
|
||||
app_console_register_commands();
|
||||
|
||||
// Register Version Command (Built-in)
|
||||
const esp_console_cmd_t version_cmd_def = {
|
||||
.command = "version",
|
||||
.help = "Get firmware version",
|
||||
.hint = NULL,
|
||||
.func = &cmd_version,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&version_cmd_def));
|
||||
// 7. Start Shell
|
||||
printf("\n ==================================================\n");
|
||||
printf(" | ESP32 iPerf Shell - Ready |\n");
|
||||
printf(" | Type 'help' for commands |\n");
|
||||
printf(" ==================================================\n");
|
||||
|
||||
// 5. Register Events
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL));
|
||||
|
||||
// 6. Application Start
|
||||
#ifdef CONFIG_ESP_WIFI_CSI_ENABLED
|
||||
bool csi_enabled = csi_mgr_should_enable();
|
||||
ESP_LOGI(TAG, "CSI Capture: %s", csi_enabled ? "ENABLED" : "DISABLED");
|
||||
#endif
|
||||
|
||||
if (wifi_cfg_apply_from_nvs()) {
|
||||
status_led_set_state(LED_STATE_WAITING);
|
||||
|
||||
char mode[16] = {0};
|
||||
uint8_t mon_ch = 36;
|
||||
if (wifi_cfg_get_mode(mode, &mon_ch) && strcmp(mode, "MONITOR") == 0) {
|
||||
wifi_ctl_auto_monitor_start(mon_ch);
|
||||
}
|
||||
} else {
|
||||
status_led_set_state(LED_STATE_NO_CONFIG);
|
||||
ESP_LOGW(TAG, "No Config Found. Waiting for setup...");
|
||||
}
|
||||
|
||||
// 7. Keep Main Task Alive
|
||||
ESP_LOGI(TAG, "Initialization complete. Entering idle loop.");
|
||||
ESP_LOGI(TAG, "Firmware Version: %s", APP_VERSION); // Log version on boot
|
||||
|
||||
while (true) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
// This function runs the REPL loop and does not return
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue