diff --git a/main/apps/app_server/app_server.cpp b/main/apps/app_server/app_server.cpp index cf662c5..6809e97 100644 --- a/main/apps/app_server/app_server.cpp +++ b/main/apps/app_server/app_server.cpp @@ -1390,28 +1390,16 @@ esp_err_t app_server_init(void) strlcpy(g_dev_state.requested_mode, hal.settings.current_mode, sizeof(g_dev_state.requested_mode)); } - /* WiFi events — additional listener, does not own the WiFi lifecycle */ + /* WiFi events — additional listener, does not own the WiFi lifecycle. */ WiFi.onEvent([](WiFiEvent ev, void *data) { switch (ev) { case WiFiEvent::STA_GOT_IP: ESP_LOGI(TAG, ">>> STA GOT IP"); hal.statusEventSend(OPERATION_EVENT_STARTUP_SUCCESS); break; - case WiFiEvent::AP_STA_CONNECTED: { + case WiFiEvent::AP_STA_CONNECTED: ESP_LOGI(TAG, ">>> AP: station connected"); - esp_err_t err = mdns_init(); - if (err) { - printf("MDNS Init failed: %d\n", err); - break; - } - char device_name[sizeof(hal.settings.device_name)] = {0}; - hal.settingsLock(); - cstring_copy(device_name, hal.settings.device_name, sizeof(device_name)); - hal.settingsUnlock(); - mdns_hostname_set(device_name); - mdns_instance_name_set("PaperColor - Config Panel"); break; - } case WiFiEvent::AP_STA_DISCONNECTED: ESP_LOGI(TAG, ">>> AP: station leaved"); break; @@ -1449,6 +1437,36 @@ esp_err_t app_server_init(void) } httpd_register_err_handler(g_srv, HTTPD_404_NOT_FOUND, http_404_error_handler); + /* Initialize mDNS once at boot so the device is reachable as + * .local on any active interface. Previously this only + * ran inside the AP_STA_CONNECTED event handler, which meant mDNS was + * only initialized when a station joined the device's softAP — so in + * STA-only operation (or before any phone ever joined the AP) + * .local never resolved on the LAN. The mdns component + * subscribes to netif up/down events itself; calling mdns_init() once + * here is enough for both STA and AP traffic, and the hostname is + * already re-applied on rename from h_wifi_config. */ + { + esp_err_t merr = mdns_init(); + if (merr != ESP_OK) { + ESP_LOGW(TAG, "mdns_init failed: %s", esp_err_to_name(merr)); + } else { + char device_name[sizeof(hal.settings.device_name)] = {0}; + hal.settingsLock(); + cstring_copy(device_name, hal.settings.device_name, sizeof(device_name)); + hal.settingsUnlock(); + if (!device_name[0]) { + cstring_copy(device_name, "papercolor", sizeof(device_name)); + } + mdns_hostname_set(device_name); + mdns_instance_name_set("PaperColor - Config Panel"); + /* Advertise an HTTP service so Bonjour-aware clients (Finder's + * Network sidebar, dns-sd -B _http._tcp, etc.) discover the + * device without needing to know its hostname. */ + mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0); + } + } + /* ==== Captive Portal Handlers ==== */ // Reference: https://github.com/espressif/esp-idf/tree/v5.5/examples/protocols/http_server/captive_portal diff --git a/sdkconfig.defaults b/sdkconfig.defaults index e2755ce..bf0bbd2 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -72,6 +72,12 @@ CONFIG_WL_SECTOR_SIZE_4096=y CONFIG_TINYUSB_MSC_ENABLED=y CONFIG_TINYUSB_MSC_BUFSIZE=4096 CONFIG_TINYUSB_MSC_MOUNT_PATH="/data" +# hal_storage.cpp uses TINYUSB_EVENT_SUSPENDED / TINYUSB_EVENT_RESUMED +# unconditionally. esp_tinyusb >= 2.x gates those enum values behind these +# Kconfigs; without them the build fails with +# "TINYUSB_EVENT_SUSPENDED was not declared in this scope" +CONFIG_TINYUSB_SUSPEND_CALLBACK=y +CONFIG_TINYUSB_RESUME_CALLBACK=y # ===== I2C Bus ===== CONFIG_I2C_BUS_DYNAMIC_CONFIG=y @@ -81,5 +87,15 @@ CONFIG_I2C_MS_TO_WAIT=200 CONFIG_MDNS_MULTIPLE_INSTANCE=y CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# ===== LWIP ===== +# app_server.cpp configures httpd_config_t.max_open_sockets = 13. ESP-IDF's +# httpd validates this against (LWIP_MAX_SOCKETS - 3) because three sockets +# are reserved internally by the HTTP server. The IDF default is 10, which +# leaves only 7 available, so httpd_start() returns ESP_ERR_INVALID_ARG with: +# httpd: Config option max_open_sockets is too large (max allowed 7, ...) +# The HTTP server then never binds port 80 — captive portal and LAN web UI +# are both unreachable. +CONFIG_LWIP_MAX_SOCKETS=16 + # ===== Core Dump ===== CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y