diff --git a/config_device.py b/config_device.py index 2a4b58f..afb1f63 100755 --- a/config_device.py +++ b/config_device.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -ESP32 WiFi Configuration Tool - With verbose mode and 80MHz support +ESP32 WiFi Configuration Tool - Static IP with auto-disable DHCP """ import serial @@ -16,15 +16,15 @@ 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): - """Configure ESP32 device via serial""" + """Configure ESP32 device via serial with static IP""" print(f"\n{'='*70}") - print(f"ESP32 WiFi Configuration") + print(f"ESP32 WiFi Configuration (Static IP)") print(f"{'='*70}") print(f"Port: {port}") print(f"SSID: {ssid}") print(f"Password: {'*' * len(password)}") - print(f"IP: {ip}") + print(f"IP: {ip} (DHCP disabled)") print(f"Gateway: {gateway}") print(f"Netmask: {netmask}") print(f"Band: {band}") @@ -50,6 +50,7 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", log_verbose(f"Existing data: {existing[:100]}", verbose) # Build config message + # DHCP is always disabled (0) when IP address is provided config_lines = [ "CFG", f"SSID:{ssid}", @@ -57,7 +58,7 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", f"IP:{ip}", f"MASK:{netmask}", f"GW:{gateway}", - "DHCP:0", + "DHCP:0", # Always disabled for static IP f"BAND:{band}", f"BW:{bandwidth}", f"POWERSAVE:{powersave}", @@ -120,7 +121,11 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", import re ip_match = re.search(r'got ip:(\d+\.\d+\.\d+\.\d+)', response, re.IGNORECASE) if ip_match: - success_indicators.append(f" Assigned IP: {ip_match.group(1)}") + received_ip = ip_match.group(1) + success_indicators.append(f" Assigned IP: {received_ip}") + if received_ip != ip: + warning_indicators.append(f"⚠ Warning: Device got {received_ip} instead of configured {ip}") + warning_indicators.append(" This might indicate DHCP is still enabled") if "connected" in response.lower(): success_indicators.append("✓ WiFi connection established") @@ -185,12 +190,16 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", boot_warnings.append("✗ NO CONFIG found in NVS") boot_warnings.append(" Device does not see saved config") - if "got ip:" in boot_msg.lower(): - boot_success.append("✓ Device connected to WiFi!") - import re - ip_match = re.search(r'got ip:(\d+\.\d+\.\d+\.\d+)', boot_msg, re.IGNORECASE) - if ip_match: - boot_success.append(f" Connected with IP: {ip_match.group(1)}") + # Check if device got the correct static IP + import re + ip_match = re.search(r'got ip:(\d+\.\d+\.\d+\.\d+)', boot_msg, re.IGNORECASE) + if ip_match: + received_ip = ip_match.group(1) + if received_ip == ip: + boot_success.append(f"✓ Device got correct static IP: {ip}") + else: + boot_warnings.append(f"⚠ Device got {received_ip} instead of {ip}") + boot_warnings.append(" DHCP may still be enabled or IP conflict exists") if "WiFi CONNECTED" in boot_msg: boot_success.append("✓ WiFi connection confirmed") @@ -219,16 +228,20 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", print("Configuration Summary") print(f"{'='*70}") print(f"Port: {port}") - print(f"Expected IP: {ip}") + print(f"Static IP: {ip}") print(f"SSID: {ssid}") print(f"Band: {band}") print(f"Bandwidth: {bandwidth}") print(f"PowerSave: {powersave}") + print(f"DHCP: Disabled (static IP mode)") print(f"{'='*70}") print("\nNext steps:") print(f" 1. Test connection:") print(f" ping {ip}") print(f" iperf -c {ip}") + print(f"\n 2. Verify device has correct IP:") + print(f" idf.py -p {port} monitor") + print(f" Look for: 'got ip:{ip}'") return True @@ -253,37 +266,34 @@ def config_device(port, ip, ssid="ClubHouse2G", password="ez2remember", def main(): parser = argparse.ArgumentParser( - description='Configure ESP32 WiFi via serial', + description='Configure ESP32 WiFi with static IP (DHCP automatically disabled)', formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: - # Basic configuration (2.4GHz, 20MHz) with auto-reboot + # Basic 2.4GHz configuration with static IP (DHCP disabled automatically) %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 - # 5GHz with 40MHz bandwidth - %(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -s ClubHouse5G -b 5G -B HT40 - - # 5GHz with 80MHz bandwidth (ESP32-C5 only, 802.11ac/ax) + # 5GHz with 80MHz bandwidth %(prog)s -p /dev/ttyUSB0 -i 192.168.1.81 -s ClubHouse5G -b 5G -B VHT80 - # Disable power save for best CSI quality (default) + # 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 - # Configure without rebooting - %(prog)s -p /dev/ttyUSB0 -i 192.168.1.51 -r - # 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. """ ) parser.add_argument('-p', '--port', required=True, help='Serial port (e.g., /dev/ttyUSB0)') parser.add_argument('-i', '--ip', required=True, - help='Static IP address') + help='Static IP address (DHCP will be disabled)') parser.add_argument('-s', '--ssid', default='ClubHouse2G', help='WiFi SSID (default: ClubHouse2G)') parser.add_argument('-P', '--password', default='ez2remember', diff --git a/main/main.c b/main/main.c index f86452f..2e68c5e 100644 --- a/main/main.c +++ b/main/main.c @@ -24,7 +24,6 @@ static const char *TAG = "main"; -// RGB LED GPIO pin configuration #if CONFIG_IDF_TARGET_ESP32S3 #define RGB_LED_GPIO 48 #elif CONFIG_IDF_TARGET_ESP32C5 @@ -42,12 +41,9 @@ static const char *TAG = "main"; #endif static led_strip_handle_t led_strip; - -// WiFi connection status static bool wifi_connected = false; static bool has_config = false; -// LED states typedef enum { LED_STATE_NO_CONFIG, LED_STATE_WAITING, @@ -132,7 +128,6 @@ static void csi_dump_task(void *arg) { static void csi_cb(void *ctx, wifi_csi_info_t *info) { csi_log_append_record(info); - s_csi_packet_count++; if ((s_csi_packet_count % 100) == 0) { @@ -147,20 +142,7 @@ static void wifi_enable_csi_once(void) { esp_err_t err; - // Wait for WiFi to stabilize - ESP_LOGI("CSI", "Waiting 500ms for WiFi to stabilize..."); - vTaskDelay(pdMS_TO_TICKS(500)); - - // Get power save mode from NVS configuration - wifi_ps_type_t ps_mode = wifi_cfg_get_power_save_mode(); - err = esp_wifi_set_ps(ps_mode); - if (err != ESP_OK) { - ESP_LOGW("CSI", "Failed to set power save mode: %s", esp_err_to_name(err)); - } else { - const char *ps_str = (ps_mode == WIFI_PS_NONE) ? "NONE (disabled)" : - (ps_mode == WIFI_PS_MIN_MODEM) ? "MIN_MODEM" : "MAX_MODEM"; - ESP_LOGI("CSI", "WiFi power save set to: %s", ps_str); - } + vTaskDelay(pdMS_TO_TICKS(2000)); wifi_csi_config_t csi_cfg; @@ -172,8 +154,8 @@ static void wifi_enable_csi_once(void) { memset(&csi_cfg, 0, sizeof(csi_cfg)); csi_cfg.lltf_en = true; csi_cfg.htltf_en = true; - csi_cfg.stbc_htltf2_en = true; - csi_cfg.ltf_merge_en = true; + csi_cfg.stbc_htltf2_en = false; + csi_cfg.ltf_merge_en = false; csi_cfg.channel_filter_en = false; csi_cfg.manu_scale = false; csi_cfg.shift = 0; @@ -183,34 +165,33 @@ static void wifi_enable_csi_once(void) { return; #endif + ESP_LOGI("CSI", "Configuring CSI..."); + err = esp_wifi_set_csi_config(&csi_cfg); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi_config failed: %s (0x%x)", esp_err_to_name(err), err); return; } - ESP_LOGI("CSI", "CSI config applied successfully"); + ESP_LOGI("CSI", "CSI config OK"); err = esp_wifi_set_csi_rx_cb(csi_cb, NULL); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi_rx_cb failed: %s", esp_err_to_name(err)); return; } - ESP_LOGI("CSI", "CSI callback registered"); + ESP_LOGI("CSI", "CSI callback OK"); err = esp_wifi_set_csi(true); if (err != ESP_OK) { ESP_LOGE("CSI", "esp_wifi_set_csi(true) failed: %s", esp_err_to_name(err)); return; } - ESP_LOGI("CSI", "CSI capture enabled"); + ESP_LOGI("CSI", "CSI enabled!"); - ESP_LOGI("CSI", "CSI fully enabled and capturing!"); s_csi_enabled = true; } static void csi_init_task(void *arg) { - vTaskDelay(pdMS_TO_TICKS(1000)); - ESP_LOGI("CSI", "Starting CSI initialization..."); wifi_enable_csi_once(); vTaskDelete(NULL); } @@ -229,7 +210,43 @@ static void event_handler(void* arg, esp_event_base_t event_base, case 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); + + // Get SSID for better error messages + wifi_config_t wifi_cfg; + const char *ssid = "unknown"; + if (esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) == ESP_OK) { + ssid = (const char*)wifi_cfg.sta.ssid; + } + + // Log disconnect with reason-specific messages + switch (event->reason) { + case 201: // WIFI_REASON_NO_AP_FOUND + ESP_LOGE(TAG, "WiFi disconnected (reason 201): NO AP FOUND"); + ESP_LOGE(TAG, " SSID attempted: '%s'", ssid); + ESP_LOGE(TAG, " Verify AP is broadcasting and in range"); + break; + case 202: // WIFI_REASON_AUTH_FAIL + ESP_LOGE(TAG, "WiFi disconnected (reason 202): AUTH FAILED"); + ESP_LOGE(TAG, " SSID: '%s'", ssid); + ESP_LOGE(TAG, " Check password is correct"); + break; + case 15: // WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT + ESP_LOGE(TAG, "WiFi disconnected (reason 15): 4-WAY HANDSHAKE TIMEOUT"); + ESP_LOGE(TAG, " SSID: '%s'", ssid); + ESP_LOGE(TAG, " Password may be incorrect"); + break; + case 2: // WIFI_REASON_AUTH_EXPIRE + ESP_LOGW(TAG, "WiFi disconnected (reason 2): AUTH EXPIRED"); + ESP_LOGW(TAG, " SSID: '%s' - will retry", ssid); + break; + case 8: // WIFI_REASON_ASSOC_LEAVE + ESP_LOGW(TAG, "WiFi disconnected (reason 8): STATION LEFT"); + ESP_LOGW(TAG, " SSID: '%s' - normal disconnect", ssid); + break; + default: + ESP_LOGW(TAG, "WiFi disconnected from '%s', reason: %d", ssid, event->reason); + break; + } if (!wifi_connected && has_config) { current_led_state = LED_STATE_FAILED; @@ -247,12 +264,36 @@ static void event_handler(void* arg, esp_event_base_t event_base, wifi_connected = true; current_led_state = LED_STATE_CONNECTED; - ESP_LOGI(TAG, "WiFi CONNECTED - BLUE LED solid"); - // Enable CSI in separate task + // Log connection details: SSID, band, channel, RSSI + wifi_config_t wifi_cfg; + wifi_ap_record_t ap_info; + if (esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) == ESP_OK && + esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { + + const char *band_str = "Unknown"; + if (ap_info.primary >= 1 && ap_info.primary <= 14) { + band_str = "2.4GHz"; + } else if (ap_info.primary >= 36) { + band_str = "5GHz"; + } + + ESP_LOGI(TAG, "========================================"); + ESP_LOGI(TAG, "WiFi CONNECTED - BLUE LED solid"); + ESP_LOGI(TAG, " SSID: '%s'", wifi_cfg.sta.ssid); + ESP_LOGI(TAG, " Band: %s", band_str); + ESP_LOGI(TAG, " Channel: %d", ap_info.primary); + ESP_LOGI(TAG, " RSSI: %d dBm", ap_info.rssi); + ESP_LOGI(TAG, " BSSID: %02x:%02x:%02x:%02x:%02x:%02x", + ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2], + ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]); + ESP_LOGI(TAG, "========================================"); + } else { + ESP_LOGI(TAG, "WiFi CONNECTED - BLUE LED solid"); + } + xTaskCreate(csi_init_task, "csi_init", 4096, NULL, 5, NULL); - // Auto-start iperf server vTaskDelay(pdMS_TO_TICKS(1000)); iperf_cfg_t cfg; @@ -263,7 +304,6 @@ static void event_handler(void* arg, esp_event_base_t event_base, iperf_start(&cfg); ESP_LOGI(TAG, "iperf TCP server started on port 5001"); - // Schedule CSI dump xTaskCreate(csi_dump_task, "csi_dump_task", 4096, NULL, 5, NULL); } }