Skip to content
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

mDNS doesn't work for AP when in WIFI_AP_STA mode #2602

Closed
MarcusWichelmann opened this issue Oct 12, 2016 · 19 comments
Closed

mDNS doesn't work for AP when in WIFI_AP_STA mode #2602

MarcusWichelmann opened this issue Oct 12, 2016 · 19 comments

Comments

@MarcusWichelmann
Copy link

MarcusWichelmann commented Oct 12, 2016

Basic Infos

Hardware

Hardware: ESP-12F
Core Version: 2.3.0 (From board-manager of Arduino IDE)

Description

Hi,

I'm running the ESP-12F in AP+Station mode, host a webserver on it and try to register a mDNS-Service to access the webserver using dslr-remote.local on both interfaces.
That way the ESP is connected to my home network and hosts an own wifi-network at the same time.

Station-IP: 192.168.3.33
AP-IP: 192.168.50.1

Access from computer via home network (through the station interface):
http://192.168.3.33 -> Works!
http://dslr-remote.local -> Works!

Access from iPhone connected to the AP of the ESP:
http://192.168.50.1 -> Works!
http://dslr-remote.local -> Cannot resolve address

I also tried to run MDNS.begin() twice for the IP-Addresses of both interfaces, but that didn't change anything.

After that I set the WIFI_AP mode instead, commented the whole station-related code out and tried again:

Access from iPhone connected to the AP of the ESP:
http://192.168.50.1 -> Works!
http://dslr-remote.local -> Works!

Is there any way to make mDNS working for the AP interface while in WIFI_AP_STA mode?
Is there anything wrong with my code or is that a bug..?

ESP8266WebServer webServer(80);

void setup()
{
    Serial.begin(115200);

    WiFi.mode(WIFI_AP_STA);
    WiFi.begin(WIFI_STATION_SSID, WIFI_STATION_KEY);
    while(WiFi.status() != WL_CONNECTED)
    {
        Serial.print(".");
        delay(300);
    }

    IPAddress apLocalIp(192, 168, 50, 1);
    IPAddress apSubnetMask(255, 255, 255, 0);
    WiFi.softAPConfig(apLocalIp, apLocalIp, apSubnetMask);
    WiFi.softAP(WIFI_AP_SSID, WIFI_AP_KEY);

    // Setup OTA, SPIFFS, webServer ...

    webServer.onNotFound([](){
        webServer.send(404, "text/plain", "File not found!");
    });
    webServer.begin();

    MDNS.begin(MDNS_NAME); // Return value was allways true while my tests
    MDNS.addService("http", "tcp", 80);
}

void loop()
{
    webServer.handleClient();
}

Settings in IDE

Module: Generic ESP8266 Module
Flash Size: 4M (3M SPIFFS)
CPU Frequency: 80Mhz
Flash Mode: DIO
Flash Frequency: 40Mhz
Upload Using: OTA & SERIAL
Reset Method: ck

@MarcusWichelmann
Copy link
Author

MarcusWichelmann commented Oct 12, 2016

I did some further experimenting:

I configured the ESP to use a static IP configuration that fits to my subnet-configuration at home now:

    IPAddress stationLocalIp(192, 168, 2, 2);
    IPAddress stationGatewayIp(192, 168, 0, 1);
    IPAddress stationSubnetMask(255, 255, 0, 0);
    WiFi.config(stationLocalIp, stationGatewayIp, stationSubnetMask);

And set the local IP on the AP-network to the same IP:

    IPAddress apLocalIp(192, 168, 2, 2);
    IPAddress apGatewayIp(192, 168, 2, 2);
    IPAddress apSubnetMask(255, 255, 255, 0);
    WiFi.softAPConfig(apLocalIp, apLocalIp, apSubnetMask);

I've done this with the intention to circumvent the need of hostnames and simply use the static ip 192.168.2.2 to reach the ESP in both networks.

Now I tried to reach the ESP using the hostnames just for fun again and now the PC (in the home network) cannot resolve the hostname anymore BUT now the iphone (connected to the AP of the ESP) can. That's really strange... :D

@SteveQuinn1
Copy link

I have exactly the same issue, slightly different circumstances.
I am using an ESP8266-01 as an IoT Temp/Humidity sensor. Network config details are stored in SPIFFs. When the device boots it starts in STA/AP mode and trys to connect to the network, if it connects it reverts to STA mode, if not it stays in STA/AP allowing some remote reconfig via a served up HTTP page, it then retries to connect.
If the SPIFFs file is corrupt or not present the device starts in AP mode and offers up the same HTTP page.
I've repeatedly tested each of the three modes. mDNS only works when the device is in AP mode, for STA/AP I need to use the AP assigned IP address 192.168.4.1 to access the HTTP page.
I'm assuming it's the 2.3.0 version core I have installed, though the library manager is reporting back 1.0.0, ESP8266 Built-In by Simon, Markus and Ivan,
I have Arduino IDE 1.6.9 installed.
And selected the following from Tools Menu
// Board: 'Generic ESP8266 Module'
// Flash Mode: 'DIO'
// Flash Frequency '40MHz'
// CPU Frequency '80 MHz'
// Flash Size: '1M (512KSPIFFS)'
// Debug Port: 'Disabled'
// Debug Level: 'None'
// Reset Method: 'ck'
// Upload Speed: '115200'

