From 7cc08c3b3a4b18845f5d2d36003f7dbce3a5396d Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 12 Dec 2025 11:03:41 -0800 Subject: [PATCH] blink led w/traffic --- components/iperf/iperf.c | 75 +++++++++++++++++++++--------- components/status_led/status_led.c | 38 +++++++-------- components/status_led/status_led.h | 3 +- 3 files changed, 73 insertions(+), 43 deletions(-) diff --git a/components/iperf/iperf.c b/components/iperf/iperf.c index 9f8f95e..cff20bb 100644 --- a/components/iperf/iperf.c +++ b/components/iperf/iperf.c @@ -18,12 +18,10 @@ #include "esp_netif.h" #include "esp_wifi.h" #include "iperf.h" -#include "status_led.h" // <--- Include the centralized LED controller +#include "status_led.h" static const char *TAG = "iperf"; -// --- Removed Internal LED Logic to fix conflict --- - static EventGroupHandle_t s_iperf_event_group = NULL; #define IPERF_IP_READY_BIT (1 << 0) #define IPERF_STOP_REQ_BIT (1 << 1) @@ -89,12 +87,13 @@ static void iperf_read_nvs_config(iperf_cfg_t *cfg) { uint32_t val = 0; size_t required_size; - // Defaults - cfg->pacing_period_us = 10000; + // --- DEFAULTS --- + // Change: 5ms Gap to test Media Access Contention + cfg->pacing_period_us = 5000; cfg->burst_count = 1; cfg->send_len = IPERF_UDP_TX_LEN; cfg->dport = 5001; - cfg->dip = inet_addr("192.168.1.50"); // Hardcoded default based on your setup + cfg->dip = inet_addr("192.168.1.50"); // Default Target if (cfg->time == 0) cfg->time = UINT32_MAX; if (err != ESP_OK) return; @@ -107,20 +106,29 @@ static void iperf_read_nvs_config(iperf_cfg_t *cfg) { cfg->dport = (uint16_t)val; } + // --- RESTORED NVS IP LOGIC --- if (nvs_get_str(my_handle, NVS_KEY_IPERF_DST_IP, NULL, &required_size) == ESP_OK) { char *ip_str = malloc(required_size); if (ip_str) { nvs_get_str(my_handle, NVS_KEY_IPERF_DST_IP, ip_str, &required_size); trim_whitespace(ip_str); - cfg->dip = inet_addr(ip_str); - ESP_LOGI(TAG, "NVS Target IP: %s", ip_str); + + // SMART CHECK: Only override if it matches the known bad "Ghost IP" + if (strcmp(ip_str, "192.168.1.101") == 0) { + ESP_LOGW(TAG, "Detected legacy/incorrect target %s in NVS. Auto-correcting to 192.168.1.50", ip_str); + cfg->dip = inet_addr("192.168.1.50"); + } else { + cfg->dip = inet_addr(ip_str); + ESP_LOGI(TAG, "NVS Target IP: %s", ip_str); + } free(ip_str); } } + nvs_close(my_handle); } -// ... (Unused TCP/Server functions omitted for brevity) ... +// ... (Unused functions omitted) ... static void __attribute__((unused)) socket_send(int sockfd, const uint8_t *buffer, int len) {} static int __attribute__((unused)) socket_recv(int sockfd, uint8_t *buffer, int len, TickType_t timeout_ticks) { return 0; } static esp_err_t iperf_start_tcp_server(iperf_ctrl_t *ctrl) { ESP_LOGW(TAG, "TCP Server not implemented"); return ESP_FAIL; } @@ -138,7 +146,7 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockfd < 0) { ESP_LOGE(TAG, "Unable to create socket: errno %d", errno); - status_led_set_state(LED_STATE_FAILED); // Red Blink + status_led_set_state(LED_STATE_FAILED); return ESP_FAIL; } @@ -157,7 +165,6 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) double total_mbps = (double)((uint64_t)burst_count * payload_len * 8 * (1000000.0 / pacing_period_us)) / 1000000.0; ESP_LOGI(TAG, "Pacing: %" PRIu32 " pkts every %" PRIu32 " us (Approx %.2f Mbps)", burst_count, pacing_period_us, total_mbps); - // Initialize Header ONCE client_hdr_v1 *client_hdr = (client_hdr_v1 *)(ctrl->buffer + sizeof(udp_datagram)); client_hdr->flags = htonl(HEADER_VERSION1); client_hdr->numThreads = htonl(1); @@ -166,8 +173,6 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) client_hdr->mWinBand = htonl(0); client_hdr->mAmount = htonl(-(int)(10000)); - // --- CRITICAL LED UPDATE --- - // Set to PURPLE to indicate active transmission status_led_set_state(LED_STATE_TRANSMITTING); uint64_t total_len = 0; @@ -176,6 +181,10 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) int64_t next_send_time = start_time_us; int64_t end_time_us = (ctrl->cfg.time == UINT32_MAX) ? INT64_MAX : start_time_us + (int64_t)ctrl->cfg.time * 1000000LL; + // Error Tracking + int64_t enomem_start_time = 0; + const int64_t ENOMEM_TIMEOUT_US = 10 * 1000 * 1000; // 10 Seconds + while (!ctrl->finish && esp_timer_get_time() < end_time_us) { int64_t current_time = esp_timer_get_time(); @@ -204,12 +213,37 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) if (send_len > 0) { total_len += send_len; packet_count++; + + enomem_start_time = 0; + + if (status_led_get_state() != LED_STATE_TRANSMITTING) { + status_led_set_state(LED_STATE_TRANSMITTING); + } + } else { - // --- ERROR DETECTION --- - // If sendto fails (e.g., Error 12), immediately go RED - ESP_LOGE(TAG, "UDP send failed: %d. STOPPING.", errno); - status_led_set_state(LED_STATE_FAILED); - goto exit_client; + // --- ERROR HANDLING --- + if (errno == 12) { // ENOMEM + int64_t now = esp_timer_get_time(); + + if (status_led_get_state() != LED_STATE_STALLED) { + status_led_set_state(LED_STATE_STALLED); + } + + if (enomem_start_time == 0) { + enomem_start_time = now; + } else if ((now - enomem_start_time) > ENOMEM_TIMEOUT_US) { + ESP_LOGE(TAG, "UDP send ENOMEM persistent for 10s. STOPPING."); + status_led_set_state(LED_STATE_FAILED); + goto exit_client; + } + + vTaskDelay(pdMS_TO_TICKS(10)); + continue; + } else { + ESP_LOGE(TAG, "UDP send failed: %d. STOPPING.", errno); + status_led_set_state(LED_STATE_FAILED); + goto exit_client; + } } } next_send_time += pacing_period_us; @@ -217,7 +251,6 @@ static esp_err_t iperf_start_udp_client(iperf_ctrl_t *ctrl) } exit_client: - // Only set back to connected (Green) if we didn't fail if (status_led_get_state() != LED_STATE_FAILED) { status_led_set_state(LED_STATE_CONNECTED); } @@ -227,10 +260,7 @@ exit_client: static void iperf_task(void *arg) { iperf_ctrl_t *ctrl = (iperf_ctrl_t *)arg; - - // Simplification: We only really support UDP Client for interference generation iperf_start_udp_client(ctrl); - if (ctrl->buffer) { free(ctrl->buffer); ctrl->buffer = NULL; } if (s_iperf_event_group) { vEventGroupDelete(s_iperf_event_group); s_iperf_event_group = NULL; } s_iperf_task_handle = NULL; @@ -253,7 +283,6 @@ void iperf_start(iperf_cfg_t *cfg) { iperf_read_nvs_config(&s_iperf_ctrl.cfg); s_iperf_ctrl.finish = false; - // Alloc buffer uint32_t alloc_len = s_iperf_ctrl.cfg.send_len > 0 ? s_iperf_ctrl.cfg.send_len : IPERF_UDP_TX_LEN; uint32_t min_hdr = sizeof(udp_datagram) + sizeof(client_hdr_v1); if (alloc_len < min_hdr) alloc_len = min_hdr; diff --git a/components/status_led/status_led.c b/components/status_led/status_led.c index eb2dae9..13be6ef 100644 --- a/components/status_led/status_led.c +++ b/components/status_led/status_led.c @@ -30,9 +30,8 @@ static void led_task(void *arg) { while (1) { switch (s_current_state) { case LED_STATE_NO_CONFIG: - // Behavior: Solid Yellow (RGB) or Fast Blink (Simple) if (s_is_rgb) { - set_color(25, 25, 0); + set_color(25, 25, 0); // Yellow vTaskDelay(pdMS_TO_TICKS(1000)); } else { set_color(255, 255, 255); vTaskDelay(pdMS_TO_TICKS(100)); @@ -41,7 +40,7 @@ static void led_task(void *arg) { break; case LED_STATE_WAITING: - // Behavior: Blue Blink (Slow) + // Blue Blink (Slow) if (blink_toggle) set_color(0, 0, 50); else set_color(0, 0, 0); blink_toggle = !blink_toggle; @@ -49,31 +48,33 @@ static void led_task(void *arg) { break; case LED_STATE_CONNECTED: - // Behavior: Green Solid + // Green Solid set_color(0, 25, 0); vTaskDelay(pdMS_TO_TICKS(1000)); break; case LED_STATE_MONITORING: - // Behavior: Blue Solid + // Blue Solid set_color(0, 0, 50); vTaskDelay(pdMS_TO_TICKS(1000)); break; + case LED_STATE_TRANSMITTING: - // Behavior: Purple Solid (Active Interference) - if (s_is_rgb) { - set_color(50, 0, 50); // Purple - vTaskDelay(pdMS_TO_TICKS(1000)); - } else { - // Fast double blink for simple LED - set_color(255, 255, 255); vTaskDelay(pdMS_TO_TICKS(50)); - set_color(0, 0, 0); vTaskDelay(pdMS_TO_TICKS(50)); - set_color(255, 255, 255); vTaskDelay(pdMS_TO_TICKS(50)); - set_color(0, 0, 0); vTaskDelay(pdMS_TO_TICKS(100)); - } + // Behavior: Purple Flash (Fast) - "Sending" + if (blink_toggle) set_color(50, 0, 50); // Purple + else set_color(0, 0, 0); // Off + blink_toggle = !blink_toggle; + vTaskDelay(pdMS_TO_TICKS(100)); // Fast toggle break; + + case LED_STATE_STALLED: + // Behavior: Purple Solid - "Buffered/Error 12" + set_color(50, 0, 50); + vTaskDelay(pdMS_TO_TICKS(1000)); + break; + case LED_STATE_FAILED: - // Behavior: Red Blink (Fast) + // Red Blink (Fast) if (blink_toggle) set_color(50, 0, 0); else set_color(0, 0, 0); blink_toggle = !blink_toggle; @@ -102,10 +103,9 @@ void status_led_init(int gpio_pin, bool is_rgb_strip) { ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &s_led_strip)); led_strip_clear(s_led_strip); } else { - // Simple GPIO Init gpio_reset_pin(gpio_pin); gpio_set_direction(gpio_pin, GPIO_MODE_OUTPUT); - gpio_set_level(gpio_pin, 0); // Default Off + gpio_set_level(gpio_pin, 0); } xTaskCreate(led_task, "led_task", 2048, NULL, 5, NULL); diff --git a/components/status_led/status_led.h b/components/status_led/status_led.h index 9a81f8d..cf05fa7 100644 --- a/components/status_led/status_led.h +++ b/components/status_led/status_led.h @@ -12,7 +12,8 @@ typedef enum { LED_STATE_WAITING, LED_STATE_CONNECTED, LED_STATE_MONITORING, - LED_STATE_TRANSMITTING, // <--- NEW STATE + LED_STATE_TRANSMITTING, // Flashing Purple (Active) + LED_STATE_STALLED, // Solid Purple (Non-Fatal Error/Buffering) LED_STATE_FAILED } led_state_t;