support for both monitor and sta modes, set in NVS using config_device.
This commit is contained in:
parent
9d402a02de
commit
7924da11c7
|
|
@ -47,7 +47,7 @@ static esp_err_t nvs_set_str2(nvs_handle_t h, const char *key, const char *val){
|
|||
return val ? nvs_set_str(h, key, val) : nvs_erase_key(h, key);
|
||||
}
|
||||
|
||||
static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw, const char* powersave){
|
||||
static void save_cfg(const char* ssid, const char* pass, const char* ip, const char* mask, const char* gw, bool dhcp, const char* band, const char* bw, const char* powersave, const char* mode, uint8_t mon_ch){
|
||||
nvs_handle_t h;
|
||||
if (nvs_open("netcfg", NVS_READWRITE, &h) != ESP_OK) return;
|
||||
if (ssid) nvs_set_str2(h, "ssid", ssid);
|
||||
|
|
@ -58,16 +58,20 @@ static void save_cfg(const char* ssid, const char* pass, const char* ip, const c
|
|||
if (band) nvs_set_str2(h, "band", band);
|
||||
if (bw) nvs_set_str2(h, "bw", bw);
|
||||
if (powersave) nvs_set_str2(h, "powersave", powersave);
|
||||
if (mode) nvs_set_str2(h, "mode", mode);
|
||||
nvs_set_u8(h, "mon_ch", mon_ch);
|
||||
nvs_set_u8(h, "dhcp", dhcp ? 1 : 0);
|
||||
nvs_commit(h);
|
||||
nvs_close(h);
|
||||
cfg_dhcp = dhcp;
|
||||
ESP_LOGI(TAG, "Config saved to NVS: SSID=%s Band=%s BW=%s PowerSave=%s", ssid?ssid:"", band?band:"", bw?bw:"", powersave?powersave:"NONE");
|
||||
ESP_LOGI(TAG, "Config saved to NVS: SSID=%s Mode=%s MonCh=%d Band=%s BW=%s PowerSave=%s",
|
||||
ssid?ssid:"", mode?mode:"STA", mon_ch, band?band:"", bw?bw:"", powersave?powersave:"NONE");
|
||||
}
|
||||
|
||||
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, bool* dhcp){
|
||||
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;
|
||||
|
|
@ -82,6 +86,8 @@ static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz,
|
|||
len = bsz; e = nvs_get_str(h, "band", band, &len); if (e!=ESP_OK) strcpy(band, "2.4G");
|
||||
len = bwsz; e = nvs_get_str(h, "bw", bw, &len); if (e!=ESP_OK) strcpy(bw, "HT20");
|
||||
len = pssz; e = nvs_get_str(h, "powersave", powersave, &len); if (e!=ESP_OK) strcpy(powersave, "NONE");
|
||||
len = modesz; e = nvs_get_str(h, "mode", mode, &len); if (e!=ESP_OK) strcpy(mode, "STA");
|
||||
uint8_t ch=36; nvs_get_u8(h, "mon_ch", &ch); *mon_ch = ch;
|
||||
uint8_t d=1; nvs_get_u8(h, "dhcp", &d); *dhcp = (d!=0);
|
||||
nvs_close(h);
|
||||
return true;
|
||||
|
|
@ -89,6 +95,32 @@ static bool load_cfg(char* ssid, size_t ssz, char* pass, size_t psz,
|
|||
|
||||
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) {
|
||||
ESP_LOGW(TAG, "Failed to open NVS for mode - defaulting to STA");
|
||||
strcpy(mode, "STA");
|
||||
*mon_ch = 36;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t len = 16;
|
||||
esp_err_t e = nvs_get_str(h, "mode", mode, &len);
|
||||
if (e != ESP_OK) {
|
||||
strcpy(mode, "STA"); // Default to STA mode
|
||||
}
|
||||
|
||||
uint8_t ch = 36;
|
||||
nvs_get_u8(h, "mon_ch", &ch);
|
||||
*mon_ch = ch;
|
||||
|
||||
nvs_close(h);
|
||||
ESP_LOGI(TAG, "Retrieved mode from NVS: %s (MonCh=%d)", mode, ch);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* --- One-time net stack bring-up (thread-safe) --- */
|
||||
static atomic_bool s_net_stack_ready = false;
|
||||
|
|
@ -157,10 +189,11 @@ static void apply_ip_static(const char* ip, const char* mask, const char* gw){
|
|||
|
||||
bool wifi_cfg_apply_from_nvs(void) {
|
||||
char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0};
|
||||
char band[16]={0}, bw[16]={0}, powersave[16]={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), ip,sizeof(ip), mask,sizeof(mask), gw,sizeof(gw),
|
||||
band,sizeof(band), bw,sizeof(bw), powersave,sizeof(powersave), &dhcp)){
|
||||
band,sizeof(band), bw,sizeof(bw), powersave,sizeof(powersave), mode,sizeof(mode), &mon_ch, &dhcp)){
|
||||
ESP_LOGW(TAG, "No Wi‑Fi config in NVS");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -169,8 +202,8 @@ bool wifi_cfg_apply_from_nvs(void) {
|
|||
ESP_LOGW(TAG, "SSID in NVS is empty; treating as no Wi-Fi config");
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAG, "Applying Wi-Fi config: SSID=%s DHCP=%d IP=%s MASK=%s GW=%s Band=%s BW=%s PowerSave=%s",
|
||||
ssid, dhcp, ip, mask, gw, band, bw, powersave);
|
||||
ESP_LOGI(TAG, "Applying Wi-Fi config: SSID=%s DHCP=%d IP=%s MASK=%s GW=%s Band=%s BW=%s PowerSave=%s Mode=%s MonCh=%d",
|
||||
ssid, dhcp, ip, mask, gw, band, bw, powersave, mode, mon_ch);
|
||||
|
||||
static bool inited = false;
|
||||
if (!inited){
|
||||
|
|
@ -336,7 +369,7 @@ typedef struct {
|
|||
bool (*fetch_line)(char *buf, size_t sz, void *ctx);
|
||||
} cfg_io_t;
|
||||
|
||||
static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, char *band, char *bw, char *powersave, bool *dhcp){
|
||||
static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char *mask, char *gw, char *band, char *bw, char *powersave, char *mode, uint8_t *mon_ch, bool *dhcp){
|
||||
if (strncmp(line, "SSID:",5)==0){ strncpy(ssid, line+5, 63); ssid[63]=0; return; }
|
||||
if (strncmp(line, "PASS:",5)==0){ strncpy(pass, line+5, 63); pass[63]=0; return; }
|
||||
if (strncmp(line, "IP:",3)==0){ strncpy(ip, line+3, 31); ip[31]=0; return; }
|
||||
|
|
@ -345,13 +378,16 @@ static void on_cfg_line(const char *line, char *ssid, char *pass, char *ip, char
|
|||
if (strncmp(line, "BAND:",5)==0){ strncpy(band, line+5, 15); band[15]=0; return; }
|
||||
if (strncmp(line, "BW:",3)==0){ strncpy(bw, line+3, 15); bw[15]=0; return; }
|
||||
if (strncmp(line, "POWERSAVE:",10)==0){ strncpy(powersave, line+10, 15); powersave[15]=0; return; }
|
||||
if (strncmp(line, "MODE:",5)==0){ strncpy(mode, line+5, 15); mode[15]=0; return; }
|
||||
if (strncmp(line, "MON_CH:",7)==0){ *mon_ch = atoi(line+7); return; }
|
||||
if (strncmp(line, "DHCP:",5)==0){ *dhcp = atoi(line+5) ? true:false; return; }
|
||||
}
|
||||
|
||||
static void cfg_worker(const cfg_io_t *io){
|
||||
char line[160];
|
||||
char ssid[64]={0}, pass[64]={0}, ip[32]={0}, mask[32]={0}, gw[32]={0};
|
||||
char band[16]={0}, bw[16]={0}, powersave[16]={0};
|
||||
char band[16]={0}, bw[16]={0}, powersave[16]={0}, mode[16]={0};
|
||||
uint8_t mon_ch = 36;
|
||||
bool dhcp = true;
|
||||
bool in_cfg = false;
|
||||
|
||||
|
|
@ -365,7 +401,8 @@ static void cfg_worker(const cfg_io_t *io){
|
|||
if (strcmp(line, "CFG")==0){
|
||||
in_cfg = true;
|
||||
ssid[0]=pass[0]=ip[0]=mask[0]=gw[0]=0;
|
||||
band[0]=bw[0]=powersave[0]=0;
|
||||
band[0]=bw[0]=powersave[0]=mode[0]=0;
|
||||
mon_ch = 36;
|
||||
dhcp = true;
|
||||
}
|
||||
continue;
|
||||
|
|
@ -375,14 +412,15 @@ static void cfg_worker(const cfg_io_t *io){
|
|||
if (!band[0]) strcpy(band, "2.4G");
|
||||
if (!bw[0]) strcpy(bw, "HT20");
|
||||
if (!powersave[0]) strcpy(powersave, "NONE");
|
||||
if (!mode[0]) strcpy(mode, "STA");
|
||||
|
||||
save_cfg(ssid, pass, ip, mask, gw, dhcp, band, bw, powersave);
|
||||
save_cfg(ssid, pass, ip, mask, gw, dhcp, band, bw, powersave, mode, mon_ch);
|
||||
if (io->emit) io->emit("OK\n", io->ctx);
|
||||
wifi_cfg_apply_from_nvs();
|
||||
in_cfg = false;
|
||||
continue;
|
||||
}
|
||||
on_cfg_line(line, ssid, pass, ip, mask, gw, band, bw, powersave, &dhcp);
|
||||
on_cfg_line(line, ssid, pass, ip, mask, gw, band, bw, powersave, mode, &mon_ch, &dhcp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,15 @@ wifi_ps_type_t wifi_cfg_get_power_save_mode(void);
|
|||
*/
|
||||
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)
|
||||
*
|
||||
|
|
|
|||
|
|
@ -15,11 +15,12 @@ def log_verbose(message, verbose=False):
|
|||
|
||||
def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember",
|
||||
gateway="192.168.1.1", netmask="255.255.255.0",
|
||||
band="2.4G", bandwidth="HT20", powersave="NONE", reboot=True, verbose=False):
|
||||
band="2.4G", bandwidth="HT20", powersave="NONE",
|
||||
mode="STA", monitor_channel=36, reboot=True, verbose=False):
|
||||
"""Configure ESP32 device via serial with static IP"""
|
||||
|
||||
print(f"\n{'='*70}")
|
||||
print(f"ESP32 WiFi Configuration (Static IP)")
|
||||
print(f"ESP32 WiFi Configuration (Static IP + Mode)")
|
||||
print(f"{'='*70}")
|
||||
print(f"Port: {port}")
|
||||
print(f"SSID: {ssid}")
|
||||
|
|
@ -27,6 +28,9 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember",
|
|||
print(f"IP: {ip} (DHCP disabled)")
|
||||
print(f"Gateway: {gateway}")
|
||||
print(f"Netmask: {netmask}")
|
||||
print(f"Mode: {mode}")
|
||||
if mode == "MONITOR":
|
||||
print(f"Mon Ch: {monitor_channel}")
|
||||
print(f"Band: {band}")
|
||||
print(f"Bandwidth: {bandwidth}")
|
||||
print(f"PowerSave: {powersave}")
|
||||
|
|
@ -62,6 +66,8 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember",
|
|||
f"BAND:{band}",
|
||||
f"BW:{bandwidth}",
|
||||
f"POWERSAVE:{powersave}",
|
||||
f"MODE:{mode}",
|
||||
f"MON_CH:{monitor_channel}",
|
||||
"END"
|
||||
]
|
||||
|
||||
|
|
@ -270,23 +276,26 @@ def main():
|
|||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Examples:
|
||||
# Basic 2.4GHz configuration with static IP (DHCP disabled automatically)
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.51
|
||||
# Configure device #1 for STA mode (iperf baseline testing)
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -M STA
|
||||
|
||||
# 5GHz with 80MHz bandwidth
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -s ClubHouse5G -b 5G -B VHT80
|
||||
# Configure device #25 for MONITOR mode on channel 36 (collapse detection)
|
||||
%(prog)s -p /dev/ttyUSB1 -i 192.168.1.90 -M MONITOR -mc 36
|
||||
|
||||
# Monitor mode on 2.4GHz channel 6
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.91 -M MONITOR -mc 6 -b 2.4G
|
||||
|
||||
# STA mode on 5GHz with 40MHz bandwidth
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -M STA -b 5G -B HT40
|
||||
|
||||
# Disable power save for best CSI quality
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -ps NONE
|
||||
|
||||
# Enable minimum power save
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -ps MIN
|
||||
|
||||
# With verbose output
|
||||
%(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -v
|
||||
|
||||
Note: DHCP is always disabled when using this script since you're providing a static IP.
|
||||
The device will use the exact IP address you specify with -i.
|
||||
Note: Mode is saved to NVS and device will auto-start in configured mode on boot.
|
||||
DHCP is always disabled when using this script since you're providing a static IP.
|
||||
"""
|
||||
)
|
||||
|
||||
|
|
@ -310,6 +319,11 @@ Note: DHCP is always disabled when using this script since you're providing a st
|
|||
parser.add_argument('-ps', '--powersave', default='NONE',
|
||||
choices=['NONE', 'MIN', 'MIN_MODEM', 'MAX', 'MAX_MODEM'],
|
||||
help='Power save mode: NONE (no PS, best for CSI), MIN/MIN_MODEM, MAX/MAX_MODEM (default: NONE)')
|
||||
parser.add_argument('-M', '--mode', default='STA',
|
||||
choices=['STA', 'MONITOR'],
|
||||
help='Operating mode: STA (connect to AP, CSI+iperf) or MONITOR (promiscuous, collapse detection) (default: STA)')
|
||||
parser.add_argument('-mc', '--monitor-channel', type=int, default=36,
|
||||
help='Monitor mode channel (1-11 for 2.4GHz, 36-165 for 5GHz) (default: 36)')
|
||||
parser.add_argument('-r', '--no-reboot', action='store_true',
|
||||
help='Do NOT reboot device after configuration')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
|
|
@ -333,6 +347,8 @@ Note: DHCP is always disabled when using this script since you're providing a st
|
|||
band=args.band,
|
||||
bandwidth=args.bandwidth,
|
||||
powersave=args.powersave,
|
||||
mode=args.mode,
|
||||
monitor_channel=args.monitor_channel,
|
||||
reboot=not args.no_reboot,
|
||||
verbose=args.verbose
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,429 @@
|
|||
# Bandwidth and Band Selection Guide
|
||||
|
||||
## 🎯 New Features
|
||||
|
||||
### Monitor Mode: Channel + Bandwidth Selection
|
||||
Control both the channel AND bandwidth when monitoring:
|
||||
```bash
|
||||
mode_monitor 6/20 # 2.4GHz channel 6, 20MHz
|
||||
mode_monitor 36/80 # 5GHz channel 36, 80MHz
|
||||
```
|
||||
|
||||
### STA Mode: Band Preference
|
||||
Force connection to specific band:
|
||||
```bash
|
||||
mode_sta 2.4 # Connect on 2.4GHz only
|
||||
mode_sta 5 # Connect on 5GHz only
|
||||
mode_sta auto # Auto select (default)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 Monitor Mode Bandwidth Control
|
||||
|
||||
### Syntax
|
||||
```
|
||||
mode_monitor <channel>/<bandwidth>
|
||||
```
|
||||
|
||||
### 2.4GHz Band Bandwidth Options
|
||||
|
||||
**20MHz (HT20)** - Single channel
|
||||
```bash
|
||||
mode_monitor 1/20
|
||||
mode_monitor 6/20
|
||||
mode_monitor 11/20
|
||||
```
|
||||
- ✅ Maximum compatibility
|
||||
- ✅ Less interference from adjacent channels
|
||||
- ❌ Lower throughput (~72 Mbps max)
|
||||
|
||||
**40MHz (HT40)** - Channel bonding
|
||||
```bash
|
||||
mode_monitor 1/40
|
||||
mode_monitor 6/40
|
||||
mode_monitor 11/40
|
||||
```
|
||||
- ✅ Higher throughput (~150 Mbps max)
|
||||
- ⚠️ Uses 2 adjacent channels (more interference)
|
||||
- ⚠️ Not recommended in dense environments
|
||||
|
||||
**Default:** If bandwidth not specified, defaults to 20MHz
|
||||
```bash
|
||||
mode_monitor 6 # Same as 6/20
|
||||
```
|
||||
|
||||
### 5GHz Band Bandwidth Options
|
||||
|
||||
**20MHz (HT20)** - Single channel
|
||||
```bash
|
||||
mode_monitor 36/20
|
||||
mode_monitor 149/20
|
||||
```
|
||||
- ✅ Maximum compatibility
|
||||
- ✅ Best for long range
|
||||
- ❌ Lower throughput
|
||||
|
||||
**40MHz (HT40)** - Channel bonding
|
||||
```bash
|
||||
mode_monitor 36/40 # Channels 36+40
|
||||
mode_monitor 149/40 # Channels 149+153
|
||||
```
|
||||
- ✅ Good balance of speed and compatibility
|
||||
- ✅ WiFi 5 (802.11ac) standard
|
||||
- ⚠️ Uses 2 channels
|
||||
|
||||
**80MHz (HT80)** - Wide channel bonding (WiFi 6)
|
||||
```bash
|
||||
mode_monitor 36/80 # Channels 36+40+44+48
|
||||
mode_monitor 149/80 # Channels 149+153+157+161
|
||||
```
|
||||
- ✅ Maximum throughput (~866 Mbps+ with WiFi 6)
|
||||
- ✅ WiFi 6 (802.11ax) optimized
|
||||
- ⚠️ Uses 4 channels
|
||||
- ⚠️ Shorter range than 20/40MHz
|
||||
|
||||
**Default:** If bandwidth not specified, defaults to 40MHz on 5GHz
|
||||
```bash
|
||||
mode_monitor 149 # Same as 149/40
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 STA Mode Band Selection
|
||||
|
||||
### Syntax
|
||||
```
|
||||
mode_sta [band]
|
||||
```
|
||||
|
||||
### Band Options
|
||||
|
||||
**Auto (Default)** - Let ESP32 choose best band
|
||||
```bash
|
||||
mode_sta
|
||||
mode_sta auto
|
||||
```
|
||||
- ✅ Connects to strongest signal
|
||||
- ✅ Falls back if preferred band unavailable
|
||||
- Use when: AP supports both bands
|
||||
|
||||
**2.4GHz Only**
|
||||
```bash
|
||||
mode_sta 2.4
|
||||
mode_sta 2
|
||||
```
|
||||
- ✅ Forces connection on 2.4GHz
|
||||
- ✅ Better range, wall penetration
|
||||
- ❌ Lower speed, more interference
|
||||
- Use when: Need maximum range
|
||||
|
||||
**5GHz Only**
|
||||
```bash
|
||||
mode_sta 5
|
||||
mode_sta 5.0
|
||||
```
|
||||
- ✅ Forces connection on 5GHz
|
||||
- ✅ Higher speed, less interference
|
||||
- ❌ Shorter range
|
||||
- Use when: AP is close, need best performance
|
||||
|
||||
---
|
||||
|
||||
## 📊 Usage Examples
|
||||
|
||||
### Example 1: 2.4GHz Narrow Band Monitoring
|
||||
For maximum interference rejection in dense environment:
|
||||
```bash
|
||||
esp32> mode_monitor 6/20
|
||||
|
||||
I (+1733424645.234) MAIN: Switching to MONITOR MODE
|
||||
I (+1733424645.235) MAIN: Channel: 6 (2.4GHz)
|
||||
I (+1733424645.236) MAIN: Bandwidth: 20MHz
|
||||
I (+1733424647.567) MAIN: ✓ Monitor mode active
|
||||
```
|
||||
|
||||
### Example 2: 2.4GHz Wide Band Monitoring
|
||||
For maximum throughput testing:
|
||||
```bash
|
||||
esp32> mode_monitor 6/40
|
||||
|
||||
I (+1733424645.234) MAIN: Switching to MONITOR MODE
|
||||
I (+1733424645.235) MAIN: Channel: 6 (2.4GHz)
|
||||
I (+1733424645.236) MAIN: Bandwidth: 40MHz
|
||||
```
|
||||
|
||||
### Example 3: 5GHz WiFi 6 Monitoring
|
||||
For WiFi 6 collapse detection with 80MHz:
|
||||
```bash
|
||||
esp32> mode_monitor 36/80
|
||||
|
||||
I (+1733424645.234) MAIN: Switching to MONITOR MODE
|
||||
I (+1733424645.235) MAIN: Channel: 36 (5GHz)
|
||||
I (+1733424645.236) MAIN: Bandwidth: 80MHz
|
||||
I (+1733424647.567) MAIN: ✓ Monitor mode active
|
||||
```
|
||||
|
||||
### Example 4: Force 5GHz Connection
|
||||
Connect to AP on 5GHz band only:
|
||||
```bash
|
||||
esp32> mode_sta 5
|
||||
|
||||
I (+1733424645.234) MAIN: Switching to STA MODE
|
||||
I (+1733424645.235) MAIN: Band preference: 5GHz only
|
||||
I (+1733424647.234) MAIN: Got IP: 192.168.1.100
|
||||
I (+1733424647.567) MAIN: ✓ STA mode active
|
||||
```
|
||||
|
||||
### Example 5: Check Current Configuration
|
||||
```bash
|
||||
esp32> mode_status
|
||||
|
||||
=== WiFi Mode Status ===
|
||||
Current mode: MONITOR
|
||||
LED state: Blue solid (Monitoring)
|
||||
Monitor channel: 36 (5GHz)
|
||||
Monitor bandwidth: 80MHz
|
||||
Monitor enabled: Yes
|
||||
Frames captured: 15234
|
||||
GPS synced: Yes (+)
|
||||
```
|
||||
|
||||
### Example 6: Switch Between Bandwidths
|
||||
Test different bandwidths on same channel:
|
||||
```bash
|
||||
# Start with 20MHz
|
||||
esp32> mode_monitor 149/20
|
||||
[collect data for 5 minutes...]
|
||||
|
||||
# Switch to 40MHz
|
||||
esp32> mode_monitor 149/40
|
||||
[collect data for 5 minutes...]
|
||||
|
||||
# Switch to 80MHz
|
||||
esp32> mode_monitor 149/80
|
||||
[collect data for 5 minutes...]
|
||||
|
||||
# Compare collapse rates vs bandwidth
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Bandwidth Selection Strategy
|
||||
|
||||
### When to Use 20MHz
|
||||
|
||||
**Best for:**
|
||||
- Dense environments with many APs
|
||||
- Long-range connections
|
||||
- Interference-prone areas
|
||||
- Maximum compatibility
|
||||
|
||||
**Monitor mode:**
|
||||
```bash
|
||||
mode_monitor 6/20 # 2.4GHz
|
||||
mode_monitor 149/20 # 5GHz
|
||||
```
|
||||
|
||||
### When to Use 40MHz
|
||||
|
||||
**Best for:**
|
||||
- Medium-density environments
|
||||
- Balance of speed and range
|
||||
- Most common configuration
|
||||
- WiFi 5 (802.11ac)
|
||||
|
||||
**Monitor mode:**
|
||||
```bash
|
||||
mode_monitor 6/40 # 2.4GHz (not recommended in dense areas)
|
||||
mode_monitor 149/40 # 5GHz (recommended)
|
||||
```
|
||||
|
||||
### When to Use 80MHz
|
||||
|
||||
**Best for:**
|
||||
- Low-density environments
|
||||
- Maximum throughput
|
||||
- WiFi 6 (802.11ax) testing
|
||||
- Short-range, high-speed links
|
||||
|
||||
**Monitor mode (5GHz only):**
|
||||
```bash
|
||||
mode_monitor 36/80
|
||||
mode_monitor 149/80
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 Real-World Scenarios
|
||||
|
||||
### Scenario 1: Office WiFi Collapse Detection
|
||||
**Goal:** Monitor office WiFi on 5GHz with WiFi 6
|
||||
|
||||
```bash
|
||||
# 1. Connect to AP and check its configuration
|
||||
esp32> mode_sta
|
||||
[wait for connection...]
|
||||
|
||||
esp32> mode_status
|
||||
Connected band: 5GHz (channel 36)
|
||||
Bandwidth: 80MHz
|
||||
|
||||
# 2. Switch to monitor mode with same config
|
||||
esp32> mode_monitor 36/80
|
||||
|
||||
# 3. Monitor for collapse events
|
||||
[Logs GPS-timestamped collapse events...]
|
||||
```
|
||||
|
||||
### Scenario 2: 2.4GHz Congestion Analysis
|
||||
**Goal:** Compare 20MHz vs 40MHz collapse rates
|
||||
|
||||
```bash
|
||||
# Test 20MHz (narrow band)
|
||||
esp32> mode_monitor 6/20
|
||||
[collect for 30 minutes...]
|
||||
# Note collapse count
|
||||
|
||||
# Test 40MHz (wide band)
|
||||
esp32> mode_monitor 6/40
|
||||
[collect for 30 minutes...]
|
||||
# Compare: 40MHz likely has MORE collapses in dense area
|
||||
```
|
||||
|
||||
### Scenario 3: Force 5GHz for Performance
|
||||
**Goal:** Ensure device connects on 5GHz only
|
||||
|
||||
```bash
|
||||
# Force 5GHz connection
|
||||
esp32> mode_sta 5
|
||||
|
||||
# Verify connected on 5GHz
|
||||
esp32> mode_status
|
||||
Band preference: 5GHz only
|
||||
Connected band: 5GHz (channel 149)
|
||||
Bandwidth: 80MHz
|
||||
|
||||
# Now switch to monitor on same channel
|
||||
esp32> mode_monitor 149/80
|
||||
```
|
||||
|
||||
### Scenario 4: Multi-Device Deployment
|
||||
**Goal:** Monitor different bandwidths across 32 devices
|
||||
|
||||
```bash
|
||||
# Devices 1-8: 2.4GHz 20MHz
|
||||
Device 1-8: mode_monitor 6/20
|
||||
|
||||
# Devices 9-16: 2.4GHz 40MHz
|
||||
Device 9-16: mode_monitor 6/40
|
||||
|
||||
# Devices 17-24: 5GHz 40MHz
|
||||
Device 17-24: mode_monitor 149/40
|
||||
|
||||
# Devices 25-32: 5GHz 80MHz
|
||||
Device 25-32: mode_monitor 149/80
|
||||
|
||||
# Compare collapse rates across all configurations!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Performance Expectations
|
||||
|
||||
### 2.4GHz Performance
|
||||
|
||||
| Bandwidth | Max PHY Rate | Typical Throughput | Range | Interference |
|
||||
|-----------|-------------|-------------------|-------|--------------|
|
||||
| 20MHz | ~72 Mbps | 40-50 Mbps | Best | Least |
|
||||
| 40MHz | ~150 Mbps | 80-100 Mbps | Good | Most |
|
||||
|
||||
### 5GHz Performance
|
||||
|
||||
| Bandwidth | Max PHY Rate | Typical Throughput | Range | Best Use |
|
||||
|-----------|-------------|-------------------|-------|----------|
|
||||
| 20MHz | ~87 Mbps | 50-60 Mbps | Best | Long range |
|
||||
| 40MHz | ~200 Mbps | 120-150 Mbps | Good | Balanced |
|
||||
| 80MHz | ~433 Mbps | 300-400 Mbps | Short | Max speed |
|
||||
|
||||
*Note: WiFi 6 (802.11ax) can achieve higher rates with OFDMA and 1024-QAM*
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Advanced Usage
|
||||
|
||||
### Match Your AP's Configuration
|
||||
Always match bandwidth to your AP for best results:
|
||||
|
||||
```bash
|
||||
# 1. Check AP configuration (via router admin or WiFi analyzer)
|
||||
# Example: AP is on channel 36 with 80MHz
|
||||
|
||||
# 2. Configure STA mode to connect
|
||||
esp32> mode_sta 5
|
||||
|
||||
# 3. Verify connection
|
||||
esp32> mode_status
|
||||
Connected band: 5GHz (channel 36)
|
||||
Bandwidth: 80MHz
|
||||
|
||||
# 4. Switch to monitor with SAME configuration
|
||||
esp32> mode_monitor 36/80
|
||||
```
|
||||
|
||||
### Test Bandwidth Impact on Collapse
|
||||
```python
|
||||
# After collecting data at different bandwidths:
|
||||
import pandas as pd
|
||||
|
||||
df_20 = pd.read_csv('collapses_ch36_20mhz.csv')
|
||||
df_40 = pd.read_csv('collapses_ch36_40mhz.csv')
|
||||
df_80 = pd.read_csv('collapses_ch36_80mhz.csv')
|
||||
|
||||
print("Collapse rate (20MHz):", len(df_20) / 3600, "per hour")
|
||||
print("Collapse rate (40MHz):", len(df_40) / 3600, "per hour")
|
||||
print("Collapse rate (80MHz):", len(df_80) / 3600, "per hour")
|
||||
|
||||
# Hypothesis: Wider bandwidth = more collapses in dense environments
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Quick Reference
|
||||
|
||||
### Monitor Mode Bandwidths
|
||||
|
||||
| Band | Command | Bandwidth | Use Case |
|
||||
|------|---------|-----------|----------|
|
||||
| 2.4GHz | `mode_monitor 6/20` | 20MHz | Dense area, max compatibility |
|
||||
| 2.4GHz | `mode_monitor 6/40` | 40MHz | Speed test (avoid in dense area) |
|
||||
| 5GHz | `mode_monitor 149/20` | 20MHz | Long range |
|
||||
| 5GHz | `mode_monitor 149/40` | 40MHz | Balanced (default) |
|
||||
| 5GHz | `mode_monitor 149/80` | 80MHz | WiFi 6 max speed |
|
||||
|
||||
### STA Mode Bands
|
||||
|
||||
| Command | Behavior | Use Case |
|
||||
|---------|----------|----------|
|
||||
| `mode_sta` | Auto select | Default, best signal |
|
||||
| `mode_sta 2.4` | Force 2.4GHz | Max range |
|
||||
| `mode_sta 5` | Force 5GHz | Max performance |
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Summary
|
||||
|
||||
**New capabilities:**
|
||||
- ✅ Monitor mode with bandwidth control (20/40/80MHz)
|
||||
- ✅ STA mode with band preference (2.4/5/auto)
|
||||
- ✅ Full control over WiFi 6 configurations
|
||||
- ✅ Test different bandwidths for collapse analysis
|
||||
- ✅ Force band for optimal performance
|
||||
|
||||
**Syntax:**
|
||||
```bash
|
||||
mode_monitor <channel>/<bandwidth> # e.g., 36/80
|
||||
mode_sta [band] # e.g., mode_sta 5
|
||||
```
|
||||
|
||||
Now you can precisely control and test WiFi configurations across all supported bands and bandwidths!
|
||||
|
|
@ -0,0 +1,779 @@
|
|||
================================================================================
|
||||
ESP32-C5 CONFIGURATION DEVICE MANUAL
|
||||
config_device.py v2.0
|
||||
================================================================================
|
||||
|
||||
TABLE OF CONTENTS
|
||||
-----------------
|
||||
1. Overview
|
||||
2. Installation Requirements
|
||||
3. Quick Start
|
||||
4. Command-Line Arguments
|
||||
5. Usage Examples
|
||||
6. Operating Modes
|
||||
7. Configuration Parameters
|
||||
8. Troubleshooting
|
||||
9. Advanced Usage
|
||||
10. Common Deployment Scenarios
|
||||
|
||||
================================================================================
|
||||
1. OVERVIEW
|
||||
================================================================================
|
||||
|
||||
config_device.py is a Python script that configures ESP32-C5 devices via
|
||||
serial connection. It sets WiFi credentials, network parameters, operating
|
||||
mode (STA or MONITOR), and all other device settings which are stored in
|
||||
Non-Volatile Storage (NVS) for persistence across reboots.
|
||||
|
||||
Key Features:
|
||||
• Static IP configuration with automatic DHCP disable
|
||||
• Operating mode selection (STA for iperf, MONITOR for WiFi analysis)
|
||||
• Monitor channel configuration
|
||||
• Power save mode control
|
||||
• WiFi band and bandwidth selection
|
||||
• Automatic device reboot after configuration
|
||||
• Comprehensive status feedback
|
||||
|
||||
================================================================================
|
||||
2. INSTALLATION REQUIREMENTS
|
||||
================================================================================
|
||||
|
||||
Python Requirements:
|
||||
• Python 3.6 or later
|
||||
• pyserial module
|
||||
|
||||
Install pyserial:
|
||||
$ pip install pyserial
|
||||
|
||||
or
|
||||
|
||||
$ pip3 install pyserial
|
||||
|
||||
System Requirements:
|
||||
• Serial port access (Linux: /dev/ttyUSB*, macOS: /dev/cu.*, Windows: COM*)
|
||||
• User permissions for serial port access
|
||||
|
||||
Linux serial port permissions:
|
||||
$ sudo usermod -a -G dialout $USER
|
||||
(then logout and login)
|
||||
|
||||
Verify installation:
|
||||
$ python3 config_device.py --help
|
||||
|
||||
================================================================================
|
||||
3. QUICK START
|
||||
================================================================================
|
||||
|
||||
Basic STA Mode Configuration:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81
|
||||
|
||||
Basic MONITOR Mode Configuration:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.90 \\
|
||||
-M MONITOR -mc 36
|
||||
|
||||
With verbose output:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -v
|
||||
|
||||
================================================================================
|
||||
4. COMMAND-LINE ARGUMENTS
|
||||
================================================================================
|
||||
|
||||
REQUIRED ARGUMENTS
|
||||
------------------
|
||||
|
||||
-p, --port PORT
|
||||
Serial port device
|
||||
Examples: /dev/ttyUSB0, /dev/ttyUSB1, COM3
|
||||
Required: YES
|
||||
|
||||
-i, --ip IP_ADDRESS
|
||||
Static IP address for the device
|
||||
DHCP is automatically disabled when using this script
|
||||
Examples: 192.168.1.81, 10.0.0.50
|
||||
Required: YES
|
||||
|
||||
OPTIONAL ARGUMENTS - WiFi Settings
|
||||
-----------------------------------
|
||||
|
||||
-s, --ssid SSID
|
||||
WiFi network name (SSID)
|
||||
Default: ClubHouse2G
|
||||
Example: -s "MyNetwork"
|
||||
|
||||
-P, --password PASSWORD
|
||||
WiFi password
|
||||
Default: ez2remember
|
||||
Example: -P "MySecurePassword123"
|
||||
|
||||
OPTIONAL ARGUMENTS - Network Settings
|
||||
--------------------------------------
|
||||
|
||||
-g, --gateway IP_ADDRESS
|
||||
Gateway IP address
|
||||
Default: 192.168.1.1
|
||||
Example: -g 192.168.1.1
|
||||
|
||||
-m, --netmask NETMASK
|
||||
Network mask
|
||||
Default: 255.255.255.0
|
||||
Example: -m 255.255.255.0
|
||||
|
||||
OPTIONAL ARGUMENTS - WiFi Configuration
|
||||
----------------------------------------
|
||||
|
||||
-b, --band {2.4G,5G}
|
||||
WiFi frequency band
|
||||
Options:
|
||||
2.4G - 2.4 GHz band (channels 1-11 in US)
|
||||
5G - 5 GHz band (channels 36-165)
|
||||
Default: 2.4G
|
||||
Example: -b 5G
|
||||
|
||||
-B, --bandwidth {HT20,HT40,VHT80}
|
||||
Channel bandwidth
|
||||
Options:
|
||||
HT20 - 20 MHz (2.4GHz or 5GHz)
|
||||
HT40 - 40 MHz (2.4GHz or 5GHz)
|
||||
VHT80 - 80 MHz (5GHz only)
|
||||
Default: HT20
|
||||
Notes:
|
||||
• VHT80 requires 5GHz band (-b 5G)
|
||||
• Monitor mode forces 20MHz regardless of setting
|
||||
Example: -B HT40
|
||||
|
||||
-ps, --powersave {NONE,MIN,MIN_MODEM,MAX,MAX_MODEM}
|
||||
Power saving mode
|
||||
Options:
|
||||
NONE - No power saving (best for CSI, highest power)
|
||||
MIN - Minimum power save (alias for MIN_MODEM)
|
||||
MIN_MODEM - Minimum modem power save
|
||||
MAX - Maximum power save (alias for MAX_MODEM)
|
||||
MAX_MODEM - Maximum modem power save (lowest power)
|
||||
Default: NONE
|
||||
Recommendation: Use NONE for CSI capture and WiFi analysis
|
||||
Example: -ps NONE
|
||||
|
||||
OPTIONAL ARGUMENTS - Operating Mode
|
||||
------------------------------------
|
||||
|
||||
-M, --mode {STA,MONITOR}
|
||||
Operating mode
|
||||
Options:
|
||||
STA - Station mode (connect to AP, run iperf, CSI capture)
|
||||
MONITOR - Monitor mode (promiscuous WiFi packet capture)
|
||||
Default: STA
|
||||
Example: -M MONITOR
|
||||
|
||||
-mc, --monitor-channel CHANNEL
|
||||
Monitor mode channel number
|
||||
Valid ranges:
|
||||
2.4GHz: 1-11 (US)
|
||||
5GHz: 36, 40, 44, 48 (UNII-1)
|
||||
149, 153, 157, 161, 165 (UNII-3)
|
||||
Default: 36
|
||||
Note: Only used when mode is MONITOR
|
||||
Example: -mc 149
|
||||
|
||||
OPTIONAL ARGUMENTS - Script Behavior
|
||||
-------------------------------------
|
||||
|
||||
-r, --no-reboot
|
||||
Do NOT reboot device after configuration
|
||||
Default: Device is rebooted automatically
|
||||
Use this flag to configure without rebooting
|
||||
Example: -r
|
||||
|
||||
-v, --verbose
|
||||
Enable verbose output
|
||||
Shows detailed serial communication and debug information
|
||||
Example: -v
|
||||
|
||||
-h, --help
|
||||
Show help message and exit
|
||||
|
||||
================================================================================
|
||||
5. USAGE EXAMPLES
|
||||
================================================================================
|
||||
|
||||
BASIC EXAMPLES
|
||||
--------------
|
||||
|
||||
Example 1: Configure device for STA mode with defaults
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81
|
||||
|
||||
Result:
|
||||
• SSID: ClubHouse2G
|
||||
• Password: ez2remember
|
||||
• IP: 192.168.1.81
|
||||
• Mode: STA
|
||||
• Band: 2.4GHz
|
||||
• Bandwidth: 20MHz
|
||||
|
||||
|
||||
Example 2: Configure device for MONITOR mode on channel 36
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.90 \\
|
||||
-M MONITOR -mc 36
|
||||
|
||||
Result:
|
||||
• Device boots in STA mode to connect to WiFi
|
||||
• After GPS sync, auto-switches to MONITOR mode on channel 36
|
||||
• Captures all WiFi traffic on channel 36
|
||||
|
||||
|
||||
Example 3: 5GHz with 40MHz bandwidth, STA mode
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 \\
|
||||
-s ClubHouse5G -b 5G -B HT40
|
||||
|
||||
Result:
|
||||
• Connects to ClubHouse5G SSID
|
||||
• Uses 5GHz band with 40MHz bandwidth
|
||||
• STA mode (default)
|
||||
|
||||
|
||||
Example 4: Custom WiFi credentials
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 \\
|
||||
-s "MyNetwork" -P "MyPassword123"
|
||||
|
||||
Result:
|
||||
• Connects to "MyNetwork" with password "MyPassword123"
|
||||
• Uses default 2.4GHz, 20MHz, STA mode
|
||||
|
||||
|
||||
Example 5: Configure without rebooting
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -r
|
||||
|
||||
Result:
|
||||
• Configuration saved to NVS
|
||||
• Device does NOT reboot
|
||||
• Must manually reboot to apply settings
|
||||
|
||||
ADVANCED EXAMPLES
|
||||
-----------------
|
||||
|
||||
Example 6: MONITOR mode on 2.4GHz channel 6
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.91 \\
|
||||
-M MONITOR -mc 6 -b 2.4G
|
||||
|
||||
Result:
|
||||
• Monitor mode on 2.4GHz channel 6
|
||||
• Good for monitoring 2.4GHz WiFi collapse
|
||||
|
||||
|
||||
Example 7: Verbose output for debugging
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -v
|
||||
|
||||
Result:
|
||||
• Shows detailed serial communication
|
||||
• Displays all bytes sent/received
|
||||
• Useful for troubleshooting
|
||||
|
||||
|
||||
Example 8: Multiple channels for different devices
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.90 \\
|
||||
-M MONITOR -mc 36
|
||||
$ python3 config_device.py -p /dev/ttyUSB1 -i 192.168.1.91 \\
|
||||
-M MONITOR -mc 40
|
||||
$ python3 config_device.py -p /dev/ttyUSB2 -i 192.168.1.92 \\
|
||||
-M MONITOR -mc 44
|
||||
|
||||
Result:
|
||||
• Device .90 monitors channel 36
|
||||
• Device .91 monitors channel 40
|
||||
• Device .92 monitors channel 44
|
||||
• Comprehensive 5GHz band monitoring
|
||||
|
||||
|
||||
Example 9: Different network settings
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 10.0.0.100 \\
|
||||
-g 10.0.0.1 -m 255.255.255.0 -s "OfficeWiFi" -P "Office2025"
|
||||
|
||||
Result:
|
||||
• IP: 10.0.0.100
|
||||
• Gateway: 10.0.0.1
|
||||
• SSID: OfficeWiFi
|
||||
• Different network configuration
|
||||
|
||||
================================================================================
|
||||
6. OPERATING MODES
|
||||
================================================================================
|
||||
|
||||
STA MODE (Station Mode)
|
||||
-----------------------
|
||||
Purpose: Connect to WiFi access point as a client
|
||||
Use Cases:
|
||||
• iperf baseline testing
|
||||
• CSI (Channel State Information) capture
|
||||
• Network performance measurement
|
||||
• Standard WiFi connectivity
|
||||
|
||||
Behavior:
|
||||
1. Device connects to configured WiFi AP
|
||||
2. Obtains configured static IP address
|
||||
3. Runs iperf server on port 5001
|
||||
4. Captures CSI data
|
||||
5. Maintains WiFi connection
|
||||
6. LED: Green (connected)
|
||||
|
||||
Configuration:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -M STA
|
||||
|
||||
Features Active in STA Mode:
|
||||
• WiFi connectivity
|
||||
• iperf server
|
||||
• CSI capture
|
||||
• GPS timestamping
|
||||
• Network services
|
||||
|
||||
MONITOR MODE (Promiscuous Mode)
|
||||
--------------------------------
|
||||
Purpose: Capture all WiFi packets on a specific channel
|
||||
Use Cases:
|
||||
• WiFi collapse detection
|
||||
• Network traffic analysis
|
||||
• Protocol debugging
|
||||
• Security research
|
||||
|
||||
Behavior:
|
||||
1. Device connects to WiFi AP initially (for GPS sync)
|
||||
2. Gets static IP address
|
||||
3. Waits for WiFi connection (LED: Green)
|
||||
4. Waits 2 seconds for GPS sync
|
||||
5. Switches to MONITOR mode on configured channel
|
||||
6. Captures all WiFi packets on that channel
|
||||
7. LED: Blue (monitoring)
|
||||
|
||||
Configuration:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.90 \\
|
||||
-M MONITOR -mc 36
|
||||
|
||||
Features Active in MONITOR Mode:
|
||||
• Promiscuous packet capture
|
||||
• WiFi frame analysis (RTS/CTS/ACK/Beacon/Data)
|
||||
• GPS timestamping
|
||||
• CSI capture
|
||||
• No WiFi connectivity (after switch)
|
||||
|
||||
Important Notes:
|
||||
• Monitor mode is read-only (no transmit)
|
||||
• Device disconnects from AP after switching to monitor
|
||||
• Monitor mode always uses 20MHz bandwidth (driver limitation)
|
||||
• Best for detecting WiFi collapse events
|
||||
|
||||
================================================================================
|
||||
7. CONFIGURATION PARAMETERS
|
||||
================================================================================
|
||||
|
||||
STORED IN NVS (Non-Volatile Storage)
|
||||
-------------------------------------
|
||||
|
||||
The following parameters are stored in NVS and persist across reboots:
|
||||
|
||||
| Parameter | NVS Key | Type | Default | Description |
|
||||
|------------|------------|---------|--------------|----------------------------|
|
||||
| SSID | ssid | string | ClubHouse2G | WiFi network name |
|
||||
| Password | pass | string | ez2remember | WiFi password |
|
||||
| IP Address | ip | string | (required) | Static IP address |
|
||||
| Netmask | mask | string | 255.255.255.0| Network mask |
|
||||
| Gateway | gw | string | 192.168.1.1 | Gateway IP |
|
||||
| DHCP | dhcp | bool | false | Always false (static IP) |
|
||||
| Band | band | string | 2.4G | WiFi band (2.4G or 5G) |
|
||||
| Bandwidth | bw | string | HT20 | Channel bandwidth |
|
||||
| PowerSave | powersave | string | NONE | Power save mode |
|
||||
| Mode | mode | string | STA | Operating mode |
|
||||
| Mon Ch | mon_ch | uint8_t | 36 | Monitor mode channel |
|
||||
|
||||
BANDWIDTH OPTIONS
|
||||
-----------------
|
||||
|
||||
HT20 (20 MHz):
|
||||
• Compatible with: 2.4GHz and 5GHz
|
||||
• Maximum throughput: ~72 Mbps (802.11n)
|
||||
• Best for: Compatibility, monitor mode
|
||||
• Channels used: 1 channel
|
||||
|
||||
HT40 (40 MHz):
|
||||
• Compatible with: 2.4GHz and 5GHz
|
||||
• Maximum throughput: ~150 Mbps (802.11n)
|
||||
• Best for: Higher throughput
|
||||
• Channels used: 2 adjacent channels
|
||||
• Note: Monitor mode forces to 20MHz
|
||||
|
||||
VHT80 (80 MHz):
|
||||
• Compatible with: 5GHz only
|
||||
• Maximum throughput: ~433 Mbps (802.11ac)
|
||||
• Best for: Maximum throughput
|
||||
• Channels used: 4 adjacent channels
|
||||
• Note: Monitor mode forces to 20MHz
|
||||
• Requires: -b 5G
|
||||
|
||||
CHANNEL SELECTION
|
||||
-----------------
|
||||
|
||||
2.4GHz Channels (US):
|
||||
• Non-overlapping: 1, 6, 11
|
||||
• All available: 1-11
|
||||
• Bandwidth: 20MHz or 40MHz
|
||||
• Example: -mc 6 -b 2.4G
|
||||
|
||||
5GHz Channels (US):
|
||||
• UNII-1: 36, 40, 44, 48 (5.15-5.25 GHz)
|
||||
• UNII-2: 52, 56, 60, 64 (5.25-5.35 GHz, DFS)
|
||||
• UNII-2e: 100-144 (5.47-5.725 GHz, DFS)
|
||||
• UNII-3: 149, 153, 157, 161, 165 (5.725-5.85 GHz)
|
||||
• Bandwidth: 20MHz, 40MHz, or 80MHz
|
||||
• Example: -mc 36 -b 5G
|
||||
|
||||
Recommended Monitor Channels:
|
||||
• 2.4GHz: 1, 6, 11 (non-overlapping)
|
||||
• 5GHz: 36, 149 (no DFS, always available)
|
||||
|
||||
================================================================================
|
||||
8. TROUBLESHOOTING
|
||||
================================================================================
|
||||
|
||||
COMMON ISSUES
|
||||
-------------
|
||||
|
||||
Issue: "Serial error: [Errno 13] Permission denied: '/dev/ttyUSB0'"
|
||||
Solution:
|
||||
1. Add user to dialout group:
|
||||
$ sudo usermod -a -G dialout $USER
|
||||
2. Logout and login
|
||||
3. Verify:
|
||||
$ groups | grep dialout
|
||||
|
||||
Issue: "No response from device"
|
||||
Possible Causes:
|
||||
1. Wrong serial port
|
||||
Solution: Check with: ls /dev/ttyUSB*
|
||||
2. Another program using the port
|
||||
Solution: Close other programs (idf.py monitor, screen, minicom)
|
||||
3. Wrong baud rate
|
||||
Solution: Script uses 115200 (correct for ESP32-C5)
|
||||
4. Device not running config handler
|
||||
Solution: Flash latest firmware
|
||||
|
||||
Issue: "Device got different IP than configured"
|
||||
Possible Causes:
|
||||
1. DHCP still enabled (shouldn't happen with this script)
|
||||
Solution: Check device logs for "DHCP:0"
|
||||
2. IP conflict on network
|
||||
Solution: Use different IP address
|
||||
3. Router forcing DHCP
|
||||
Solution: Check router settings, reserve IP
|
||||
|
||||
Issue: "VHT80 error"
|
||||
Message: "✗ Error: VHT80 (80MHz) is only supported on 5GHz band"
|
||||
Solution:
|
||||
• Use -b 5G with -B VHT80
|
||||
• Or use -B HT20 or -B HT40 for 2.4GHz
|
||||
|
||||
Issue: "Device not switching to MONITOR mode"
|
||||
Possible Causes:
|
||||
1. WiFi not connected first
|
||||
Solution: Check logs for "WiFi CONNECTED"
|
||||
2. GPS not syncing
|
||||
Solution: Wait 30-60 seconds for GPS lock
|
||||
3. Wrong firmware version
|
||||
Solution: Flash latest firmware with auto_monitor_task
|
||||
|
||||
Issue: "Configuration not persisting after reboot"
|
||||
Possible Causes:
|
||||
1. NVS partition corrupted
|
||||
Solution: Erase flash and reconfigure:
|
||||
$ idf.py -p /dev/ttyUSB0 erase-flash
|
||||
$ idf.py -p /dev/ttyUSB0 flash
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81
|
||||
|
||||
VERBOSE MODE DEBUGGING
|
||||
----------------------
|
||||
|
||||
Enable verbose mode to see detailed information:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -v
|
||||
|
||||
Verbose output shows:
|
||||
• Serial port settings
|
||||
• Bytes sent/received
|
||||
• Configuration message contents
|
||||
• Device response parsing
|
||||
• Error details with traceback
|
||||
|
||||
SERIAL PORT VERIFICATION
|
||||
-------------------------
|
||||
|
||||
List available serial ports:
|
||||
Linux: $ ls -l /dev/ttyUSB*
|
||||
macOS: $ ls -l /dev/cu.*
|
||||
Windows: $ mode
|
||||
|
||||
Test serial port communication:
|
||||
$ python3 -m serial.tools.miniterm /dev/ttyUSB0 115200
|
||||
|
||||
================================================================================
|
||||
9. ADVANCED USAGE
|
||||
================================================================================
|
||||
|
||||
BATCH CONFIGURATION
|
||||
-------------------
|
||||
|
||||
Configure multiple devices with a script:
|
||||
|
||||
#!/bin/bash
|
||||
# configure_devices.sh
|
||||
|
||||
# STA mode devices (.81-.89)
|
||||
for i in {81..89}; do
|
||||
port=$((i-81))
|
||||
echo "Configuring device $i on /dev/ttyUSB$port (STA mode)"
|
||||
python3 config_device.py -p /dev/ttyUSB$port -i 192.168.1.$i -M STA
|
||||
sleep 2
|
||||
done
|
||||
|
||||
# MONITOR mode devices (.90-.98)
|
||||
for i in {90..98}; do
|
||||
port=$((i-81))
|
||||
echo "Configuring device $i on /dev/ttyUSB$port (MONITOR mode)"
|
||||
python3 config_device.py -p /dev/ttyUSB$port -i 192.168.1.$i \\
|
||||
-M MONITOR -mc 36
|
||||
sleep 2
|
||||
done
|
||||
|
||||
Usage:
|
||||
$ chmod +x configure_devices.sh
|
||||
$ ./configure_devices.sh
|
||||
|
||||
CONFIGURATION WITHOUT REBOOT
|
||||
-----------------------------
|
||||
|
||||
Use -r flag to configure without rebooting:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -r
|
||||
|
||||
Then manually reboot later:
|
||||
• Press RESET button on device
|
||||
• Or use: idf.py -p /dev/ttyUSB0 monitor (then Ctrl+T, Ctrl+R)
|
||||
• Or power cycle
|
||||
|
||||
MULTI-CHANNEL MONITORING
|
||||
-------------------------
|
||||
|
||||
Deploy devices across multiple channels:
|
||||
|
||||
channels=(36 40 44 48 149 153 157 161)
|
||||
start_ip=90
|
||||
|
||||
for i in "${!channels[@]}"; do
|
||||
ch=${channels[$i]}
|
||||
ip=$((start_ip + i))
|
||||
port=$i
|
||||
echo "Device $ip: Monitor channel $ch on /dev/ttyUSB$port"
|
||||
python3 config_device.py -p /dev/ttyUSB$port -i 192.168.1.$ip \\
|
||||
-M MONITOR -mc $ch -b 5G
|
||||
done
|
||||
|
||||
DIFFERENT POWER SAVE MODES
|
||||
---------------------------
|
||||
|
||||
Test different power save modes:
|
||||
|
||||
# Device 1: No power save (best for CSI)
|
||||
python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -ps NONE
|
||||
|
||||
# Device 2: Minimum power save
|
||||
python3 config_device.py -p /dev/ttyUSB1 -i 192.168.1.82 -ps MIN
|
||||
|
||||
# Device 3: Maximum power save
|
||||
python3 config_device.py -p /dev/ttyUSB2 -i 192.168.1.83 -ps MAX
|
||||
|
||||
INTEGRATION WITH MONITORING SCRIPTS
|
||||
------------------------------------
|
||||
|
||||
Configure device and start monitoring:
|
||||
|
||||
#!/bin/bash
|
||||
# deploy_and_monitor.sh
|
||||
|
||||
DEVICE_IP="192.168.1.90"
|
||||
PORT="/dev/ttyUSB0"
|
||||
|
||||
# Configure device
|
||||
python3 config_device.py -p $PORT -i $DEVICE_IP -M MONITOR -mc 36
|
||||
|
||||
# Wait for reboot
|
||||
sleep 10
|
||||
|
||||
# Start monitoring
|
||||
idf.py -p $PORT monitor | tee device_90.log
|
||||
|
||||
================================================================================
|
||||
10. COMMON DEPLOYMENT SCENARIOS
|
||||
================================================================================
|
||||
|
||||
SCENARIO 1: WIFI COLLAPSE DETECTION (32 devices)
|
||||
-------------------------------------------------
|
||||
|
||||
Goal: Detect WiFi collapse events and correlate with iperf degradation
|
||||
|
||||
Setup:
|
||||
• 9 devices in STA mode (.81-.89) for iperf baseline
|
||||
• 9 devices in MONITOR mode (.90-.98) for collapse detection
|
||||
• All on 5GHz channel 36
|
||||
|
||||
Configuration:
|
||||
# STA devices
|
||||
for i in {81..89}; do
|
||||
python3 config_device.py -p /dev/ttyUSB$((i-81)) \\
|
||||
-i 192.168.1.$i -M STA -b 5G -B HT20 -ps NONE
|
||||
done
|
||||
|
||||
# MONITOR devices
|
||||
for i in {90..98}; do
|
||||
python3 config_device.py -p /dev/ttyUSB$((i-81)) \\
|
||||
-i 192.168.1.$i -M MONITOR -mc 36 -b 5G
|
||||
done
|
||||
|
||||
Data Collection:
|
||||
# Capture logs from all devices
|
||||
for i in {0..17}; do
|
||||
cat /dev/ttyUSB$i > logs/device_$((81+i)).log &
|
||||
done
|
||||
|
||||
# Merge by GPS timestamp
|
||||
cat logs/*.log | sort -t'(' -k2 -n > merged.log
|
||||
|
||||
SCENARIO 2: CHANNEL SURVEY (8 channels)
|
||||
----------------------------------------
|
||||
|
||||
Goal: Monitor WiFi activity across multiple 5GHz channels
|
||||
|
||||
Setup:
|
||||
• 8 devices in MONITOR mode on different channels
|
||||
• Comprehensive 5GHz band coverage
|
||||
|
||||
Configuration:
|
||||
channels=(36 40 44 48 149 153 157 161)
|
||||
for i in "${!channels[@]}"; do
|
||||
python3 config_device.py -p /dev/ttyUSB$i \\
|
||||
-i 192.168.1.$((90+i)) -M MONITOR -mc ${channels[$i]} -b 5G
|
||||
done
|
||||
|
||||
SCENARIO 3: 2.4GHz vs 5GHz COMPARISON
|
||||
--------------------------------------
|
||||
|
||||
Goal: Compare WiFi behavior on 2.4GHz vs 5GHz
|
||||
|
||||
Setup:
|
||||
• 4 devices on 2.4GHz channels 1, 6, 11 (MONITOR)
|
||||
• 4 devices on 5GHz channels 36, 149 (MONITOR)
|
||||
• 2 STA devices (1 on each band)
|
||||
|
||||
Configuration:
|
||||
# 2.4GHz monitors
|
||||
for ch in 1 6 11; do
|
||||
python3 config_device.py -p /dev/ttyUSB$i \\
|
||||
-i 192.168.1.$((90+i)) -M MONITOR -mc $ch -b 2.4G
|
||||
((i++))
|
||||
done
|
||||
|
||||
# 5GHz monitors
|
||||
for ch in 36 149; do
|
||||
python3 config_device.py -p /dev/ttyUSB$i \\
|
||||
-i 192.168.1.$((90+i)) -M MONITOR -mc $ch -b 5G
|
||||
((i++))
|
||||
done
|
||||
|
||||
SCENARIO 4: POWER SAVE IMPACT TESTING
|
||||
--------------------------------------
|
||||
|
||||
Goal: Measure impact of power save modes on CSI quality
|
||||
|
||||
Setup:
|
||||
• 3 devices with different power save modes
|
||||
• All in STA mode for CSI capture
|
||||
|
||||
Configuration:
|
||||
python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -ps NONE
|
||||
python3 config_device.py -p /dev/ttyUSB1 -i 192.168.1.82 -ps MIN
|
||||
python3 config_device.py -p /dev/ttyUSB2 -i 192.168.1.83 -ps MAX
|
||||
|
||||
Compare CSI data quality across the three modes.
|
||||
|
||||
================================================================================
|
||||
APPENDIX A: CONFIGURATION MESSAGE FORMAT
|
||||
================================================================================
|
||||
|
||||
The script sends this message to the device over serial:
|
||||
|
||||
CFG
|
||||
SSID:ClubHouse2G
|
||||
PASS:ez2remember
|
||||
IP:192.168.1.90
|
||||
MASK:255.255.255.0
|
||||
GW:192.168.1.1
|
||||
DHCP:0
|
||||
BAND:5G
|
||||
BW:HT20
|
||||
POWERSAVE:NONE
|
||||
MODE:MONITOR
|
||||
MON_CH:36
|
||||
END
|
||||
|
||||
Device responds with:
|
||||
OK
|
||||
|
||||
Then device logs:
|
||||
I (1234) wifi_cfg: Config saved to NVS: SSID=ClubHouse2G Mode=MONITOR MonCh=36...
|
||||
I (1234) wifi_cfg: Applying Wi-Fi config: ...
|
||||
|
||||
================================================================================
|
||||
APPENDIX B: LED STATUS INDICATORS
|
||||
================================================================================
|
||||
|
||||
| Color | Pattern | Meaning |
|
||||
|--------|----------|------------------------------------------|
|
||||
| Yellow | Solid | No WiFi config in NVS |
|
||||
| Blue | Blinking | Connecting to WiFi |
|
||||
| Green | Solid | Connected in STA mode |
|
||||
| Blue | Solid | MONITOR mode active |
|
||||
| Red | Blinking | Connection failed / Error |
|
||||
|
||||
================================================================================
|
||||
APPENDIX C: QUICK REFERENCE CARD
|
||||
================================================================================
|
||||
|
||||
Most Common Configurations:
|
||||
|
||||
STA mode (default everything):
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81
|
||||
|
||||
STA mode on 5GHz:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -b 5G
|
||||
|
||||
MONITOR mode channel 36:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.90 \\
|
||||
-M MONITOR -mc 36
|
||||
|
||||
MONITOR mode 2.4GHz channel 6:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.91 \\
|
||||
-M MONITOR -mc 6 -b 2.4G
|
||||
|
||||
Custom SSID/password:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 \\
|
||||
-s "MyWiFi" -P "MyPassword"
|
||||
|
||||
Verbose debugging:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -v
|
||||
|
||||
No reboot:
|
||||
$ python3 config_device.py -p /dev/ttyUSB0 -i 192.168.1.81 -r
|
||||
|
||||
================================================================================
|
||||
END OF MANUAL
|
||||
================================================================================
|
||||
|
||||
For more information and updates:
|
||||
• See NVS_MODE_CONFIGURATION_GUIDE.md
|
||||
• See QUICK_DEPLOYMENT_REFERENCE.md
|
||||
• See WIFI_CFG_CHANGES_DETAILED.md
|
||||
|
||||
Version: 2.0
|
||||
Last Updated: December 2025
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
# Console Commands Quick Reference
|
||||
|
||||
## 🎮 All Available Commands
|
||||
|
||||
```bash
|
||||
mode_monitor [channel/bandwidth] # Monitor mode with bandwidth control
|
||||
mode_sta [band] # STA mode with band selection
|
||||
mode_status # Show current configuration
|
||||
csi_dump # Dump CSI data (STA mode only)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 Monitor Mode Examples
|
||||
|
||||
### 2.4GHz Band
|
||||
```bash
|
||||
mode_monitor 6/20 # Channel 6, 20MHz (narrow, less interference)
|
||||
mode_monitor 6/40 # Channel 6, 40MHz (wide, more speed)
|
||||
mode_monitor 11/20 # Channel 11, 20MHz
|
||||
mode_monitor 1 # Channel 1, default 20MHz
|
||||
```
|
||||
|
||||
### 5GHz Band
|
||||
```bash
|
||||
mode_monitor 36/20 # Channel 36, 20MHz (max range)
|
||||
mode_monitor 36/40 # Channel 36, 40MHz (balanced)
|
||||
mode_monitor 36/80 # Channel 36, 80MHz (max speed, WiFi 6)
|
||||
mode_monitor 149/80 # Channel 149, 80MHz
|
||||
mode_monitor 161 # Channel 161, default 40MHz
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🌐 STA Mode Examples
|
||||
|
||||
### Auto Band Selection (Default)
|
||||
```bash
|
||||
mode_sta # Auto select 2.4GHz or 5GHz
|
||||
mode_sta auto # Same as above
|
||||
```
|
||||
|
||||
### Force 2.4GHz
|
||||
```bash
|
||||
mode_sta 2.4 # Connect on 2.4GHz only
|
||||
mode_sta 2 # Same as above
|
||||
```
|
||||
|
||||
### Force 5GHz
|
||||
```bash
|
||||
mode_sta 5 # Connect on 5GHz only
|
||||
mode_sta 5.0 # Same as above
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Status Check
|
||||
|
||||
```bash
|
||||
esp32> mode_status
|
||||
|
||||
=== WiFi Mode Status ===
|
||||
Current mode: MONITOR
|
||||
LED state: Blue solid (Monitoring)
|
||||
Monitor channel: 36 (5GHz)
|
||||
Monitor bandwidth: 80MHz
|
||||
Monitor enabled: Yes
|
||||
Frames captured: 15234
|
||||
GPS synced: Yes (+)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Common Workflows
|
||||
|
||||
### Workflow 1: WiFi 6 Testing on 5GHz
|
||||
```bash
|
||||
# 1. Connect on 5GHz
|
||||
esp32> mode_sta 5
|
||||
|
||||
# 2. Wait for connection (green LED)
|
||||
|
||||
# 3. Check AP channel
|
||||
esp32> mode_status
|
||||
Connected band: 5GHz (channel 36)
|
||||
Bandwidth: 80MHz
|
||||
|
||||
# 4. Switch to monitor with same config
|
||||
esp32> mode_monitor 36/80
|
||||
|
||||
# 5. Monitor collapse events with GPS timestamps
|
||||
[Monitoring...]
|
||||
```
|
||||
|
||||
### Workflow 2: 2.4GHz Congestion Analysis
|
||||
```bash
|
||||
# Test narrow bandwidth
|
||||
esp32> mode_monitor 6/20
|
||||
[collect for 30 min...]
|
||||
|
||||
# Test wide bandwidth
|
||||
esp32> mode_monitor 6/40
|
||||
[collect for 30 min...]
|
||||
|
||||
# Compare collapse rates
|
||||
```
|
||||
|
||||
### Workflow 3: Force 5GHz for Performance
|
||||
```bash
|
||||
# Force 5GHz connection
|
||||
esp32> mode_sta 5
|
||||
|
||||
# Verify connected on 5GHz
|
||||
esp32> mode_status
|
||||
|
||||
# Collect CSI data on 5GHz
|
||||
[wait 20 seconds for auto dump]
|
||||
|
||||
# Or dump manually
|
||||
esp32> csi_dump
|
||||
```
|
||||
|
||||
### Workflow 4: Multi-Bandwidth Testing
|
||||
```bash
|
||||
# Test same channel at different bandwidths
|
||||
esp32> mode_monitor 149/20
|
||||
[5 minutes...]
|
||||
|
||||
esp32> mode_monitor 149/40
|
||||
[5 minutes...]
|
||||
|
||||
esp32> mode_monitor 149/80
|
||||
[5 minutes...]
|
||||
|
||||
# Analyze which has fewer collapses
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 LED Status
|
||||
|
||||
| Color | State | Mode |
|
||||
|-------|-------|------|
|
||||
| Yellow solid | No WiFi config | - |
|
||||
| Blue blink | Connecting to AP | STA |
|
||||
| Green solid | Connected, CSI+iperf running | STA |
|
||||
| Blue solid | Monitor mode active | Monitor |
|
||||
| Red blink | Connection failed | - |
|
||||
|
||||
---
|
||||
|
||||
## 📝 GPS Timestamp Format
|
||||
|
||||
```
|
||||
Log messages:
|
||||
I (*1.234) MAIN: Waiting... (* = not synced)
|
||||
I (+1733424645.234) MAIN: Ready! (+ = GPS synced)
|
||||
|
||||
CSV collapse events:
|
||||
COLLAPSE,MonoMS,GpsMS,Synced,NAV,RSSI,Retry
|
||||
COLLAPSE,5234567,1733424645234,1,5234.50,-65,1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Configuration Matrix
|
||||
|
||||
### Valid Bandwidth Combinations
|
||||
|
||||
| Band | Channel Examples | 20MHz | 40MHz | 80MHz |
|
||||
|------|-----------------|-------|-------|-------|
|
||||
| 2.4GHz | 1, 6, 11 | ✅ | ✅ | ❌ |
|
||||
| 5GHz | 36, 149, 161 | ✅ | ✅ | ✅ |
|
||||
|
||||
### Valid Band Preferences
|
||||
|
||||
| Mode | 2.4GHz | 5GHz | Auto |
|
||||
|------|--------|------|------|
|
||||
| STA | ✅ | ✅ | ✅ (default) |
|
||||
| Monitor | ✅ | ✅ | N/A |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment Examples
|
||||
|
||||
### 32-Device Setup: Multi-Bandwidth Testing
|
||||
```bash
|
||||
# Devices 1-8: 2.4GHz 20MHz
|
||||
mode_monitor 6/20
|
||||
|
||||
# Devices 9-16: 2.4GHz 40MHz
|
||||
mode_monitor 6/40
|
||||
|
||||
# Devices 17-24: 5GHz 40MHz
|
||||
mode_monitor 149/40
|
||||
|
||||
# Devices 25-32: 5GHz 80MHz
|
||||
mode_monitor 149/80
|
||||
```
|
||||
|
||||
### Production Deployment: Best Performance
|
||||
```bash
|
||||
# All devices: Force 5GHz connection
|
||||
mode_sta 5
|
||||
|
||||
# After connection, monitor on AP's channel
|
||||
mode_monitor 149/80
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Performance Tips
|
||||
|
||||
### For Maximum Range
|
||||
```bash
|
||||
mode_sta 2.4 # Connect on 2.4GHz
|
||||
mode_monitor 6/20 # Monitor with 20MHz
|
||||
```
|
||||
|
||||
### For Maximum Speed
|
||||
```bash
|
||||
mode_sta 5 # Connect on 5GHz
|
||||
mode_monitor 149/80 # Monitor with 80MHz
|
||||
```
|
||||
|
||||
### For Dense Environments
|
||||
```bash
|
||||
mode_sta 5 # Prefer 5GHz (less congestion)
|
||||
mode_monitor 149/20 # Narrow bandwidth (less interference)
|
||||
```
|
||||
|
||||
### For WiFi 6 Testing
|
||||
```bash
|
||||
mode_sta auto # Auto select
|
||||
mode_monitor 36/80 # 80MHz WiFi 6
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Feature Summary
|
||||
|
||||
**ESP32-C5 Capabilities:**
|
||||
- ✅ WiFi 6 (802.11ax) on 2.4GHz and 5GHz
|
||||
- ✅ Bandwidths: 20MHz, 40MHz (both bands); 80MHz (5GHz only)
|
||||
- ✅ Band selection: Auto, 2.4GHz only, 5GHz only
|
||||
- ✅ Runtime mode switching (no reflashing needed)
|
||||
- ✅ GPS-timestamped collapse detection
|
||||
- ✅ CSI capture + iperf server in STA mode
|
||||
- ✅ Visual LED status indicators
|
||||
|
||||
**Console Commands:**
|
||||
- 4 commands total
|
||||
- Bandwidth control in monitor mode
|
||||
- Band preference in STA mode
|
||||
- Real-time status checking
|
||||
- One firmware for all configurations!
|
||||
|
|
@ -1,10 +1,17 @@
|
|||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES
|
||||
csi_log
|
||||
gps_sync
|
||||
REQUIRES
|
||||
nvs_flash
|
||||
esp_wifi
|
||||
esp_netif
|
||||
esp_event
|
||||
lwip
|
||||
console # Console handles UART automatically
|
||||
iperf
|
||||
wifi_cfg
|
||||
csi_log
|
||||
wifi_monitor
|
||||
gps_sync
|
||||
led_strip
|
||||
)
|
||||
|
|
|
|||
674
main/main.c
674
main/main.c
|
|
@ -10,6 +10,8 @@
|
|||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_console.h"
|
||||
#include "linenoise/linenoise.h"
|
||||
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
|
|
@ -22,7 +24,7 @@
|
|||
#include "wifi_cfg.h"
|
||||
#include "csi_log.h"
|
||||
#include "wifi_monitor.h"
|
||||
#include "gps_sync.h" // <--- ADDED: GPS Support
|
||||
#include "gps_sync.h"
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
|
|
@ -30,10 +32,22 @@ static const char *TAG = "MAIN";
|
|||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
#define RGB_LED_GPIO 27
|
||||
#else
|
||||
// Fallback for other chips if you switch boards
|
||||
#define RGB_LED_GPIO 8
|
||||
#endif
|
||||
|
||||
// --- WiFi Operation Mode ---
|
||||
typedef enum {
|
||||
WIFI_MODE_STA_CSI, // STA mode: Connected to AP, CSI + iperf (DEFAULT)
|
||||
WIFI_MODE_MONITOR // Monitor mode: Promiscuous, collapse detection
|
||||
} wifi_operation_mode_t;
|
||||
|
||||
// Note: wifi_band_mode_t is already defined in ESP-IDF's esp_wifi_types_generic.h
|
||||
// Values: WIFI_BAND_MODE_2G_ONLY, WIFI_BAND_MODE_5G_ONLY, WIFI_BAND_MODE_AUTO
|
||||
|
||||
static wifi_operation_mode_t current_wifi_mode = WIFI_MODE_STA_CSI;
|
||||
static wifi_band_mode_t preferred_band = WIFI_BAND_MODE_AUTO;
|
||||
static uint8_t monitor_channel = 6; // Default monitor channel
|
||||
|
||||
// --- LED State Machine ---
|
||||
static led_strip_handle_t led_strip;
|
||||
static bool wifi_connected = false;
|
||||
|
|
@ -49,6 +63,9 @@ typedef enum {
|
|||
|
||||
static led_state_t current_led_state = LED_STATE_NO_CONFIG;
|
||||
|
||||
// --- Forward Declarations ---
|
||||
static void auto_monitor_task(void *arg);
|
||||
|
||||
static void rgb_led_init(void) {
|
||||
ESP_LOGI(TAG, "Initializing RGB LED on GPIO %d", RGB_LED_GPIO);
|
||||
led_strip_config_t strip_config = {
|
||||
|
|
@ -105,7 +122,6 @@ static void led_task(void *arg) {
|
|||
}
|
||||
|
||||
// --- GPS Logging Helper ---
|
||||
// Replaces the old plain text log with your CSV + GPS Timestamp format
|
||||
void log_collapse_event(float nav_duration_us, int rssi, int retry) {
|
||||
gps_timestamp_t ts = gps_get_timestamp();
|
||||
|
||||
|
|
@ -137,33 +153,48 @@ static void wifi_enable_csi_once(void) {
|
|||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
wifi_csi_config_t csi_cfg;
|
||||
memset(&csi_cfg, 0, sizeof(csi_cfg));
|
||||
csi_cfg.enable = true; // C5 specific simple config
|
||||
csi_cfg.enable = true;
|
||||
|
||||
ESP_LOGI("CSI", "Configuring CSI...");
|
||||
if (esp_wifi_set_csi_config(&csi_cfg) != ESP_OK) return;
|
||||
if (esp_wifi_set_csi_rx_cb(csi_cb, NULL) != ESP_OK) return;
|
||||
if (esp_wifi_set_csi(true) != ESP_OK) return;
|
||||
if (esp_wifi_set_csi_config(&csi_cfg) != ESP_OK) {
|
||||
ESP_LOGE("CSI", "Failed to set CSI config");
|
||||
return;
|
||||
}
|
||||
if (esp_wifi_set_csi_rx_cb(csi_cb, NULL) != ESP_OK) {
|
||||
ESP_LOGE("CSI", "Failed to set CSI callback");
|
||||
return;
|
||||
}
|
||||
if (esp_wifi_set_csi(true) != ESP_OK) {
|
||||
ESP_LOGE("CSI", "Failed to enable CSI");
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI("CSI", "CSI enabled!");
|
||||
s_csi_enabled = true;
|
||||
}
|
||||
|
||||
static void csi_dump_task(void *arg) {
|
||||
vTaskDelay(pdMS_TO_TICKS(20000)); // Dump after 20 seconds
|
||||
csi_log_dump_over_uart();
|
||||
vTaskDelete(NULL);
|
||||
static void wifi_disable_csi(void) {
|
||||
if (!s_csi_enabled) return;
|
||||
|
||||
ESP_LOGI("CSI", "Disabling CSI...");
|
||||
esp_wifi_set_csi(false);
|
||||
s_csi_enabled = false;
|
||||
ESP_LOGI("CSI", "CSI disabled");
|
||||
}
|
||||
|
||||
static void csi_init_task(void *arg) {
|
||||
wifi_enable_csi_once();
|
||||
static void csi_dump_task(void *arg) {
|
||||
vTaskDelay(pdMS_TO_TICKS(20000)); // Dump after 20 seconds
|
||||
ESP_LOGI("CSI", "Dumping CSI data...");
|
||||
csi_log_dump_over_uart();
|
||||
ESP_LOGI("CSI", "CSI dump complete");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// --- WiFi Monitor Mode Support -------------------------------------
|
||||
static bool s_monitor_enabled = false;
|
||||
static uint32_t s_monitor_frame_count = 0;
|
||||
static TaskHandle_t s_monitor_stats_task_handle = NULL;
|
||||
|
||||
// This is the core analysis function
|
||||
static void monitor_frame_callback(const wifi_frame_info_t *frame,
|
||||
const uint8_t *payload,
|
||||
uint16_t len) {
|
||||
|
|
@ -171,13 +202,12 @@ static void monitor_frame_callback(const wifi_frame_info_t *frame,
|
|||
|
||||
// 1. Check for Collapse (High NAV + Retry)
|
||||
if (frame->retry && frame->duration_id > 5000) {
|
||||
// USE GPS LOGGING HERE
|
||||
log_collapse_event((float)frame->duration_id, frame->rssi, frame->retry);
|
||||
}
|
||||
|
||||
// 2. Also warn on extremely high NAV (blocking the channel)
|
||||
// 2. Warn on extremely high NAV
|
||||
if (frame->duration_id > 30000) {
|
||||
ESP_LOGW("MONITOR", "⚠ VERY HIGH NAV: %u us", frame->duration_id);
|
||||
ESP_LOGW("MONITOR", "⚠️ VERY HIGH NAV: %u us", frame->duration_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -190,35 +220,458 @@ static void monitor_stats_task(void *arg) {
|
|||
stats.total_frames, stats.retry_rate, stats.avg_nav);
|
||||
|
||||
if (wifi_monitor_is_collapsed()) {
|
||||
ESP_LOGW("MONITOR", "⚠⚠⚠ WiFi COLLAPSE DETECTED! ⚠⚠⚠");
|
||||
ESP_LOGW("MONITOR", "⚠️ ⚠️ ⚠️ WiFi COLLAPSE DETECTED! ⚠️ ⚠️ ⚠️ ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_enable_monitor_mode(uint8_t channel) {
|
||||
if (s_monitor_enabled) return;
|
||||
// --- Mode Switching Functions --------------------------------------
|
||||
|
||||
ESP_LOGI("MONITOR", "Starting WiFi monitor mode on channel %d", channel);
|
||||
if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) return;
|
||||
if (wifi_monitor_start() != ESP_OK) return;
|
||||
esp_err_t switch_to_monitor_mode(uint8_t channel, wifi_bandwidth_t bandwidth) {
|
||||
if (current_wifi_mode == WIFI_MODE_MONITOR) {
|
||||
ESP_LOGW(TAG, "Already in monitor mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// CRITICAL: ESP-IDF monitor/promiscuous mode is typically restricted to 20MHz
|
||||
// even though the hardware supports 40MHz. Force 20MHz for monitor mode.
|
||||
if (bandwidth != WIFI_BW_HT20) {
|
||||
ESP_LOGW(TAG, "Monitor mode typically restricted to 20MHz capture width");
|
||||
ESP_LOGW(TAG, "Forcing bandwidth to 20MHz (driver limitation)");
|
||||
bandwidth = WIFI_BW_HT20;
|
||||
}
|
||||
|
||||
// Detect band for informational logging
|
||||
const char* band_str = "2.4GHz";
|
||||
if (channel >= 36 && channel <= 165) {
|
||||
band_str = "5GHz";
|
||||
}
|
||||
|
||||
const char* bw_str = "20MHz";
|
||||
// Note: Monitor mode typically limited to 20MHz by ESP-IDF drivers
|
||||
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Switching to MONITOR MODE");
|
||||
ESP_LOGI(TAG, " Channel: %d (%s)", channel, band_str);
|
||||
ESP_LOGI(TAG, " Bandwidth: %s (monitor mode limitation)", bw_str);
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
// 1. Stop iperf if running
|
||||
ESP_LOGI(TAG, "Stopping iperf...");
|
||||
iperf_stop();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 2. Disable CSI
|
||||
wifi_disable_csi();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 3. Disconnect from AP
|
||||
ESP_LOGI(TAG, "Disconnecting from AP...");
|
||||
esp_wifi_disconnect();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
// 4. Stop WiFi
|
||||
ESP_LOGI(TAG, "Stopping WiFi...");
|
||||
esp_wifi_stop();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 5. Set to NULL mode
|
||||
ESP_LOGI(TAG, "Setting WiFi mode to NULL...");
|
||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 6. Configure bandwidth before starting monitor mode
|
||||
ESP_LOGI(TAG, "Configuring bandwidth to %s...", bw_str);
|
||||
wifi_config_t wifi_config = {};
|
||||
esp_wifi_get_config(WIFI_IF_STA, &wifi_config);
|
||||
|
||||
// Set bandwidth in promiscuous mode config
|
||||
// Note: Bandwidth is set via wifi monitor init
|
||||
|
||||
// 7. Start monitor mode
|
||||
ESP_LOGI(TAG, "Starting monitor mode...");
|
||||
if (wifi_monitor_init(channel, monitor_frame_callback) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to init monitor mode");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Set bandwidth after init
|
||||
esp_wifi_set_bandwidth(WIFI_IF_STA, bandwidth);
|
||||
|
||||
if (wifi_monitor_start() != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to start monitor mode");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
s_monitor_enabled = true;
|
||||
current_wifi_mode = WIFI_MODE_MONITOR;
|
||||
current_led_state = LED_STATE_MONITORING;
|
||||
monitor_channel = channel;
|
||||
|
||||
ESP_LOGI("MONITOR", "WiFi monitor started");
|
||||
xTaskCreate(monitor_stats_task, "monitor_stats", 4096, NULL, 5, NULL);
|
||||
// 8. Start stats task
|
||||
if (s_monitor_stats_task_handle == NULL) {
|
||||
xTaskCreate(monitor_stats_task, "monitor_stats", 4096, NULL, 5, &s_monitor_stats_task_handle);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "✓ Monitor mode active");
|
||||
ESP_LOGI(TAG, " - Channel: %d (%s)", channel, band_str);
|
||||
ESP_LOGI(TAG, " - Bandwidth: %s", bw_str);
|
||||
ESP_LOGI(TAG, " - Logging GPS-timestamped collapse events");
|
||||
ESP_LOGI(TAG, " - LED: Blue solid");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void monitor_init_task(void *arg) {
|
||||
wifi_ap_record_t ap_info;
|
||||
// Try to sniff the same channel our AP is using
|
||||
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
|
||||
wifi_enable_monitor_mode(ap_info.primary);
|
||||
} else {
|
||||
wifi_enable_monitor_mode(6); // Default fallback
|
||||
esp_err_t switch_to_sta_mode(wifi_band_mode_t band_mode) {
|
||||
if (current_wifi_mode == WIFI_MODE_STA_CSI) {
|
||||
ESP_LOGW(TAG, "Already in STA mode");
|
||||
return ESP_OK;
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
|
||||
const char* band_str = "Auto (2.4GHz or 5GHz)";
|
||||
if (band_mode == WIFI_BAND_MODE_2G_ONLY) {
|
||||
band_str = "2.4GHz only";
|
||||
} else if (band_mode == WIFI_BAND_MODE_5G_ONLY) {
|
||||
band_str = "5GHz only";
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Switching to STA MODE (CSI + iperf)");
|
||||
ESP_LOGI(TAG, " Band preference: %s", band_str);
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
preferred_band = band_mode;
|
||||
|
||||
// 1. Stop monitor stats task
|
||||
if (s_monitor_stats_task_handle != NULL) {
|
||||
vTaskDelete(s_monitor_stats_task_handle);
|
||||
s_monitor_stats_task_handle = NULL;
|
||||
}
|
||||
|
||||
// 2. Stop monitor mode
|
||||
if (s_monitor_enabled) {
|
||||
ESP_LOGI(TAG, "Stopping monitor mode...");
|
||||
wifi_monitor_stop();
|
||||
s_monitor_enabled = false;
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
|
||||
// 3. Set mode back to STA
|
||||
ESP_LOGI(TAG, "Setting WiFi mode to STA...");
|
||||
esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 4. Configure band preference
|
||||
wifi_config_t wifi_config;
|
||||
esp_wifi_get_config(WIFI_IF_STA, &wifi_config);
|
||||
|
||||
if (band_mode == WIFI_BAND_MODE_2G_ONLY) {
|
||||
wifi_config.sta.channel = 0; // Scan all channels, but prefer 2.4GHz
|
||||
wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||
// Note: ESP-IDF doesn't have direct band filtering, but we can set channel to force band
|
||||
ESP_LOGI(TAG, "Configured for 2.4GHz band");
|
||||
} else if (band_mode == WIFI_BAND_MODE_5G_ONLY) {
|
||||
wifi_config.sta.channel = 0; // Scan all channels
|
||||
wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||
// The AP should be on 5GHz; connection will work if AP supports 5GHz
|
||||
ESP_LOGI(TAG, "Configured for 5GHz band preference");
|
||||
} else {
|
||||
// Auto mode - let ESP-IDF choose best band
|
||||
wifi_config.sta.channel = 0;
|
||||
wifi_config.sta.scan_method = WIFI_ALL_CHANNEL_SCAN;
|
||||
ESP_LOGI(TAG, "Configured for auto band selection");
|
||||
}
|
||||
|
||||
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
|
||||
|
||||
// 5. Start WiFi
|
||||
ESP_LOGI(TAG, "Starting WiFi...");
|
||||
esp_wifi_start();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
|
||||
// 6. Reconnect to AP
|
||||
ESP_LOGI(TAG, "Connecting to AP...");
|
||||
esp_wifi_connect();
|
||||
|
||||
current_wifi_mode = WIFI_MODE_STA_CSI;
|
||||
current_led_state = LED_STATE_WAITING;
|
||||
wifi_connected = false;
|
||||
|
||||
ESP_LOGI(TAG, "✓ Reconnecting to AP...");
|
||||
ESP_LOGI(TAG, " - Band: %s", band_str);
|
||||
ESP_LOGI(TAG, " - Waiting for IP address");
|
||||
ESP_LOGI(TAG, " - CSI and iperf will start after connection");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
// Note: CSI and iperf will be started by event handler when IP is obtained
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// --- Console Commands ----------------------------------------------
|
||||
|
||||
static int cmd_mode_monitor(int argc, char **argv) {
|
||||
int channel = monitor_channel; // Use last channel or default
|
||||
wifi_bandwidth_t bandwidth = WIFI_BW_HT20; // Default to 20MHz
|
||||
|
||||
if (argc > 1) {
|
||||
// Parse channel/bandwidth format: "6/20" or "36/40"
|
||||
char *slash = strchr(argv[1], '/');
|
||||
if (slash != NULL) {
|
||||
*slash = '\0'; // Split string at '/'
|
||||
channel = atoi(argv[1]);
|
||||
int bw = atoi(slash + 1);
|
||||
|
||||
// Convert bandwidth to enum - ESP32-C5 only supports 20/40MHz
|
||||
switch(bw) {
|
||||
case 20:
|
||||
bandwidth = WIFI_BW_HT20;
|
||||
break;
|
||||
case 40:
|
||||
bandwidth = WIFI_BW_HT40;
|
||||
printf("WARNING: Monitor mode typically restricted to 20MHz by ESP-IDF drivers\n");
|
||||
printf(" 40MHz requested but will be forced to 20MHz\n");
|
||||
break;
|
||||
default:
|
||||
printf("Error: Invalid bandwidth %d\n", bw);
|
||||
printf("ESP32-C5 hardware: 20MHz and 40MHz\n");
|
||||
printf("Monitor mode driver: 20MHz only (typical limitation)\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
channel = atoi(argv[1]);
|
||||
// Monitor mode: always default to 20MHz (driver limitation)
|
||||
bandwidth = WIFI_BW_HT20;
|
||||
}
|
||||
|
||||
// Validate channel based on band
|
||||
// ESP32-C5 supports WiFi 6 on 2.4GHz and 5GHz only (NO 6GHz support)
|
||||
bool valid = false;
|
||||
const char* band = "Unknown";
|
||||
|
||||
// 2.4GHz: channels 1-14
|
||||
if (channel >= 1 && channel <= 14) {
|
||||
valid = true;
|
||||
band = "2.4GHz";
|
||||
|
||||
// Validate bandwidth for 2.4GHz
|
||||
if (bandwidth != WIFI_BW_HT20 && bandwidth != WIFI_BW_HT40) {
|
||||
printf("Error: 2.4GHz only supports 20MHz and 40MHz bandwidth\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// 5GHz: specific valid channels only
|
||||
else if (channel >= 36 && channel <= 165) {
|
||||
// UNII-1 and UNII-2: 36-64 (every 4 channels)
|
||||
if ((channel >= 36 && channel <= 64 && (channel % 4 == 0)) ||
|
||||
// UNII-2 Extended: 100-144 (every 4 channels)
|
||||
(channel >= 100 && channel <= 144 && (channel % 4 == 0)) ||
|
||||
// UNII-3: 149,153,157,161,165
|
||||
(channel >= 149 && channel <= 165 && (channel % 4 == 1))) {
|
||||
valid = true;
|
||||
band = "5GHz";
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
printf("Error: Invalid channel %d\n", channel);
|
||||
printf("\nESP32-C5 supports WiFi 6 on 2.4GHz and 5GHz bands only:\n");
|
||||
printf(" 2.4GHz: 1-14 (20MHz or 40MHz)\n");
|
||||
printf(" 5GHz: 36,40,44,48,52,56,60,64,100,104,...,161,165 (20/40/80MHz)\n");
|
||||
printf("\nExamples:\n");
|
||||
printf(" mode_monitor 6/20 # 2.4GHz channel 6, 20MHz\n");
|
||||
printf(" mode_monitor 6/40 # 2.4GHz channel 6, 40MHz\n");
|
||||
printf(" mode_monitor 36/20 # 5GHz channel 36, 20MHz\n");
|
||||
printf(" mode_monitor 36/40 # 5GHz channel 36, 40MHz\n");
|
||||
printf(" mode_monitor 36/80 # 5GHz channel 36, 80MHz\n");
|
||||
printf(" mode_monitor 149 # 5GHz channel 149, default 40MHz\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char* bw_str = (bandwidth == WIFI_BW_HT40) ? "40MHz" : "20MHz";
|
||||
|
||||
printf("Monitoring channel %d (%s band, %s)\n", channel, band, bw_str);
|
||||
}
|
||||
|
||||
esp_err_t err = switch_to_monitor_mode(channel, bandwidth);
|
||||
if (err != ESP_OK) {
|
||||
printf("Failed to switch to monitor mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_mode_sta(int argc, char **argv) {
|
||||
wifi_band_mode_t band_mode = WIFI_BAND_MODE_AUTO; // Default to auto
|
||||
|
||||
if (argc > 1) {
|
||||
if (strcmp(argv[1], "2.4") == 0 || strcmp(argv[1], "2") == 0) {
|
||||
band_mode = WIFI_BAND_MODE_2G_ONLY;
|
||||
printf("Forcing 2.4GHz band\n");
|
||||
} else if (strcmp(argv[1], "5") == 0 || strcmp(argv[1], "5.0") == 0) {
|
||||
band_mode = WIFI_BAND_MODE_5G_ONLY;
|
||||
printf("Forcing 5GHz band\n");
|
||||
} else if (strcmp(argv[1], "auto") == 0) {
|
||||
band_mode = WIFI_BAND_MODE_AUTO;
|
||||
printf("Auto band selection (2.4GHz or 5GHz)\n");
|
||||
} else {
|
||||
printf("Error: Invalid band '%s'\n", argv[1]);
|
||||
printf("Valid options: 2.4, 5, auto\n");
|
||||
printf("Examples:\n");
|
||||
printf(" mode_sta 2.4 # Connect on 2.4GHz only\n");
|
||||
printf(" mode_sta 5 # Connect on 5GHz only\n");
|
||||
printf(" mode_sta auto # Auto select (default)\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = switch_to_sta_mode(band_mode);
|
||||
if (err != ESP_OK) {
|
||||
printf("Failed to switch to STA mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Switching to STA mode (reconnecting to AP...)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_mode_status(int argc, char **argv) {
|
||||
printf("\n=== WiFi Mode Status ===\n");
|
||||
printf("Current mode: %s\n",
|
||||
current_wifi_mode == WIFI_MODE_STA_CSI ? "STA (CSI + iperf)" : "MONITOR");
|
||||
printf("LED state: ");
|
||||
switch(current_led_state) {
|
||||
case LED_STATE_NO_CONFIG: printf("Yellow (No config)\n"); break;
|
||||
case LED_STATE_WAITING: printf("Blue blink (Connecting)\n"); break;
|
||||
case LED_STATE_CONNECTED: printf("Green (Connected)\n"); break;
|
||||
case LED_STATE_MONITORING: printf("Blue solid (Monitoring)\n"); break;
|
||||
case LED_STATE_FAILED: printf("Red blink (Failed)\n"); break;
|
||||
}
|
||||
|
||||
if (current_wifi_mode == WIFI_MODE_STA_CSI) {
|
||||
printf("WiFi connected: %s\n", wifi_connected ? "Yes" : "No");
|
||||
|
||||
// Show band preference
|
||||
const char* band_pref = "Auto";
|
||||
if (preferred_band == WIFI_BAND_MODE_2G_ONLY) band_pref = "2.4GHz only";
|
||||
else if (preferred_band == WIFI_BAND_MODE_5G_ONLY) band_pref = "5GHz only";
|
||||
printf("Band preference: %s\n", band_pref);
|
||||
|
||||
// Show actual connected band/channel if connected
|
||||
if (wifi_connected) {
|
||||
wifi_ap_record_t ap_info;
|
||||
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
|
||||
const char* band = (ap_info.primary >= 36) ? "5GHz" : "2.4GHz";
|
||||
printf("Connected band: %s (channel %d)\n", band, ap_info.primary);
|
||||
|
||||
// Show bandwidth
|
||||
wifi_bandwidth_t bw;
|
||||
esp_wifi_get_bandwidth(WIFI_IF_STA, &bw);
|
||||
const char* bw_str = "Unknown";
|
||||
if (bw == WIFI_BW_HT20) bw_str = "20MHz";
|
||||
else if (bw == WIFI_BW_HT40) bw_str = "40MHz";
|
||||
printf("Bandwidth: %s\n", bw_str);
|
||||
}
|
||||
}
|
||||
|
||||
printf("CSI enabled: %s\n", s_csi_enabled ? "Yes" : "No");
|
||||
if (s_csi_enabled) {
|
||||
printf("CSI packets captured: %lu\n", (unsigned long)s_csi_packet_count);
|
||||
}
|
||||
} else {
|
||||
const char* band = (monitor_channel >= 36) ? "5GHz" : "2.4GHz";
|
||||
printf("Monitor channel: %d (%s)\n", monitor_channel, band);
|
||||
|
||||
// Show monitor bandwidth
|
||||
wifi_bandwidth_t bw;
|
||||
esp_wifi_get_bandwidth(WIFI_IF_STA, &bw);
|
||||
const char* bw_str = "Unknown";
|
||||
if (bw == WIFI_BW_HT20) bw_str = "20MHz";
|
||||
else if (bw == WIFI_BW_HT40) bw_str = "40MHz";
|
||||
printf("Monitor bandwidth: %s\n", bw_str);
|
||||
|
||||
printf("Monitor enabled: %s\n", s_monitor_enabled ? "Yes" : "No");
|
||||
printf("Frames captured: %lu\n", (unsigned long)s_monitor_frame_count);
|
||||
}
|
||||
|
||||
printf("GPS synced: %s\n", gps_is_synced() ? "Yes (+)" : "No (*)");
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_csi_dump(int argc, char **argv) {
|
||||
if (current_wifi_mode != WIFI_MODE_STA_CSI) {
|
||||
printf("Error: CSI only available in STA mode\n");
|
||||
printf("Use 'mode_sta' to switch to STA mode first\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!s_csi_enabled) {
|
||||
printf("Error: CSI not enabled yet\n");
|
||||
printf("Wait for WiFi connection, or reconnect with 'mode_sta'\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Dumping CSI data...\n");
|
||||
csi_log_dump_over_uart();
|
||||
printf("CSI dump complete\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_mode_commands(void) {
|
||||
const esp_console_cmd_t mode_monitor = {
|
||||
.command = "mode_monitor",
|
||||
.help = "Switch to monitor mode (collapse detection)\n"
|
||||
" ESP32-C5 Hardware: WiFi 6 on 2.4GHz/5GHz, 20/40MHz\n"
|
||||
" Monitor Driver: Typically restricted to 20MHz capture\n"
|
||||
" Usage: mode_monitor [channel[/bandwidth]]\n"
|
||||
" Note: 40MHz will be forced to 20MHz (driver limitation)\n"
|
||||
" Examples:\n"
|
||||
" mode_monitor 6 # 2.4GHz ch 6, 20MHz\n"
|
||||
" mode_monitor 6/20 # 2.4GHz ch 6, 20MHz (explicit)\n"
|
||||
" mode_monitor 36 # 5GHz ch 36, 20MHz\n"
|
||||
" mode_monitor 149/20 # 5GHz ch 149, 20MHz",
|
||||
.func = &cmd_mode_monitor,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&mode_monitor));
|
||||
|
||||
const esp_console_cmd_t mode_sta = {
|
||||
.command = "mode_sta",
|
||||
.help = "Switch to STA mode (CSI + iperf)\n"
|
||||
" STA mode supports 20MHz and 40MHz (full hardware support)\n"
|
||||
" Usage: mode_sta [band]\n"
|
||||
" Band: 2.4, 5, auto (default)\n"
|
||||
" Examples:\n"
|
||||
" mode_sta # Auto band selection\n"
|
||||
" mode_sta 2.4 # Connect on 2.4GHz only\n"
|
||||
" mode_sta 5 # Connect on 5GHz only",
|
||||
.func = &cmd_mode_sta,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&mode_sta));
|
||||
|
||||
const esp_console_cmd_t mode_status = {
|
||||
.command = "mode_status",
|
||||
.help = "Show current WiFi mode and status",
|
||||
.func = &cmd_mode_status,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&mode_status));
|
||||
|
||||
const esp_console_cmd_t csi_dump = {
|
||||
.command = "csi_dump",
|
||||
.help = "Dump CSI data to UART (STA mode only)",
|
||||
.func = &cmd_csi_dump,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&csi_dump));
|
||||
|
||||
ESP_LOGI(TAG, "Mode switch commands registered:");
|
||||
ESP_LOGI(TAG, " mode_monitor [ch/bw] - Switch to monitor mode with bandwidth");
|
||||
ESP_LOGI(TAG, " mode_sta [band] - Switch to STA mode with band preference");
|
||||
ESP_LOGI(TAG, " mode_status - Show current mode");
|
||||
ESP_LOGI(TAG, " csi_dump - Dump CSI data");
|
||||
}
|
||||
|
||||
// --- Event Handler (Connection Logic) ------------------------------
|
||||
|
|
@ -226,37 +679,62 @@ 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 (has_config) current_led_state = LED_STATE_WAITING;
|
||||
if (has_config && current_wifi_mode == WIFI_MODE_STA_CSI) {
|
||||
current_led_state = LED_STATE_WAITING;
|
||||
}
|
||||
}
|
||||
else if (event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
wifi_event_sta_disconnected_t* event = (wifi_event_sta_disconnected_t*) event_data;
|
||||
ESP_LOGW(TAG, "WiFi Disconnected (Reason: %d)", event->reason);
|
||||
if (!wifi_connected && has_config) current_led_state = LED_STATE_FAILED;
|
||||
if (!wifi_connected && has_config && current_wifi_mode == WIFI_MODE_STA_CSI) {
|
||||
current_led_state = LED_STATE_FAILED;
|
||||
}
|
||||
wifi_connected = false;
|
||||
}
|
||||
}
|
||||
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
if (current_wifi_mode != WIFI_MODE_STA_CSI) {
|
||||
ESP_LOGW(TAG, "Got IP but not in STA mode (mode changed during connection)");
|
||||
return;
|
||||
}
|
||||
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
wifi_connected = true;
|
||||
current_led_state = LED_STATE_CONNECTED;
|
||||
|
||||
// Sequence: 1. Start CSI, 2. Start Monitor, 3. Start Iperf
|
||||
xTaskCreate(csi_init_task, "csi_init", 4096, NULL, 5, NULL);
|
||||
// DEFAULT MODE: Start CSI + iperf (STA mode)
|
||||
ESP_LOGI(TAG, "Starting STA mode services...");
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
xTaskCreate(monitor_init_task, "monitor_init", 4096, NULL, 5, NULL);
|
||||
// 1. Enable CSI
|
||||
ESP_LOGI(TAG, "Enabling CSI...");
|
||||
wifi_enable_csi_once();
|
||||
|
||||
// 2. Start iperf server
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
iperf_cfg_t cfg;
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.flag = IPERF_FLAG_SERVER | IPERF_FLAG_TCP;
|
||||
cfg.sport = 5001;
|
||||
iperf_start(&cfg);
|
||||
ESP_LOGI(TAG, "iperf TCP server started on port 5001");
|
||||
ESP_LOGI(TAG, "✓ iperf TCP server started on port 5001");
|
||||
|
||||
// Optional: Dump CSI data later
|
||||
// 3. Optional: Schedule CSI dump for later
|
||||
xTaskCreate(csi_dump_task, "csi_dump_task", 4096, NULL, 5, NULL);
|
||||
|
||||
ESP_LOGI(TAG, "✓ STA mode active");
|
||||
ESP_LOGI(TAG, " - CSI capture enabled");
|
||||
ESP_LOGI(TAG, " - iperf server running");
|
||||
ESP_LOGI(TAG, " - LED: Green");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Console commands available:");
|
||||
ESP_LOGI(TAG, " mode_monitor [ch] - Switch to monitor mode");
|
||||
ESP_LOGI(TAG, " mode_status - Show current status");
|
||||
ESP_LOGI(TAG, " csi_dump - Dump CSI data now");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,10 +752,14 @@ void app_main(void) {
|
|||
rgb_led_init();
|
||||
xTaskCreate(led_task, "led_task", 4096, NULL, 5, NULL);
|
||||
|
||||
// 4. Initialize GPS (The new addition!)
|
||||
// We do this EARLY so timestamps are ready when WiFi events happen
|
||||
ESP_LOGI(TAG, "Starting GPS Sync...");
|
||||
gps_sync_init(true); // true = Use GPS for system log timestamps
|
||||
// 4. Initialize GPS (Enable GPS-timestamped logs)
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Initializing GPS sync...");
|
||||
gps_sync_init(true); // true = GPS timestamps for ESP_LOG
|
||||
ESP_LOGI(TAG, "GPS initialized");
|
||||
ESP_LOGI(TAG, " - Waiting for GPS lock...");
|
||||
ESP_LOGI(TAG, " - Timestamps: (*) = not synced, (+) = GPS synced");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
// 5. Register WiFi Events
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(
|
||||
|
|
@ -288,23 +770,105 @@ void app_main(void) {
|
|||
// 6. Initialize WiFi Configuration
|
||||
wifi_cfg_init();
|
||||
|
||||
// 7. Initialize Serial Console (CRITICAL for console commands)
|
||||
ESP_LOGI(TAG, "Initializing console...");
|
||||
|
||||
/* Disable buffering on stdin */
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
|
||||
/* Initialize the console */
|
||||
esp_console_config_t console_config = {
|
||||
.max_cmdline_args = 8,
|
||||
.max_cmdline_length = 256,
|
||||
#if CONFIG_LOG_COLORS
|
||||
.hint_color = atoi(LOG_COLOR_CYAN)
|
||||
#endif
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_init(&console_config));
|
||||
|
||||
/* Configure linenoise line completion library */
|
||||
linenoiseSetMultiLine(1);
|
||||
linenoiseSetCompletionCallback(NULL);
|
||||
linenoiseSetHintsCallback(NULL);
|
||||
linenoiseHistorySetMaxLen(100);
|
||||
|
||||
/* Register help command */
|
||||
esp_console_register_help_command();
|
||||
|
||||
ESP_LOGI(TAG, "✓ Console initialized");
|
||||
|
||||
// 8. Register Console Commands for Mode Switching
|
||||
register_mode_commands();
|
||||
|
||||
// 9. Apply WiFi config and connect
|
||||
if (wifi_cfg_apply_from_nvs()) {
|
||||
has_config = true;
|
||||
current_led_state = LED_STATE_WAITING;
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "WiFi config loaded. Connecting...");
|
||||
|
||||
// Check if device is configured for MONITOR mode
|
||||
char mode[16] = {0};
|
||||
uint8_t mon_ch = 36;
|
||||
if (wifi_cfg_get_mode(mode, &mon_ch)) {
|
||||
if (strcmp(mode, "MONITOR") == 0) {
|
||||
ESP_LOGI(TAG, "MODE: MONITOR (collapse detection)");
|
||||
ESP_LOGI(TAG, "Monitor Channel: %d", mon_ch);
|
||||
ESP_LOGI(TAG, "Will switch to monitor mode after WiFi connects...");
|
||||
|
||||
// Allocate channel parameter for task
|
||||
uint8_t *ch_param = malloc(sizeof(uint8_t));
|
||||
*ch_param = mon_ch;
|
||||
|
||||
// Create task to switch to monitor mode after connection
|
||||
xTaskCreate(auto_monitor_task, "auto_monitor", 4096, ch_param, 5, NULL);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "MODE: STA (CSI + iperf)");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "DEFAULT MODE: STA (CSI + iperf)");
|
||||
}
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
} else {
|
||||
has_config = false;
|
||||
current_led_state = LED_STATE_NO_CONFIG;
|
||||
ESP_LOGI(TAG, "No WiFi config found. Yellow LED.");
|
||||
ESP_LOGI(TAG, "Use CLI 'wifi_config_set <ssid> <pass>' to configure.");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "No WiFi config found.");
|
||||
ESP_LOGI(TAG, "LED: Yellow");
|
||||
ESP_LOGI(TAG, "Use CLI command: wifi_config_set <ssid> <pass>");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
}
|
||||
|
||||
// 7. Loop forever (Logic is handled by tasks and events)
|
||||
while(1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
// Optional: Print GPS status occasionally
|
||||
if (!gps_is_synced()) {
|
||||
// ESP_LOGI(TAG, "Waiting for GPS lock...");
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
ESP_LOGI(TAG, "Initialization complete");
|
||||
ESP_LOGI(TAG, "Console commands available (no interactive prompt)");
|
||||
ESP_LOGI(TAG, "========================================");
|
||||
|
||||
// app_main() returns - device runs autonomously
|
||||
}
|
||||
|
||||
// --- Auto-Monitor Mode Task (switches to monitor mode after WiFi connects) ---
|
||||
static void auto_monitor_task(void *arg) {
|
||||
uint8_t channel = *(uint8_t*)arg;
|
||||
free(arg); // Free the allocated channel parameter
|
||||
|
||||
// Wait for WiFi connection (LED will be green)
|
||||
ESP_LOGI(TAG, "Waiting for WiFi connection before switching to monitor mode...");
|
||||
while (current_led_state != LED_STATE_CONNECTED) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
}
|
||||
|
||||
// Wait additional 2 seconds for GPS sync
|
||||
ESP_LOGI(TAG, "WiFi connected, waiting for GPS sync...");
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
|
||||
ESP_LOGI(TAG, "Auto-switching to MONITOR mode on channel %d...", channel);
|
||||
esp_err_t err = switch_to_monitor_mode(channel, WIFI_BW_HT20);
|
||||
if (err == ESP_OK) {
|
||||
ESP_LOGI(TAG, "✓ Monitor mode activated");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "✗ Failed to switch to monitor mode: %s", esp_err_to_name(err));
|
||||
}
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# partitions_csi.csv
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xF000, 0x1000,
|
||||
factory, app, factory, 0x10000, 0x100000,
|
||||
csi_log, data, 0x40, 0x110000, 0x0F0000,
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, , 0x6000,
|
||||
phy_init, data, phy, , 0x1000,
|
||||
factory, app, factory, , 2M,
|
||||
csi_log, data, 0x40, , 0x5F0000,
|
||||
|
|
|
|||
|
Loading…
Reference in New Issue