@me-no-dev
Copy link
Collaborator

The problem is a bit more complex :) Since we are talking about mDNS, we are talking about multicast service and multicast services are attached to given IP on given interface (AP or STA), I'm not positive that AP interface supports multicast but I will check. Regardless, if you change the configuration, mDNS will not attach to the new interface and it will not work. Maybe try restarting the service.

@SteveQuinn1
Copy link

Hi me-no-dev,

Thanks for the quick reply.

I've listed out below the sequence I follow for the case where the config file is present in SPIFFs but the target WiFi is turned off. So the sequence is;

  1. Boot device
  2. If SECURITY_PARAMETERS_FILE present
  3. Read SPIFFs NetworkSecurityParameters
  4. Start in AP/STA mode
  5. Configure MQTT client (I'm using Nick O'Leary's PubSubClient )
  6. Start HTTP server
  7. Start mDNS

In every occasion, only when WiFi.mode(WIFI_AP) is used will MDNS.begin(host) return true.

Forgive me if I have misinterpreted your reply, but do you advocate the following sequence;

WiFi.softAP((const char *)ap_network_ssid, (const char *)ap_network_password);
WiFi.begin((const char *)sta_network_ssid, (const char *)sta_network_password);
MDNS.begin(host);

Best Regards

SteveQuinn1

CODE SEGMENT BELOW;

In Setup
WiFi.mode(WIFI_OFF);

In Loop
if (SPIFFS.exists(SECURITY_PARAMETERS_FILE)) // Yes it does in this case
readNetworkSecurityParameters();
WiFi.mode(WIFI_AP_STA);
WiFi.begin((const char *)sta_network_ssid, (const char *)sta_network_password);
WiFi.encryptionType(ENC_TYPE_WEP);
WiFi.softAP((const char *)ap_network_ssid, (const char *)ap_network_password);

MQTTclient.setServer((const char *)mqtt_broker_ip, mqtt_broker_port);
MQTTclient.setCallback(callback);
server.on("/0", HTTP_GET, handleNetworkConfig);
server.onNotFound(handleNotFound);
server.begin();

if (MDNS.begin(host)) {
MDNS.addService("http", "tcp", 80);
#ifdef DEBUG_MDNS
Serial.println("MDNS responder started");
Serial.print("You can now connect to http://");
Serial.print(host);
Serial.println(".local");
#endif
} else {
#ifdef DEBUG_MDNS
Serial.println("MDNS responder failed to start");
#endif
}

@me-no-dev
Copy link
Collaborator

aah :) you are starting the services without waiting for WiFi to connect and assign IP :)

    WiFi.begin(STA_SSID, STA_PASS);
    if(WiFi.waitForConnectResult() != WL_CONNECTED){
        Serial.println("WiFi FAIL!!!");
        return;
    }

@SteveQuinn1
Copy link

Hi me-no-dev,

Ok, I think I know the question I need to ask.

