4747#if defined(WS_DATA_FEATURE)
4848#include " ../websocket/websocket_server.h"
4949#endif // WS_DATA_FEATURE
50+ #include " ../../core/esp3d_hal.h"
51+ #include " ../../core/esp3d_string.h"
52+ #if defined(FILESYSTEM_FEATURE)
53+ #include " ../filesystem/esp_filesystem.h"
54+ #endif // FILESYSTEM_FEATURE
55+ #if defined(NOTIFICATION_FEATURE)
56+ #include " ../notifications/notifications_service.h"
57+ #endif // NOTIFICATION_FEATURE
58+ #if defined(CAMERA_DEVICE)
59+ #include " ../camera/camera.h"
60+ #endif // CAMERA_DEVICE
61+ #if defined(BLUETOOTH_FEATURE)
62+ #include " ../bluetooth/BT_service.h"
63+ #endif // BLUETOOTH_FEATURE
64+ #if defined(SENSOR_DEVICE)
65+ #include " ../sensor/sensor.h"
66+ #endif // SENSOR_DEVICE
67+ #if defined(TIMESTAMP_FEATURE)
68+ #include " ../time/time_service.h"
69+ #endif // TIMESTAMP_FEATURE
70+ // Helper: addServiceTxt with bool return on ESP32 (const char* overload returns void)
71+ // On ESP8266 addServiceTxt also returns void, so we always return true there.
72+ static bool esp3d_mdns_add_txt (const char * svc, const char * proto,
73+ const char * key, const char * val) {
74+ #if defined(ARDUINO_ARCH_ESP32)
75+ return MDNS .addServiceTxt ((char *)svc, (char *)proto, (char *)key, (char *)val);
76+ #else
77+ MDNS .addServiceTxt (svc, proto, key, val);
78+ return true ;
79+ #endif
80+ }
81+
5082mDNS_Service esp3d_mDNS;
5183
5284#define MDNS_SERVICE_NAME " esp3d"
5385#define MDNS_SERVICE_TYPE " tcp"
86+ #define MDNS_DEVICE_INFO_SERVICE " device-info"
5487
5588mDNS_Service::mDNS_Service () {
5689 _started = false ;
@@ -136,6 +169,10 @@ void mDNS_Service::end() {
136169 esp3d_log_e (" failed" );
137170 }
138171#endif // WS_DATA_FEATURE
172+ if (!MDNS .removeService (_hostname.c_str (), MDNS_DEVICE_INFO_SERVICE ,
173+ MDNS_SERVICE_TYPE )) {
174+ esp3d_log_e (" failed" );
175+ }
139176#endif // ARDUINO_ARCH_ESP8266
140177#if defined(ARDUINO_ARCH_ESP32)
141178 mdns_service_remove (" _" MDNS_SERVICE_NAME , " _" MDNS_SERVICE_TYPE );
@@ -154,6 +191,7 @@ void mDNS_Service::end() {
154191#if defined(WS_DATA_FEATURE)
155192 mdns_service_remove (" _websocket" , " _tcp" );
156193#endif // WS_DATA_FEATURE
194+ mdns_service_remove (" _" MDNS_DEVICE_INFO_SERVICE , " _" MDNS_SERVICE_TYPE );
157195#endif // ARDUINO_ARCH_ESP32
158196 MDNS .end ();
159197 _hostname = " " ;
@@ -167,32 +205,262 @@ void MDNSServiceQueryCallback(MDNSResponder::MDNSServiceInfo serviceInfo,
167205 bool p_bSetContent) {}
168206#endif // ARDUINO_ARCH_ESP8266
169207void mDNS_Service::addESP3DServices (uint16_t port) {
208+ // Port 0 means auto-detect: first active service port will be used.
209+ // Note: the ESP Arduino mDNS stack rejects port 0 at service registration
210+ // (addService returns false), even though DNS-SD standard allows it.
170211 _port = port;
171212 if (WiFi.getMode () == WIFI_AP ) {
172213 return ;
173214 }
174- MDNS .addService (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , _port);
175- MDNS .addServiceTxt (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , " firmware" ,
176- ESP3D_CODE_BASE );
177- MDNS .addServiceTxt (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , " version" ,
178- FW_VERSION );
215+ // Register individual services first, capturing the first available port
179216#if defined(HTTP_FEATURE)
180217 MDNS .addService (" http" , " tcp" , HTTP_Server::port ());
218+ if (_port == 0 ) _port = HTTP_Server::port ();
181219#endif // HTTP_FEATURE
182220#if defined(FTP_FEATURE)
183221 MDNS .addService (" ftp" , " tcp" , ftp_server.ctrlport ());
222+ if (_port == 0 ) _port = ftp_server.ctrlport ();
184223#endif // FTP_FEATURE
185224#if defined(TELNET_FEATURE)
186225 MDNS .addService (" telnet" , " tcp" , telnet_server.port ());
226+ if (_port == 0 ) _port = telnet_server.port ();
187227#endif // TELNET_FEATURE
188228#if defined(WEBDAV_FEATURE)
189229 MDNS .addService (" webdav" , " tcp" , webdav_server.port ());
230+ if (_port == 0 ) _port = webdav_server.port ();
190231#endif // WEBDAV_FEATURE
191232#if defined(WS_DATA_FEATURE)
192233 MDNS .addService (" websocket" , " tcp" , websocket_data_server.port ());
193- MDNS .addServiceTxt (" websocket" , " tcp" , " uri" , " /" );
194- MDNS .addServiceTxt (" websocket" , " tcp" , " subprotocol" , " arduino" );
234+ if (!esp3d_mdns_add_txt (" websocket" , " tcp" , " uri" , " /" )) {
235+ esp3d_log_e (" Failed to add TXT websocket/uri" );
236+ }
237+ if (!esp3d_mdns_add_txt (" websocket" , " tcp" , " subprotocol" , " arduino" )) {
238+ esp3d_log_e (" Failed to add TXT websocket/subprotocol" );
239+ }
240+ if (_port == 0 ) _port = websocket_data_server.port ();
195241#endif // WS_DATA_FEATURE
242+ // No active service found - register esp3d and device-info with 8080
243+ if (_port == 0 ) {
244+ _port = 8080 ;
245+ esp3d_log (" No active service port, using 8080 for esp3d and device-info registration" );
246+ }
247+ // Main esp3d service (port = first active service port)
248+ MDNS .addService (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , _port);
249+ if (!esp3d_mdns_add_txt (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , " firmware" ,
250+ ESP3D_CODE_BASE )) {
251+ esp3d_log_e (" Failed to add TXT firmware" );
252+ }
253+ if (!esp3d_mdns_add_txt (MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , " version" ,
254+ FW_VERSION )) {
255+ esp3d_log_e (" Failed to add TXT version" );
256+ }
257+ // Device info service - ESP8266 version: minimal records only to avoid OOM.
258+ // The mDNS parser needs heap to process incoming packets; too many TXT records
259+ // exhaust it and cause crashes.
260+ #if defined(ARDUINO_ARCH_ESP8266)
261+ if (MDNS .addService (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , _port)) {
262+ esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " board" ,
263+ ESP3DSettings::TargetBoard ());
264+ } else {
265+ esp3d_log_e (" Failed to add service " MDNS_DEVICE_INFO_SERVICE );
266+ }
267+ #else
268+ // Device info service - device identification and capabilities
269+ if (!MDNS .addService (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , _port)) {
270+ esp3d_log_e (" Failed to add service " MDNS_DEVICE_INFO_SERVICE );
271+ return ;
272+ }
273+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " name" ,
274+ _hostname.c_str ())) {
275+ esp3d_log_e (" Failed to add TXT name" );
276+ }
277+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " board" ,
278+ ESP3DSettings::TargetBoard ())) {
279+ esp3d_log_e (" Failed to add TXT board" );
280+ }
281+ #if defined(ARDUINO_ARCH_ESP32)
282+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " chip" ,
283+ ESP .getChipModel ())) {
284+ esp3d_log_e (" Failed to add TXT chip" );
285+ }
286+ #endif // ARDUINO_ARCH_ESP32
287+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " fw" ,
288+ ESP3D_CODE_BASE )) {
289+ esp3d_log_e (" Failed to add TXT fw" );
290+ }
291+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " ver" ,
292+ FW_VERSION )) {
293+ esp3d_log_e (" Failed to add TXT ver" );
294+ }
295+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
296+ " target" ,
297+ ESP3DSettings::GetFirmwareTargetShortName ())) {
298+ esp3d_log_e (" Failed to add TXT target" );
299+ }
300+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " sdk" ,
301+ ESP .getSdkVersion ())) {
302+ esp3d_log_e (" Failed to add TXT sdk" );
303+ }
304+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " core" ,
305+ ESP3DHal::arduinoVersion ())) {
306+ esp3d_log_e (" Failed to add TXT core" );
307+ }
308+ {
309+ String s = esp3d_string::formatBytes (ESP .getFlashChipSize ());
310+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
311+ " flash" , s.c_str ())) {
312+ esp3d_log_e (" Failed to add TXT flash" );
313+ }
314+ }
315+ #if defined(ARDUINO_ARCH_ESP32) && defined(BOARD_HAS_PSRAM)
316+ {
317+ String s = esp3d_string::formatBytes (ESP .getPsramSize ());
318+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
319+ " psram" , s.c_str ())) {
320+ esp3d_log_e (" Failed to add TXT psram" );
321+ }
322+ }
323+ #endif // ARDUINO_ARCH_ESP32 && BOARD_HAS_PSRAM
324+ #if defined(FILESYSTEM_FEATURE)
325+ {
326+ String s = esp3d_string::formatBytes (ESP_FileSystem::totalBytes ());
327+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " fs" ,
328+ s.c_str ())) {
329+ esp3d_log_e (" Failed to add TXT fs" );
330+ }
331+ }
332+ #endif // FILESYSTEM_FEATURE
333+ #if defined(NOTIFICATION_FEATURE)
334+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
335+ " notification" ,
336+ notificationsservice.getTypeString ())) {
337+ esp3d_log_e (" Failed to add TXT notification" );
338+ }
339+ #endif // NOTIFICATION_FEATURE
340+ #if defined(CAMERA_DEVICE)
341+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
342+ " camera" , esp3d_camera.GetModelString ())) {
343+ esp3d_log_e (" Failed to add TXT camera" );
344+ }
345+ #endif // CAMERA_DEVICE
346+ #if defined(BLUETOOTH_FEATURE)
347+ {
348+ String btinfo = bt_service.hostname ();
349+ btinfo += " /" ;
350+ btinfo += BTService::macAddress ();
351+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " bt" ,
352+ btinfo.c_str ())) {
353+ esp3d_log_e (" Failed to add TXT bt" );
354+ }
355+ }
356+ #endif // BLUETOOTH_FEATURE
357+ #if defined(SENSOR_DEVICE)
358+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
359+ " sensor" , esp3d_sensor.GetCurrentModelString ())) {
360+ esp3d_log_e (" Failed to add TXT sensor" );
361+ }
362+ #endif // SENSOR_DEVICE
363+ #if defined(SD_UPDATE_FEATURE)
364+ if (!esp3d_mdns_add_txt (
365+ MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " sd-update" ,
366+ ESP3DSettings::readByte (ESP_SD_CHECK_UPDATE_AT_BOOT ) != 0 ? " ON"
367+ : " OFF" )) {
368+ esp3d_log_e (" Failed to add TXT sd-update" );
369+ }
370+ #endif // SD_UPDATE_FEATURE
371+ #if defined(WEB_UPDATE_FEATURE)
372+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE ,
373+ " web-update" , " enabled" )) {
374+ esp3d_log_e (" Failed to add TXT web-update" );
375+ }
376+ #endif // WEB_UPDATE_FEATURE
377+ #if defined(TIMESTAMP_FEATURE)
378+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " time" ,
379+ timeService.isInternetTime () ? " ntp" : " manual" )) {
380+ esp3d_log_e (" Failed to add TXT time" );
381+ }
382+ #endif // TIMESTAMP_FEATURE
383+ #if defined(SD_DEVICE)
384+ #if SD_DEVICE == ESP_SDIO
385+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " sd" ,
386+ " SDIO" )) {
387+ esp3d_log_e (" Failed to add TXT sd" );
388+ }
389+ #elif SD_DEVICE == ESP_SDFAT2
390+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " sd" ,
391+ " SPI-SdFat" )) {
392+ esp3d_log_e (" Failed to add TXT sd" );
393+ }
394+ #else
395+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " sd" ,
396+ " SPI" )) {
397+ esp3d_log_e (" Failed to add TXT sd" );
398+ }
399+ #endif
400+ #endif // SD_DEVICE
401+ #if defined(LUA_INTERPRETER_FEATURE)
402+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " lua" ,
403+ " enabled" )) {
404+ esp3d_log_e (" Failed to add TXT lua" );
405+ }
406+ #endif // LUA_INTERPRETER_FEATURE
407+ #if defined(USB_SERIAL_FEATURE)
408+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " usb" ,
409+ " enabled" )) {
410+ esp3d_log_e (" Failed to add TXT usb" );
411+ }
412+ #endif // USB_SERIAL_FEATURE
413+ #if defined(AUTHENTICATION_FEATURE)
414+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " auth" ,
415+ " enabled" )) {
416+ esp3d_log_e (" Failed to add TXT auth" );
417+ }
418+ #else
419+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " auth" ,
420+ " disabled" )) {
421+ esp3d_log_e (" Failed to add TXT auth" );
422+ }
423+ #endif // AUTHENTICATION_FEATURE
424+ #if defined(SSDP_FEATURE)
425+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " ssdp" ,
426+ " enabled" )) {
427+ esp3d_log_e (" Failed to add TXT ssdp" );
428+ }
429+ #endif // SSDP_FEATURE
430+ {
431+ String loginfo = " " ;
432+ #if defined(ESP_LOG_FEATURE)
433+ #if ESP_LOG_FEATURE == LOG_OUTPUT_SERIAL0
434+ loginfo = " serial0/" ;
435+ #elif ESP_LOG_FEATURE == LOG_OUTPUT_SERIAL1
436+ loginfo = " serial1/" ;
437+ #elif ESP_LOG_FEATURE == LOG_OUTPUT_SERIAL2
438+ loginfo = " serial2/" ;
439+ #elif ESP_LOG_FEATURE == LOG_OUTPUT_TELNET
440+ loginfo = " telnet/" ;
441+ #elif ESP_LOG_FEATURE == LOG_OUTPUT_WEBSOCKET
442+ loginfo = " websocket/" ;
443+ #else
444+ loginfo = " unknown/" ;
445+ #endif
446+ #if ESP3D_LOG_LEVEL == LOG_LEVEL_VERBOSE
447+ loginfo += " verbose" ;
448+ #elif ESP3D_LOG_LEVEL == LOG_LEVEL_DEBUG
449+ loginfo += " debug" ;
450+ #elif ESP3D_LOG_LEVEL == LOG_LEVEL_ERROR
451+ loginfo += " error" ;
452+ #else
453+ loginfo += " none" ;
454+ #endif
455+ #else
456+ loginfo = " none" ;
457+ #endif // ESP_LOG_FEATURE
458+ if (!esp3d_mdns_add_txt (MDNS_DEVICE_INFO_SERVICE , MDNS_SERVICE_TYPE , " log" ,
459+ loginfo.c_str ())) {
460+ esp3d_log_e (" Failed to add TXT log" );
461+ }
462+ }
463+ #endif // ARDUINO_ARCH_ESP8266 / else
196464#if defined(ARDUINO_ARCH_ESP8266)
197465 _hMDNSServiceQuery = MDNS .installServiceQuery (
198466 MDNS_SERVICE_NAME , MDNS_SERVICE_TYPE , MDNSServiceQueryCallback);
0 commit comments