Skip to content

mDNS in NodeMCU #8912

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
3 of 6 tasks
silasalves opened this issue Apr 22, 2023 · 4 comments
Open
3 of 6 tasks

mDNS in NodeMCU #8912

silasalves opened this issue Apr 22, 2023 · 4 comments

Comments

@silasalves
Copy link

silasalves commented Apr 22, 2023

Basic Infos

  • This issue complies with the issue POLICY doc.
  • I have read the documentation at readthedocs and the issue is not addressed there.
  • I have tested that the issue is present in current master branch (aka latest git).
  • I have searched the issue tracker for a similar issue.
  • If there is a stack dump, I have decoded it.
  • I have filled out all fields below.

Platform

  • Hardware: ESP8266
  • Core Version: 3.1.2
  • Development Env: Arduino IDE 2.1.0
  • Operating System: Windows

Settings in IDE

  • Module: Nodemcu|other
  • Flash Mode: ? (couldn't find)
  • Flash Size: 4MB
  • lwip Variant: v2 Lower Memory
  • Reset Method: nodemcu
  • Flash Frequency: 40Mhz
  • CPU Frequency: 80Mhz and 160MHz
  • Upload Using: SERIAL
  • Upload Speed: 115200 and 460800

Problem Description

None of the mDNS samples work for me. I can connect through the IP address, but I am not able to find the device using mDNS.

The sample that works the "best" so far is the HelloServer. After it connects and prints

.......
Connected to Network
IP address: 192.168.50.43
MDNS responder started
HTTP server started

I start pinging esp8266.local and it works once, but then it stops working:

PS C:\Users\silas> ping esp8266.local
Ping request could not find host esp8266.local. Please check the name and try again.
PS C:\Users\silas> ping esp8266.local

Pinging esp8266.local [192.168.50.43] with 32 bytes of data:
Reply from 192.168.50.43: bytes=32 time=491ms TTL=255
Reply from 192.168.50.43: bytes=32 time=88ms TTL=255
Reply from 192.168.50.43: bytes=32 time=769ms TTL=255
Reply from 192.168.50.43: bytes=32 time=214ms TTL=255

Ping statistics for 192.168.50.43:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 88ms, Maximum = 769ms, Average = 390ms
PS C:\Users\silas> ping esp8266.local
Ping request could not find host esp8266.local. Please check the name and try again.
PS C:\Users\silas> ping esp8266.local
Ping request could not find host esp8266.local. Please check the name and try again.

I didn't do any changes to the sample code (other than the network data) and I couldn't find anyone with a solution to this problem either.

Any ideas of what could be preventing MDNS from working after the first time? I am not using OTA and I am erasing all flash contents.

I am pasting the sample code for completion:

MCVE Sketch

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

#ifndef STASSID
#define STASSID "..."
#define STAPSK "..."
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

ESP8266WebServer server(80);

const int led = 13;

void handleRoot() {
  digitalWrite(led, 1);
  server.send(200, "text/plain", "hello from esp8266!\r\n");
  digitalWrite(led, 0);
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; }
  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}

