esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
15.98k stars 13.34k forks source link

MDNS does not start during setup, if use With ArduinoOTA #7861

Open whakru opened 3 years ago

whakru commented 3 years ago

Platform

Settings in IDE

Problem Description

After enabling mdns during setup, ot does not work. Although the ip is available. If you reconnect (by its function) after losing the connection, it is available. Which looks weird.

Setup:

MCVE Sketch


Serial.println(F("WIFIConnectInternet() start"));  
WiFi.softAPdisconnect();
  if (WiFi.SSID() != "") {
    Serial.println(F("WiFi credentials set in flash, wiping them"));
    WiFi.disconnect(true);
  }
  if (WiFi.getAutoConnect()) {
    Serial.println(F("Disabling auto-connect"));
    WiFi.setAutoConnect(false);
  }
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
delay(100);

 byte tries = 11;
 String _ssid = jsonRead(configSetup, "ssid");
 String _password = jsonRead(configSetup, "password");
           if (_ssid == "" && _password == "") {
             WiFi.begin("null","null");
            }
            else {
              WiFi.begin(_ssid.c_str(), _password.c_str());
            }

  while (--tries && WiFi.status() != WL_CONNECTED) //ждем подключения.
  {
    Serial.print(".");
    yield();
    delay(1000);
  }

   if (WiFi.status() != WL_CONNECTED) {
    //не удалось....
    Serial.println(F("NO CONNECT ROUTER!\n"));
  } else {
    // удалось подключиться, говорим о подключении и выводим адрес IP
   connectMode=1;
    delay(150);
      if (!MDNS.begin(DNS_NAME,WiFi.localIP()))
      {
        Serial.printf("Cannot restart mDNS responder\n");
      }
      else
      {
        Serial.printf("mDNS responder Started, IP is: %s\n", WiFi.localIP().toString().c_str());
      }
      delay(150);
      MDNS.addService("http", "tcp", 80); 
      MDNS.addService("ws", "tcp", 81); 
  }

All right, he's connected:

13:18:14.591 -> WIFIConnectInternet() start
13:18:14.694 -> Disabling auto-connect
13:18:14.797 -> ......mDNS responder Started, IP is: 192.168.31.83

but DNS_NAME remains unavailable. Although 192.168.31.83 is available

I also use the connection check function, and if the connection is lost, it disables DNS and connects it when the connection is restored. After that, DNS_NAME works.

loop: CheckConnect();

void CheckConnect(){
    static int lastStatus = WiFi.status();

    if (WiFi.status() != WL_CONNECTED && lastStatus == WL_CONNECTED ){
    Serial.printf("Интернета нет...... OFF MDNS! \n"); 
      MDNS.end(); //завершаем.
     delay(150);
    }

 if (WiFi.status() == WL_CONNECTED && lastStatus != WL_CONNECTED ){ //если интернета небыло, и он появился:
      Serial.printf("Connected, IP is: %s\n", WiFi.localIP().toString().c_str());
      delay(150);
      Serial.printf("MDNS begin 1 \n"); 
      if (!MDNS.begin(DNS_NAME,WiFi.localIP())) //пытаемся запустить днс на новом ип.
      {
        Serial.printf("Cannot restart mDNS responder\n");
      }
      else
      {
      Serial.printf("mDNS responder restarted\n");
      }
      delay(50);
      Serial.printf("MDNS addService 2 \n"); 
      MDNS.addService("http", "tcp", 80); yield(); //запускаем сервисы.
      MDNS.addService("ws", "tcp", 81); yield(); 
      delay(150);
       }
    lastStatus = WiFi.status();
yield();
};

I specifically checked by turning off the Internet:

13:20:07.828 -> Интернета нет...... OFF MDNS! 
13:20:13.378 -> FreeHeap: 40504   -- Uptime: 00:02:00
13:20:18.574 -> Connected, IP is: 192.168.31.83
13:20:18.711 -> MDNS begin 1 
13:20:18.711 -> mDNS responder restarted
13:20:18.745 -> MDNS addService 2 

After that, the DNS works...

Pablo2048 commented 3 years ago

Your mCve is not Complete - do You call MDNS.update() in the loop() ? https://github.com/esp8266/Arduino/blob/27da34760b7f431cba5e4e69471777eaa3db283b/libraries/ESP8266mDNS/src/LEAmDNS.h#L494

whakru commented 3 years ago

do You call MDNS.update() in the loop() ?

Yes, I execute MDNS.update(); in loop

 void loop() {
  CheckConnect();
  MDNS.update();
  webSocket.loop();
 yield();
  server.handleClient();
  ArduinoOTA.handle();
 yield();
  effectsTick();
 wdtFeedGo();
}
Pablo2048 commented 3 years ago

Ok, so please create real MCVE which can be compiled and tested...

whakru commented 3 years ago

Ok, so please create real MCVE which can be compiled and tested...

I spent a lot of time searching, I found that this is affected by ArduinoOTA... With ArduinoOTA, MDN does not start from the first time. on 2.7.4, this worked perfectly. But on 3.0.0-dev no longer exists.

#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include "ArduinoOTA.h"
#include <WiFiClient.h>
#include <ESP8266mDNS.h>

ESP8266WebServer server(80);
MDNSResponder MDNS;

#define DNS_NAME "test"

// впишите сюда данные, соответствующие вашей сети: 
const char* ssid = "SSID";
const char* password = "PASS";

String webPage = "";

void setup(void){
  ESP.wdtEnable(WDTO_8S);

  webPage += "<h1>ESP8266 Web Server</h1><p>Socket #1 <a href=\"socket1On\"><button>ON</button></a>&nbsp;<a href=\"socket1Off\"><button>OFF</button></a></p>";
  webPage += "<p>Socket #2 <a href=\"socket2On\"><button>ON</button></a>&nbsp;<a href=\"socket2Off\"><button>OFF</button></a></p>";

  delay(1000);
  Serial.begin(115200);
  Serial.println("");

Serial.println(F("WIFIConnectInternet() start"));  
WiFi.softAPdisconnect();
  if (WiFi.SSID() != "") {
    Serial.println(F("WiFi credentials set in flash, wiping them"));
    WiFi.disconnect(true);
  }
  if (WiFi.getAutoConnect()) {
    Serial.println(F("Disabling auto-connect"));
    WiFi.setAutoConnect(false);
  }
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
delay(100);

 byte tries = 11;
 WiFi.begin(ssid,password);
  while (--tries && WiFi.status() != WL_CONNECTED) //ждем подключения.
  {
    Serial.print(".");
    yield();
    delay(1000);
  }

   if (WiFi.status() != WL_CONNECTED) {
    Serial.println(F("NO CONNECT ROUTER!\n"));     //не удалось.... 
  } else {
    // удалось подключиться, говорим о подключении и выводим адрес IP
      if (!MDNS.begin(DNS_NAME,WiFi.localIP()))
      {
       Serial.printf("Cannot start mDNS responder\n");
      }
      else
      {
       Serial.printf("mDNS responder Started, IP is: %s\n", WiFi.localIP().toString().c_str());
      }
      MDNS.addService("http", "tcp", 80); 
  }

  server.on("/", [](){
    server.send(200, "text/html", webPage);
  });

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

ArduinoOTA.onStart([]() {
    Serial.println("Start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("End Failed");
  });
  ArduinoOTA.begin();

  Serial.println(F("END SETUP"));  
}

void loop(){
  MDNS.update();
  server.handleClient();
  ArduinoOTA.handle();
}
Pablo2048 commented 3 years ago

It is another bug actually IMHO... I can confirm, that ArduinoOTA breaks MDNS hostname. I used slightly modified MCVE:

#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include "ArduinoOTA.h"
#include <WiFiClient.h>
#include <ESP8266mDNS.h>

ESP8266WebServer server(80);
MDNSResponder MDNS;

#define DNS_NAME "test"

const char* ssid = "SSID";
const char* password = "PASS";

const char WEB[] PROGMEM = R"=====(<h1>ESP8266 Web Server</h1><p>Socket #1 <a href="socket1On"><button>ON</button></a>&nbsp;<a href="socket1Off"><button>OFF</button></a></p>
<p>Socket #2 <a href="socket2On"><button>ON</button></a>&nbsp;<a href="socket2Off"><button>OFF</button></a></p>)=====";

void setup(void) {

    Serial.begin(115200);
    Serial.println();

    WiFi.persistent(false);
    WiFi.disconnect();
    delay(100);
    WiFi.mode(WIFI_STA);
    WiFi.setAutoReconnect(true);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(1000);
    }
    Serial.println();

    if (!MDNS.begin(DNS_NAME)) {
        Serial.println(F("Cannot start mDNS responder"));
    } else {
        Serial.printf_P(PSTR("mDNS responder Started, IP is: %s\n"), WiFi.localIP().toString().c_str());
    }
    MDNS.addService("http", "tcp", 80);

    server.on("/", []() {
        server.send_P(200, PSTR("text/html"), WEB);
    });

    server.begin();

    ArduinoOTA.begin();
    Serial.println(F("END SETUP"));
}

void loop() {

    MDNS.update();
    server.handleClient();
    ArduinoOTA.handle();
}

and found out that there is no test.local after AP association. Then I use Avahi zeroconf browser and end with: Snímek z 2021-02-06 09-46-20 So there is some device, named test and some device, named esp8266-0aca2a on the same IP address. Then I've looked into mDNS and found this https://github.com/esp8266/Arduino/blob/27da34760b7f431cba5e4e69471777eaa3db283b/libraries/ArduinoOTA/ArduinoOTA.cpp#L125 - it seems like ArduinoOTA overwrite MDNS Hostname. Please can anybody take a look and confirm this?

d-a-v commented 3 years ago

Can you try and pass false in the parameter on line 96 of your link ?

Pablo2048 commented 3 years ago

I can, but then there be no arduinoOTA capable device shown in the IDE imo, because this will not be called https://github.com/esp8266/Arduino/blob/27da34760b7f431cba5e4e69471777eaa3db283b/libraries/ArduinoOTA/ArduinoOTA.cpp#L130 Ill give it a try anyway...

Pablo2048 commented 3 years ago

Yes, now it pings to the test.local, but there is no test._arduino._tcp.local device on the network so the IDE is unable to locate it.

luc-github commented 3 years ago

I do not know if it helps, but I got same issue before, and I workaround using ArduinoOTA.setHostname(DNS_NAME); before ArduinoOTA.begin();

whakru commented 3 years ago

I do not now if it helps but I got same issue before and I workaround using ArduinoOTA.setHostname(DNS_NAME); before ArduinoOTA.begin();

I checked, it really works.

Pablo2048 commented 3 years ago

So what if we change https://github.com/esp8266/Arduino/blob/27da34760b7f431cba5e4e69471777eaa3db283b/libraries/ArduinoOTA/ArduinoOTA.cpp#L123-L133 into this:

#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS)
  if(_useMDNS) {
    if (!MDNS.isRunning()) {
      MDNS.begin(_hostname.c_str());
    }
    if (_password.length()) {
      MDNS.enableArduino(_port, true);
    } else {
      MDNS.enableArduino(_port);
    }
  }
#endif
fenyvesi commented 3 years ago

Arduino 1.8.12 ESP8266 core 2.7.0 mDNSDoes not work as the comments above and my experience show.