From 09c9a6425587e8f71a8089815aaae11e51bdfef9 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 20 May 2026 06:50:27 +0530 Subject: fix: start captive portal on AP_START, use esp_timer for service init Root cause: xTaskCreate from within IP event handler never scheduled the services_start_task on ESP32-S3. Replaced with esp_timer one-shot callback. Also moved captive_portal_start() into start_ap_services() so the portal starts immediately when the AP comes up, not waiting for STA GOT IP. Added /debug endpoint for runtime diagnostics. Added captive_portal diagnostic getters. --- main/captive_portal.c | 30 +++++++++++++++++++----------- main/captive_portal.h | 2 ++ main/tollgate_api.c | 29 +++++++++++++++++++++++++++++ main/tollgate_main.c | 44 +++++++++++++++++++++++++++++++------------- 4 files changed, 81 insertions(+), 24 deletions(-) (limited to 'main') diff --git a/main/captive_portal.c b/main/captive_portal.c index 6a8c716..9a0a5ff 100644 --- a/main/captive_portal.c +++ b/main/captive_portal.c @@ -17,6 +17,8 @@ #include static const char *TAG = "captive_portal"; +static bool s_start_called = false; +static esp_err_t s_start_result = ESP_OK; static httpd_handle_t s_server = NULL; static char s_ap_ip_str[16] = "10.0.0.1"; @@ -707,16 +709,18 @@ static const httpd_uri_t uri_wifi_status = { .uri = "/wifi/status", .method = HT esp_err_t captive_portal_start(const char *ap_ip_str) { + s_start_called = true; if (s_server) return ESP_OK; + if (!ap_ip_str) return ESP_ERR_INVALID_ARG; strncpy(s_ap_ip_str, ap_ip_str, sizeof(s_ap_ip_str) - 1); httpd_config_t config = HTTPD_DEFAULT_CONFIG(); config.max_uri_handlers = 20; - esp_err_t ret = httpd_start(&s_server, &config); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to start HTTP server: %s", esp_err_to_name(ret)); - return ret; + s_start_result = httpd_start(&s_server, &config); + if (s_start_result != ESP_OK) { + ESP_LOGE(TAG, "Failed to start HTTP server on port %d: %s", config.server_port, esp_err_to_name(s_start_result)); + return s_start_result; } httpd_register_uri_handler(s_server, &uri_portal); @@ -733,19 +737,23 @@ esp_err_t captive_portal_start(const char *ap_ip_str) httpd_register_uri_handler(s_server, &uri_connecttest); httpd_register_uri_handler(s_server, &uri_wpad); httpd_register_uri_handler(s_server, &uri_setup); - ret = httpd_register_uri_handler(s_server, &uri_wifi_scan); - ESP_LOGI(TAG, "Registered /wifi/scan: %s", esp_err_to_name(ret)); - ret = httpd_register_uri_handler(s_server, &uri_wifi_connect); - ESP_LOGI(TAG, "Registered /wifi/connect: %s", esp_err_to_name(ret)); - ret = httpd_register_uri_handler(s_server, &uri_wifi_status); - ESP_LOGI(TAG, "Registered /wifi/status: %s", esp_err_to_name(ret)); + esp_err_t reg_ret; + reg_ret = httpd_register_uri_handler(s_server, &uri_wifi_scan); + ESP_LOGI(TAG, "Registered /wifi/scan: %s", esp_err_to_name(reg_ret)); + reg_ret = httpd_register_uri_handler(s_server, &uri_wifi_connect); + ESP_LOGI(TAG, "Registered /wifi/connect: %s", esp_err_to_name(reg_ret)); + reg_ret = httpd_register_uri_handler(s_server, &uri_wifi_status); + ESP_LOGI(TAG, "Registered /wifi/status: %s", esp_err_to_name(reg_ret)); httpd_register_err_handler(s_server, HTTPD_404_NOT_FOUND, catchall_err_handler); ESP_LOGI(TAG, "Captive portal started on port 80"); - return ESP_OK; + return s_start_result; } +bool captive_portal_was_start_called(void) { return s_start_called; } +esp_err_t captive_portal_get_start_result(void) { return s_start_result; } + void captive_portal_stop(void) { if (s_server) { diff --git a/main/captive_portal.h b/main/captive_portal.h index e02a4ce..c3aa923 100644 --- a/main/captive_portal.h +++ b/main/captive_portal.h @@ -8,5 +8,7 @@ esp_err_t captive_portal_start(const char *ap_ip_str); void captive_portal_stop(void); httpd_handle_t captive_portal_get_server(void); bool captive_portal_is_setup_available(void); +bool captive_portal_was_start_called(void); +esp_err_t captive_portal_get_start_result(void); #endif diff --git a/main/tollgate_api.c b/main/tollgate_api.c index 45cd02f..af91093 100644 --- a/main/tollgate_api.c +++ b/main/tollgate_api.c @@ -3,6 +3,7 @@ #include "config.h" #include "identity.h" #include "session.h" +#include "captive_portal.h" #include "firewall.h" #include "nucula_wallet.h" #include "mint_health.h" @@ -681,6 +682,32 @@ static esp_err_t api_get_mining_stats(httpd_req_t *req) return ESP_OK; } +extern bool s_start_services_called; +extern bool s_start_ap_services_called; +extern bool s_sta_got_ip; +extern bool s_ap_started; + +static esp_err_t api_get_debug(httpd_req_t *req) +{ + httpd_handle_t portal = captive_portal_get_server(); + cJSON *root = cJSON_CreateObject(); + cJSON_AddBoolToObject(root, "portal_running", portal != NULL); + cJSON_AddBoolToObject(root, "portal_start_called", captive_portal_was_start_called()); + cJSON_AddNumberToObject(root, "portal_start_result", captive_portal_get_start_result()); + cJSON_AddBoolToObject(root, "start_services_called", s_start_services_called); + cJSON_AddBoolToObject(root, "start_ap_services_called", s_start_ap_services_called); + cJSON_AddBoolToObject(root, "sta_got_ip", s_sta_got_ip); + cJSON_AddBoolToObject(root, "ap_started", s_ap_started); + cJSON_AddNumberToObject(root, "free_heap", (double)esp_get_free_heap_size()); + cJSON_AddNumberToObject(root, "min_free_heap", (double)esp_get_minimum_free_heap_size()); + char *json = cJSON_PrintUnformatted(root); + httpd_resp_set_type(req, "application/json"); + httpd_resp_sendstr(req, json); + cJSON_free(json); + cJSON_Delete(root); + return ESP_OK; +} + static const httpd_uri_t uri_discovery = { .uri = "/", .method = HTTP_GET, .handler = api_get_discovery }; static const httpd_uri_t uri_payment = { .uri = "/", .method = HTTP_POST, .handler = api_post_payment }; static const httpd_uri_t uri_mints = { .uri = "/mints", .method = HTTP_GET, .handler = api_get_mints }; @@ -731,6 +758,7 @@ static esp_err_t api_get_market(httpd_req_t *req) } static const httpd_uri_t uri_market = { .uri = "/market", .method = HTTP_GET, .handler = api_get_market }; +static const httpd_uri_t uri_debug = { .uri = "/debug", .method = HTTP_GET, .handler = api_get_debug }; esp_err_t tollgate_api_start(void) { @@ -750,6 +778,7 @@ esp_err_t tollgate_api_start(void) } httpd_register_uri_handler(s_api_server, &uri_discovery); + httpd_register_uri_handler(s_api_server, &uri_debug); httpd_register_uri_handler(s_api_server, &uri_payment); httpd_register_uri_handler(s_api_server, &uri_mints); httpd_register_uri_handler(s_api_server, &uri_usage); diff --git a/main/tollgate_main.c b/main/tollgate_main.c index 6c85b28..23b4a00 100644 --- a/main/tollgate_main.c +++ b/main/tollgate_main.c @@ -8,6 +8,7 @@ #include "esp_system.h" #include "nvs_flash.h" #include "esp_netif.h" +#include "esp_timer.h" #include "lwip/netif.h" #include "lwip/dns.h" #include "esp_sntp.h" @@ -55,14 +56,22 @@ static char s_ap_ip_str[16] = "10.0.0.1"; static relay_selector_t s_relay_selector; static sync_manager_t s_sync_manager; +volatile bool s_start_services_called = false; +volatile bool s_start_ap_services_called = false; +volatile bool s_sta_got_ip = false; +volatile bool s_ap_started = false; + static void start_services(void); static void stop_services(void); static void start_ap_services(void); static void start_ap_services(void) { + s_start_ap_services_called = true; if (s_ap_services_running) return; + const tollgate_config_t *cfg = tollgate_config_get(); + captive_portal_start(cfg->ap_ip_str); tollgate_api_start(); beacon_price_start(); market_init(); @@ -120,17 +129,18 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, event->mac[0], event->mac[1], event->mac[2], event->mac[3], event->mac[4], event->mac[5]); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) { + s_ap_started = true; start_ap_services(); } } -static void services_start_task(void *pvParameters) +static void services_start_timer_cb(void *arg) { - vTaskDelay(pdMS_TO_TICKS(3000)); start_services(); - vTaskDelete(NULL); } +static esp_timer_handle_t s_services_timer; + static void ip_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) { @@ -138,8 +148,17 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base, ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data; ESP_LOGI(TAG, "Got IP:" IPSTR ", GW:" IPSTR, IP2STR(&event->ip_info.ip), IP2STR(&event->ip_info.gw)); s_retry_count = 0; + s_sta_got_ip = true; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); + const esp_timer_create_args_t timer_cfg = { + .callback = services_start_timer_cb, + .name = "svc_start", + }; + ESP_ERROR_CHECK(esp_timer_create(&timer_cfg, &s_services_timer)); + ESP_ERROR_CHECK(esp_timer_start_once(s_services_timer, 3000000)); + ESP_LOGI(TAG, "services_start_timer scheduled (3s)"); + esp_sntp_stop(); esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); esp_sntp_setservername(0, "pool.ntp.org"); @@ -150,8 +169,6 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base, char gw_ip_str[16]; snprintf(gw_ip_str, sizeof(gw_ip_str), IPSTR, IP2STR(&event->ip_info.gw)); tollgate_client_on_sta_connected(gw_ip_str); - - xTaskCreate(services_start_task, "svc_start", 32768, NULL, 5, NULL); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP) { ESP_LOGW(TAG, "Lost IP address"); xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT); @@ -159,13 +176,6 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base, } } -static void wallet_init_task(void *pvParameters) -{ - const tollgate_config_t *cfg = tollgate_config_get(); - nucula_wallet_init(cfg->mint_url); - vTaskDelete(NULL); -} - static void publish_wifistr_task(void *pvParameters) { vTaskDelay(pdMS_TO_TICKS(5000)); @@ -177,12 +187,15 @@ static void publish_wifistr_task(void *pvParameters) static void start_services(void) { + ESP_LOGI(TAG, ">>> start_services() called"); if (s_services_mutex) xSemaphoreTake(s_services_mutex, portMAX_DELAY); if (s_services_running) { if (s_services_mutex) xSemaphoreGive(s_services_mutex); return; } + s_start_services_called = true; + esp_netif_get_ip_info(s_ap_netif, &(esp_netif_ip_info_t){0}); esp_netif_ip_info_t ap_ip_info; esp_netif_get_ip_info(s_ap_netif, &ap_ip_info); @@ -412,7 +425,12 @@ void app_main(void) if (tollgate_config_get_wifi(&(wifi_config_t){0}) != ESP_OK) { ESP_LOGI(TAG, "No STA network configured, starting services immediately"); - xTaskCreate(services_start_task, "svc_start", 32768, NULL, 5, NULL); + const esp_timer_create_args_t timer_cfg = { + .callback = services_start_timer_cb, + .name = "svc_start_fallback", + }; + ESP_ERROR_CHECK(esp_timer_create(&timer_cfg, &s_services_timer)); + ESP_ERROR_CHECK(esp_timer_start_once(s_services_timer, 3000000)); } while (1) { -- cgit v1.2.3