void setup(void) {
  pinMode(led, OUTPUT);
  digitalWrite(led, 0);
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started"); }

  server.on("/", handleRoot);

  server.on("/inline", []() {
    server.send(200, "text/plain", "this works as well");
  });

  server.on("/gif", []() {
    static const uint8_t gif[] PROGMEM = {
      0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80, 0x01,
      0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x2c, 0x00, 0x00, 0x00, 0x00,
      0x10, 0x00, 0x10, 0x00, 0x00, 0x02, 0x19, 0x8c, 0x8f, 0xa9, 0xcb, 0x9d,
      0x00, 0x5f, 0x74, 0xb4, 0x56, 0xb0, 0xb0, 0xd2, 0xf2, 0x35, 0x1e, 0x4c,
      0x0c, 0x24, 0x5a, 0xe6, 0x89, 0xa6, 0x4d, 0x01, 0x00, 0x3b
    };
    char gif_colored[sizeof(gif)];
    memcpy_P(gif_colored, gif, sizeof(gif));
    // Set the background to a random set of colors
    gif_colored[16] = millis() % 256;
    gif_colored[17] = millis() % 256;
    gif_colored[18] = millis() % 256;
    server.send(200, "image/gif", gif_colored, sizeof(gif_colored));
  });

  server.onNotFound(handleNotFound);

  /////////////////////////////////////////////////////////
  // Hook examples

  server.addHook([](const String& method, const String& url, WiFiClient* client, ESP8266WebServer::ContentTypeFunction contentType) {
    (void)method;       // GET, PUT, ...
    (void)url;          // example: /root/myfile.html
    (void)client;       // the webserver tcp client connection
    (void)contentType;  // contentType(".html") => "text/html"
    Serial.printf("A useless web hook has passed\n");
    Serial.printf("(this hook is in 0x%08x area (401x=IRAM 402x=FLASH))\n", esp_get_program_counter());
    return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
  });

  server.addHook([](const String&, const String& url, WiFiClient*, ESP8266WebServer::ContentTypeFunction) {
    if (url.startsWith("/fail")) {
      Serial.printf("An always failing web hook has been triggered\n");
      return ESP8266WebServer::CLIENT_MUST_STOP;
    }
    return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
  });

  server.addHook([](const String&, const String& url, WiFiClient* client, ESP8266WebServer::ContentTypeFunction) {
    if (url.startsWith("/dump")) {
      Serial.printf("The dumper web hook is on the run\n");

      // Here the request is not interpreted, so we cannot for sure
      // swallow the exact amount matching the full request+content,
      // hence the tcp connection cannot be handled anymore by the
      // webserver.
#ifdef STREAMSEND_API
      // we are lucky
      client->sendAll(Serial, 500);
#else
      auto last = millis();
      while ((millis() - last) < 500) {
        char buf[32];
        size_t len = client->read((uint8_t*)buf, sizeof(buf));
        if (len > 0) {
          Serial.printf("(<%d> chars)", (int)len);
          Serial.write(buf, len);
          last = millis();
        }
      }
#endif
      // Two choices: return MUST STOP and webserver will close it
      //                       (we already have the example with '/fail' hook)
      // or                  IS GIVEN and webserver will forget it
      // trying with IS GIVEN and storing it on a dumb WiFiClient.
      // check the client connection: it should not immediately be closed
      // (make another '/dump' one to close the first)
      Serial.printf("\nTelling server to forget this connection\n");
      static WiFiClient forgetme = *client;  // stop previous one if present and transfer client refcounter
      return ESP8266WebServer::CLIENT_IS_GIVEN;
    }
    return ESP8266WebServer::CLIENT_REQUEST_CAN_CONTINUE;
  });

  // Hook examples
  /////////////////////////////////////////////////////////

  server.begin();
  Serial.println("HTTP server started");
}

void loop(void) {
  server.handleClient();
  MDNS.update();
}

@mcspr
Copy link
Collaborator

mcspr commented Apr 22, 2023

Latency always that high?

Reply from 192.168.50.43: bytes=32 time=491ms TTL=255
Reply from 192.168.50.43: bytes=32 time=88ms TTL=255
Reply from 192.168.50.43: bytes=32 time=769ms TTL=255
Reply from 192.168.50.43: bytes=32 time=214ms TTL=255

Any difference when dealing with DNS client directly?

> Resolve-DnsName -llmnronly ESP-4A2914.local

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
ESP-4A2914.local                               A      120   Answer     10.10.10.137

(check out get-help resolve-dnsname and dnsmodule docs)

afaik we are dealing with multicast replies; looking at ping, there is a single query. PS cmdlet sends out more than one, thus also receiving more than one reply (with consideration that it might miss some requests in the process)

@silasalves
Copy link
Author

silasalves commented Apr 23, 2023

@mcspr Thanks for the response! I think I found a solution, so I am detailing it here.

Latency always that high?

I am afraid so... I placed the device close to the router and ran the ping command again. This is the result:

> ping esp8266.local -n 30

