diff options
Diffstat (limited to 'main')
| -rw-r--r-- | main/captive_portal.c | 46 | ||||
| -rw-r--r-- | main/tollgate_main.c | 20 |
2 files changed, 43 insertions, 23 deletions
diff --git a/main/captive_portal.c b/main/captive_portal.c index 0c1d33b..d275b59 100644 --- a/main/captive_portal.c +++ b/main/captive_portal.c | |||
| @@ -277,17 +277,19 @@ static esp_err_t redirect_to_portal_handler(httpd_req_t *req) | |||
| 277 | return portal_handler(req); | 277 | return portal_handler(req); |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | static esp_err_t catchall_handler(httpd_req_t *req) | 280 | static esp_err_t catchall_err_handler(httpd_req_t *req, httpd_err_code_t err) |
| 281 | { | 281 | { |
| 282 | ESP_LOGI(TAG, "Catchall: GET %s → 302 → http://%s/", req->uri, s_ap_ip_str); | 282 | if (err == HTTPD_404_NOT_FOUND) { |
| 283 | httpd_resp_set_status(req, "302 Found"); | 283 | ESP_LOGI(TAG, "Catchall 404: GET %s → 302 → http://%s/", req->uri, s_ap_ip_str); |
| 284 | 284 | httpd_resp_set_status(req, "302 Found"); | |
| 285 | char location[64]; | 285 | char location[64]; |
| 286 | snprintf(location, sizeof(location), "http://%s/", s_ap_ip_str); | 286 | snprintf(location, sizeof(location), "http://%s/", s_ap_ip_str); |
| 287 | httpd_resp_set_hdr(req, "Location", location); | 287 | httpd_resp_set_hdr(req, "Location", location); |
| 288 | httpd_resp_set_hdr(req, "Connection", "close"); | 288 | httpd_resp_set_hdr(req, "Connection", "close"); |
| 289 | httpd_resp_send(req, NULL, 0); | 289 | httpd_resp_send(req, NULL, 0); |
| 290 | return ESP_OK; | 290 | return ESP_OK; |
| 291 | } | ||
| 292 | return ESP_FAIL; | ||
| 291 | } | 293 | } |
| 292 | 294 | ||
| 293 | static const httpd_uri_t uri_portal = { .uri = "/", .method = HTTP_GET, .handler = portal_handler }; | 295 | static const httpd_uri_t uri_portal = { .uri = "/", .method = HTTP_GET, .handler = portal_handler }; |
| @@ -303,7 +305,6 @@ static const httpd_uri_t uri_success = { .uri = "/success.txt", .method = HTTP_G | |||
| 303 | static const httpd_uri_t uri_ncsi = { .uri = "/ncsi.txt", .method = HTTP_GET, .handler = redirect_to_portal_handler }; | 305 | static const httpd_uri_t uri_ncsi = { .uri = "/ncsi.txt", .method = HTTP_GET, .handler = redirect_to_portal_handler }; |
| 304 | static const httpd_uri_t uri_connecttest = { .uri = "/connecttest.txt", .method = HTTP_GET, .handler = redirect_to_portal_handler }; | 306 | static const httpd_uri_t uri_connecttest = { .uri = "/connecttest.txt", .method = HTTP_GET, .handler = redirect_to_portal_handler }; |
| 305 | static const httpd_uri_t uri_wpad = { .uri = "/wpad.dat", .method = HTTP_GET, .handler = redirect_to_portal_handler }; | 307 | static const httpd_uri_t uri_wpad = { .uri = "/wpad.dat", .method = HTTP_GET, .handler = redirect_to_portal_handler }; |
| 306 | static const httpd_uri_t uri_catchall = { .uri = "/*", .method = HTTP_GET, .handler = catchall_handler }; | ||
| 307 | 308 | ||
| 308 | static const char SETUP_HTML_TEMPLATE[] = \ | 309 | static const char SETUP_HTML_TEMPLATE[] = \ |
| 309 | "<!DOCTYPE html>" | 310 | "<!DOCTYPE html>" |
| @@ -545,7 +546,7 @@ static esp_err_t wifi_connect_handler(httpd_req_t *req) { | |||
| 545 | int content_len = req->content_len; | 546 | int content_len = req->content_len; |
| 546 | if (content_len <= 0 || content_len > 1024) { | 547 | if (content_len <= 0 || content_len > 1024) { |
| 547 | httpd_resp_set_type(req, "application/json"); | 548 | httpd_resp_set_type(req, "application/json"); |
| 548 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"invalid request\"}", 33); | 549 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"invalid request\"}", HTTPD_RESP_USE_STRLEN); |
| 549 | return ESP_OK; | 550 | return ESP_OK; |
| 550 | } | 551 | } |
| 551 | 552 | ||
| @@ -566,7 +567,7 @@ static esp_err_t wifi_connect_handler(httpd_req_t *req) { | |||
| 566 | free(body); | 567 | free(body); |
| 567 | if (!json) { | 568 | if (!json) { |
| 568 | httpd_resp_set_type(req, "application/json"); | 569 | httpd_resp_set_type(req, "application/json"); |
| 569 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"invalid JSON\"}", 33); | 570 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"invalid JSON\"}", HTTPD_RESP_USE_STRLEN); |
| 570 | return ESP_OK; | 571 | return ESP_OK; |
| 571 | } | 572 | } |
| 572 | 573 | ||
| @@ -575,7 +576,7 @@ static esp_err_t wifi_connect_handler(httpd_req_t *req) { | |||
| 575 | if (!ssid_item || !cJSON_IsString(ssid_item)) { | 576 | if (!ssid_item || !cJSON_IsString(ssid_item)) { |
| 576 | cJSON_Delete(json); | 577 | cJSON_Delete(json); |
| 577 | httpd_resp_set_type(req, "application/json"); | 578 | httpd_resp_set_type(req, "application/json"); |
| 578 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"missing ssid\"}", 32); | 579 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"missing ssid\"}", HTTPD_RESP_USE_STRLEN); |
| 579 | return ESP_OK; | 580 | return ESP_OK; |
| 580 | } | 581 | } |
| 581 | 582 | ||
| @@ -586,7 +587,7 @@ static esp_err_t wifi_connect_handler(httpd_req_t *req) { | |||
| 586 | if (err != ESP_OK) { | 587 | if (err != ESP_OK) { |
| 587 | cJSON_Delete(json); | 588 | cJSON_Delete(json); |
| 588 | httpd_resp_set_type(req, "application/json"); | 589 | httpd_resp_set_type(req, "application/json"); |
| 589 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"save failed\"}", 33); | 590 | httpd_resp_send(req, "{\"ok\":false,\"error\":\"save failed\"}", HTTPD_RESP_USE_STRLEN); |
| 590 | return ESP_OK; | 591 | return ESP_OK; |
| 591 | } | 592 | } |
| 592 | 593 | ||
| @@ -600,7 +601,7 @@ static esp_err_t wifi_connect_handler(httpd_req_t *req) { | |||
| 600 | cJSON_Delete(json); | 601 | cJSON_Delete(json); |
| 601 | 602 | ||
| 602 | httpd_resp_set_type(req, "application/json"); | 603 | httpd_resp_set_type(req, "application/json"); |
| 603 | httpd_resp_send(req, "{\"ok\":true}", 10); | 604 | httpd_resp_send(req, "{\"ok\":true}", HTTPD_RESP_USE_STRLEN); |
| 604 | return ESP_OK; | 605 | return ESP_OK; |
| 605 | } | 606 | } |
| 606 | 607 | ||
| @@ -644,7 +645,6 @@ esp_err_t captive_portal_start(const char *ap_ip_str) | |||
| 644 | 645 | ||
| 645 | httpd_config_t config = HTTPD_DEFAULT_CONFIG(); | 646 | httpd_config_t config = HTTPD_DEFAULT_CONFIG(); |
| 646 | config.max_uri_handlers = 20; | 647 | config.max_uri_handlers = 20; |
| 647 | config.uri_match_fn = httpd_uri_match_wildcard; | ||
| 648 | 648 | ||
| 649 | esp_err_t ret = httpd_start(&s_server, &config); | 649 | esp_err_t ret = httpd_start(&s_server, &config); |
| 650 | if (ret != ESP_OK) { | 650 | if (ret != ESP_OK) { |
| @@ -666,10 +666,14 @@ esp_err_t captive_portal_start(const char *ap_ip_str) | |||
| 666 | httpd_register_uri_handler(s_server, &uri_connecttest); | 666 | httpd_register_uri_handler(s_server, &uri_connecttest); |
| 667 | httpd_register_uri_handler(s_server, &uri_wpad); | 667 | httpd_register_uri_handler(s_server, &uri_wpad); |
| 668 | httpd_register_uri_handler(s_server, &uri_setup); | 668 | httpd_register_uri_handler(s_server, &uri_setup); |
| 669 | httpd_register_uri_handler(s_server, &uri_wifi_scan); | 669 | ret = httpd_register_uri_handler(s_server, &uri_wifi_scan); |
| 670 | httpd_register_uri_handler(s_server, &uri_wifi_connect); | 670 | ESP_LOGI(TAG, "Registered /wifi/scan: %s", esp_err_to_name(ret)); |
| 671 | httpd_register_uri_handler(s_server, &uri_wifi_status); | 671 | ret = httpd_register_uri_handler(s_server, &uri_wifi_connect); |
| 672 | httpd_register_uri_handler(s_server, &uri_catchall); | 672 | ESP_LOGI(TAG, "Registered /wifi/connect: %s", esp_err_to_name(ret)); |
| 673 | ret = httpd_register_uri_handler(s_server, &uri_wifi_status); | ||
| 674 | ESP_LOGI(TAG, "Registered /wifi/status: %s", esp_err_to_name(ret)); | ||
| 675 | |||
| 676 | httpd_register_err_handler(s_server, HTTPD_404_NOT_FOUND, catchall_err_handler); | ||
| 673 | 677 | ||
| 674 | ESP_LOGI(TAG, "Captive portal started on port 80"); | 678 | ESP_LOGI(TAG, "Captive portal started on port 80"); |
| 675 | return ESP_OK; | 679 | return ESP_OK; |
diff --git a/main/tollgate_main.c b/main/tollgate_main.c index 9960ea5..ec6ffc8 100644 --- a/main/tollgate_main.c +++ b/main/tollgate_main.c | |||
| @@ -37,11 +37,13 @@ static esp_netif_t *s_ap_netif = NULL; | |||
| 37 | static int s_retry_count = 0; | 37 | static int s_retry_count = 0; |
| 38 | static int s_total_retries = 0; | 38 | static int s_total_retries = 0; |
| 39 | static bool s_services_running = false; | 39 | static bool s_services_running = false; |
| 40 | static bool s_start_in_error_state = false; | ||
| 40 | static SemaphoreHandle_t s_services_mutex = NULL; | 41 | static SemaphoreHandle_t s_services_mutex = NULL; |
| 41 | static char s_ap_ip_str[16] = "10.0.0.1"; | 42 | static char s_ap_ip_str[16] = "10.0.0.1"; |
| 42 | 43 | ||
| 43 | static void start_services(void); | 44 | static void start_services(void); |
| 44 | static void stop_services(void); | 45 | static void stop_services(void); |
| 46 | static void services_start_task(void *pvParameters); | ||
| 45 | 47 | ||
| 46 | static void wifi_event_handler(void *arg, esp_event_base_t event_base, | 48 | static void wifi_event_handler(void *arg, esp_event_base_t event_base, |
| 47 | int32_t event_id, void *event_data) | 49 | int32_t event_id, void *event_data) |
| @@ -60,11 +62,15 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, | |||
| 60 | tollgate_client_on_sta_disconnected(); | 62 | tollgate_client_on_sta_disconnected(); |
| 61 | display_notify_wifi_disconnected(); | 63 | display_notify_wifi_disconnected(); |
| 62 | if (s_services_running) { | 64 | if (s_services_running) { |
| 63 | stop_services(); | ||
| 64 | display_set_state(DISPLAY_ERROR); | 65 | display_set_state(DISPLAY_ERROR); |
| 65 | } | 66 | } |
| 66 | if (s_total_retries >= MAX_TOTAL_RETRIES) { | 67 | if (s_total_retries >= MAX_TOTAL_RETRIES) { |
| 67 | ESP_LOGW(TAG, "All WiFi retries exhausted"); | 68 | ESP_LOGW(TAG, "All WiFi retries exhausted"); |
| 69 | if (!s_services_running) { | ||
| 70 | s_start_in_error_state = true; | ||
| 71 | ESP_LOGI(TAG, "Starting services for /setup access (no upstream)"); | ||
| 72 | xTaskCreate(services_start_task, "svc_start", 32768, NULL, 5, NULL); | ||
| 73 | } | ||
| 68 | const tollgate_config_t *cfg = tollgate_config_get(); | 74 | const tollgate_config_t *cfg = tollgate_config_get(); |
| 69 | char portal_url[128]; | 75 | char portal_url[128]; |
| 70 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); | 76 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); |
| @@ -86,6 +92,11 @@ static void wifi_event_handler(void *arg, esp_event_base_t event_base, | |||
| 86 | esp_wifi_connect(); | 92 | esp_wifi_connect(); |
| 87 | } else { | 93 | } else { |
| 88 | ESP_LOGW(TAG, "No more WiFi networks to try"); | 94 | ESP_LOGW(TAG, "No more WiFi networks to try"); |
| 95 | if (!s_services_running) { | ||
| 96 | s_start_in_error_state = true; | ||
| 97 | ESP_LOGI(TAG, "Starting services for /setup access (no upstream)"); | ||
| 98 | xTaskCreate(services_start_task, "svc_start", 32768, NULL, 5, NULL); | ||
| 99 | } | ||
| 89 | const tollgate_config_t *cfg = tollgate_config_get(); | 100 | const tollgate_config_t *cfg = tollgate_config_get(); |
| 90 | char portal_url[128]; | 101 | char portal_url[128]; |
| 91 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); | 102 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); |
| @@ -143,7 +154,6 @@ static void ip_event_handler(void *arg, esp_event_base_t event_base, | |||
| 143 | } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP) { | 154 | } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_LOST_IP) { |
| 144 | ESP_LOGW(TAG, "Lost IP address"); | 155 | ESP_LOGW(TAG, "Lost IP address"); |
| 145 | xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT); | 156 | xEventGroupClearBits(s_wifi_event_group, WIFI_CONNECTED_BIT); |
| 146 | stop_services(); | ||
| 147 | } | 157 | } |
| 148 | } | 158 | } |
| 149 | 159 | ||
| @@ -202,6 +212,12 @@ static void start_services(void) | |||
| 202 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); | 212 | if (s_services_mutex) xSemaphoreGive(s_services_mutex); |
| 203 | ESP_LOGI(TAG, "=== TollGate services started ==="); | 213 | ESP_LOGI(TAG, "=== TollGate services started ==="); |
| 204 | 214 | ||
| 215 | if (s_start_in_error_state) { | ||
| 216 | s_start_in_error_state = false; | ||
| 217 | ESP_LOGI(TAG, "Services started in error state (no upstream), keeping DISPLAY_ERROR"); | ||
| 218 | return; | ||
| 219 | } | ||
| 220 | |||
| 205 | display_set_state(DISPLAY_READY); | 221 | display_set_state(DISPLAY_READY); |
| 206 | char portal_url[128]; | 222 | char portal_url[128]; |
| 207 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); | 223 | snprintf(portal_url, sizeof(portal_url), "http://%s/", cfg->ap_ip_str); |