I only require mDNS support on the AP side of the ESP8266, consequently is it possible to force/configure the mDNS server in the ESP8266 to bind only with the IP address of the AP when WiFi.mode() has been configured for either WIFI_AP or WIFI_AP_STA? In other words I do not want the mDNS service for the STA n/w connection. In this case it's only required for the AP side as it isn't possible to determine the AP IP address (ok, I know in all the literature, blog posts I've seen in respect of this issue they always indicate the ESP8266 AP IP address seems to default to 192.168.4.1), and wanted to use something along the lines of 'SENSOR.local' in my browser URL once connected to the AP only.

Best Regards

SteveQuinn1

@swarren
Copy link
Contributor

swarren commented Jan 15, 2017

#2864 should solve this issue.

@SteveQuinn1
Copy link

Thanks for the heads up,

Being new to github, how does one pick up the changes?

Best Regards

SteveQuinn1

@swarren
Copy link
Contributor

swarren commented Jan 16, 2017

@SteveQuinn1 you can get the code from https://github.com/swarren/esp8266-arduino/tree/mdns-multi-interface then you'll have to install the "git version" of the ESP8266 support libraries; the instructions to do this are in the README.md file of either the main project or my fork. Either that, or hopefully the patch will get applied soon and included in the next release, which you can obtain using the Arduino IDE board manager.

@SteveQuinn1
Copy link

SteveQuinn1 commented Jan 16, 2017 via email

@swarren
Copy link
Contributor

swarren commented Jan 17, 2017

BTW, it's merged now.

@MarcusWichelmann
Copy link
Author

Very cool!
Thank you, great work! 👍

Will try this the next time I've the ESP running.
I will close this issue if I could confirm whether it's fixed then.

@devyte
Copy link
Collaborator

devyte commented Oct 11, 2017

Relevant code is merged => closing.

@devyte devyte closed this as completed Oct 11, 2017
@kdeepakkumarbk
Copy link

kdeepakkumarbk commented Oct 25, 2017

Hi ,

I'm facing an similar issue. i tried the example ->esp8266mDNS->mDNS_Webserver. I noticed that i'm able to find mDNS (http://esp8266.local) response on only LINUX and Mac OS. Neither my windows PC or my android seems to find this mDNS name."http://esp8266.local ". ONLY when IP address is assigned (say : 192.168.0.10 ) I am able to connect to the esp web server through my android phone and windows PC. I even tried "ping esp8266.local" using run as administrator in windows but no respond.

can any one help me connect to server hosted in esp module using mDSN name through android devide and windows.

The example code used:

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

const char* ssid = `"............";`
const char* password = "..............";

// TCP server at port 80 will respond to HTTP requests
WiFiServer server(80);

void setup(void)
{  
  Serial.begin(115200);
  
  // Connect to WiFi network
  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());

  // Set up mDNS responder:
  // - first argument is the domain name, in this example
  //   the fully-qualified domain name is "esp8266.local"
  // - second argument is the IP address to advertise
  //   we send our IP address on the WiFi network
  if (!MDNS.begin("esp8266")) {
    Serial.println("Error setting up MDNS responder!");
    while(1) { 
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");
  
  // Start TCP (HTTP) server
  server.begin();
  Serial.println("TCP server started");
  
  // Add service to MDNS-SD
  MDNS.addService("http", "tcp", 80);
}

void loop(void)
{
  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  Serial.println("");
  Serial.println("New client");

  // Wait for data from client to become available
  while(client.connected() && !client.available()){
    delay(1);
  }
  
  // Read the first line of HTTP request
  String req = client.readStringUntil('\r');
  
  // First line of HTTP request looks like "GET /path HTTP/1.1"
  // Retrieve the "/path" part by finding the spaces
  int addr_start = req.indexOf(' ');
  int addr_end = req.indexOf(' ', addr_start + 1);
  if (addr_start == -1 || addr_end == -1) {
    Serial.print("Invalid request: ");
    Serial.println(req);
    return;
  }
  req = req.substring(addr_start + 1, addr_end);
  Serial.print("Request: ");
  Serial.println(req);
  client.flush();
  
  String s;
  if (req == "/")
  {
    IPAddress ip = WiFi.localIP();
    String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
    s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP8266 at ";
    s += ipStr;
    s += "</html>\r\n\r\n";
    Serial.println("Sending 200");
  }
  else
  {
    s = "HTTP/1.1 404 Not Found\r\n\r\n";
    Serial.println("Sending 404");
  }
  client.print(s);
  
  Serial.println("Done with client");
}

@swarren
Copy link
Contributor

swarren commented Oct 25, 2017

@kdeepakkumarbk,

Android doesn't support mDNS at all. There are a few 3rd-party applications that implement mDNS queries, although they don't allow *.local names to work in other applications. An application that I've used is "Pea Finder".

IIRC, (some versions of?) Windows don't/doesn't natively support mDNS either. You may need to install Apple's Bonjour software for this to work.

@IanAber
Copy link

IanAber commented Feb 23, 2018

I am trying to add mDNS support to my project. I can get the ESP8266 to report to my Mac once but if you leave it foe a few minutes and try again the ESP will not respond again unless you reset it. I am using the same code as the Sming example UdpServer_mDNS which also exhibits the same behaviour.

@daspuru
Copy link

daspuru commented Aug 1, 2018

Hi all, I am having the same problem, the mDNS service is announced, but after some minutes disappears, and there is no way to announce the service again until I reset the device. I tried first with the AT command for MDNS, and then programming directly to the ESP8266 and in both cases, with all code combinations I have tried, the behavior is the same. Anyone here has been able to announce services when the device is on without disappearing?

Thanks!

@aramperez
Copy link

Has this issue really been resolved? I still having and I just installed the 2.5.0-beta3 version of esp8266. I'm using a NodeMCU board. Thanks!

/Aram

@papadenis
Copy link

papadenis commented Aug 7, 2020

Try this, it worked for me. Tested on pair of two ESPs: client and server.

Server's part:

#include <DNSServer.h>
...
#define MY_AP ap
AsyncWebServer server(80);
DNSServer dnsServer;
...
IPAddress softAP_ip = WiFi.softAPIP();

dnsServer.start(53, "*", softAP_ip);

if (MDNS.begin(MY_AP))
        Serial.printf("MDNS responder started:\n%s.local\n", MY_AP);

server.begin();
MDNS.addService("http", "tcp", 80);

Client's part:

ap_server = find_ap_ip(MY_AP);
...
String find_ap_ip(String local_name) {
    // in general, this is a crutch that corrects the fact that mDNS local names
    // are not directly found by applications

    String found_ap = "none";
    int nrOfServices = MDNS.queryService("http", "tcp");

    if (nrOfServices == 0)
        Serial.println("No services were found");
    else {
        for (int i = 0; i<nrOfServices || found_ap==local_name; i++) {
            if (MDNS.hostname(i) == local_name)
                found_ap = MDNS.IP(i).toString();
        }
    }
    return found_ap;
}

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

10 participants