Pinging esp8266.local [192.168.50.43] with 32 bytes of data:
Reply from 192.168.50.43: bytes=32 time=289ms TTL=255
Reply from 192.168.50.43: bytes=32 time=270ms TTL=255
Reply from 192.168.50.43: bytes=32 time=1259ms TTL=255
Reply from 192.168.50.43: bytes=32 time=4ms TTL=255
Reply from 192.168.50.43: bytes=32 time=640ms TTL=255
Reply from 192.168.50.43: bytes=32 time=5ms TTL=255
Reply from 192.168.50.43: bytes=32 time=149ms TTL=255
Reply from 192.168.50.43: bytes=32 time=60ms TTL=255
Reply from 192.168.50.43: bytes=32 time=274ms TTL=255
Reply from 192.168.50.43: bytes=32 time=185ms TTL=255
Reply from 192.168.50.43: bytes=32 time=99ms TTL=255
Reply from 192.168.50.43: bytes=32 time=308ms TTL=255
Reply from 192.168.50.43: bytes=32 time=212ms TTL=255
Reply from 192.168.50.43: bytes=32 time=126ms TTL=255
Reply from 192.168.50.43: bytes=32 time=46ms TTL=255
Reply from 192.168.50.43: bytes=32 time=254ms TTL=255
Reply from 192.168.50.43: bytes=32 time=167ms TTL=255
Reply from 192.168.50.43: bytes=32 time=73ms TTL=255
Reply from 192.168.50.43: bytes=32 time=282ms TTL=255
Reply from 192.168.50.43: bytes=32 time=192ms TTL=255
Reply from 192.168.50.43: bytes=32 time=105ms TTL=255
Reply from 192.168.50.43: bytes=32 time=12ms TTL=255
Reply from 192.168.50.43: bytes=32 time=228ms TTL=255
Reply from 192.168.50.43: bytes=32 time=139ms TTL=255
Reply from 192.168.50.43: bytes=32 time=48ms TTL=255
Reply from 192.168.50.43: bytes=32 time=282ms TTL=255
Reply from 192.168.50.43: bytes=32 time=165ms TTL=255
Reply from 192.168.50.43: bytes=32 time=81ms TTL=255
Reply from 192.168.50.43: bytes=32 time=297ms TTL=255
Reply from 192.168.50.43: bytes=32 time=210ms TTL=255

Ping statistics for 192.168.50.43:
    Packets: Sent = 30, Received = 30, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 4ms, Maximum = 1259ms, Average = 215ms

Is there anything that can be done to improve this?


Any difference when dealing with DNS client directly?

Without any changes to the code, not really. It couldn't be found:

> Resolve-DnsName -llmnronly esp8266.local
Resolve-DnsName : esp8266.local : This operation returned because the timeout period expired
At line:1 char:1
+ Resolve-DnsName -llmnronly esp8266.local
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationTimeout: (esp8266.local:String) [Resolve-DnsName], Win32Exception
    + FullyQualifiedErrorId : ERROR_TIMEOUT,Microsoft.DnsClient.Commands.ResolveDnsName

What was bothering me is that the MDNS worked for a short while before stopping completely, so I decided to read the source code and see if there was anything there that could help me. That's how I found the bool MDNSResponder::announce(void) which seemed worth try using -- maybe MDNS was announcing just once and that is why it worked only once as well, who knows? Then I created a quick-and-dirty workaround to test this hypothesis.

First, I added this to the beginning of the file:

// counter used for delaying the call to MDNS.announce()
long int advertiseCounter = 0;

and then I changed the loop() function to:

void loop(void) {
  server.handleClient();
  MDNS.update();
  
  // call MDNS.announce() periodically when the counter exceeds the threshold, then resets the counter.
  if (advertiseCounter++ > 100000)
  {
    MDNS.announce();
    advertiseCounter = 0;
  }
}

And now I can find the device successfully on Windows =)

> Resolve-DnsName -llmnronly esp8266.local

Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
esp8266.local                                  A      120   Answer     192.168.50.43

Name      : 43.50.168.192.in-addr.arpa
QueryType : PTR
TTL       : 120
Section   : Answer
NameHost  : esp8266.local

The browser can also find it, so I think this issue is at least partially solved... And the reason for the "partial" is that although it works in Windows, it doesn't work at all with Android... On Windows it works whether I use http://esp8266.local or http://192.168.50.43; in Android, both fail, no matter the browser I am using (Firefox or Chrome). The phone just returns ERR_ADDRESS_UNREACHABLE and that's it. Any ideas? I wonder if it's related to the high latency.

@aromprg
Copy link

aromprg commented Apr 28, 2023

https://stackoverflow.com/questions/30449988/how-to-enable-mdns-support-in-android-browser-address-bar
Now mdns support avilable in android 12 or higher (I'm not tested)

@silasalves
Copy link
Author

https://stackoverflow.com/questions/30449988/how-to-enable-mdns-support-in-android-browser-address-bar Now mdns support avilable in android 12 or higher (I'm not tested)

It's not a MDNS error; it fails even when I use the IP itself. I will try with a different phone and see what happens.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants