Reputation: 631
I have my local webserver that has mDNS - http://android.local:8182 I want to use it with ESP8266 by using HTTPClient class from ESP8266HTTPClient library. Code goes like this:
HTTPClient http;
http.begin("http://android.local:8182");
http.addHeader("values.json", "text/json");
int code = http.POST(jsonStr);
Log(DATA, "HTTP code: " + String(code));
Log(DATA, "Response: " + http.getString());
But it always returns -1 code. When I literally copy paste the url into my pc web browser, it works. I tried to replace "android.local" with IP address of my server and it worked, but not with mDNS address. Can someone tell me how to get it working properly?
Upvotes: 1
Views: 6834
Reputation: 7069
Windows, macOS and Linux all run on much more capable computers than the ESP8266. While regular DNS and mDNS are almost the same protocol, they're used differently and are implemented separately. In fact, it's common for Windows and Linux to not support mDNS without installing additional software ("Bonjour" under Windows and "avahi" under Linux).
There are two ways you can approach this on the ESP8266 with the Arduino SDK.
Either way you'll need to resolve android.local
to its IP address and then rewrite the URL to include the IP address instead of the hostname.
Unfortunately, the ESP8266 mDNS library doesn't support direct hostname to IP address resolution, so this is going to be a little contorted.
First way: if the device which is advertising android.local
offers an mDNS service record for "http", "tcp", and provides the IP address and port number (8182) in the advertisement, then you can look up the service record using the ESP8266mDNS library.
Your code would look something like this:
// your other necessary #include's first
#include <ESP8266mDNS.h>
#define HOSTNAME "the name of this ESP8266"
#define TARGET_HOSTNAME "android"
bool resolve_mdns_service(char* service_name, char* protocol, char* desired_host, IPAddress* ip_addr, uint16_t *port_number) {
Serial.println("Sending mDNS query");
int n = MDNS.queryService(service_name, protocol);
Serial.printf("mDNS query got %d results\n", n);
if(n == 0) {
Serial.println("no services found");
} else {
for (int i = 0; i < n; ++i) {
#ifdef DEBUG
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i));
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
#endif
if(strcmp(MDNS.hostname(i).c_str(), desired_host) == 0) {
*ip_addr = MDNS.IP(i);
*port_number = MDNS.port(i);
return true;
}
}
}
return false;
}
void setup() {
// get WiFi setup first
if(!MDNS.begin(HOSTNAME))
Serial.println("Error setting up MDNS responder!");
else
Serial.println("mDNS responder started");
IPAddress server_ip;
uint16_t port_number;
if(resolve_mdns_service("http", "tcp", TARGET_HOSTNAME, &server_ip, &port_number)) {
Serial.printf("got an answer for %s.local!\n", TARGET_HOSTNAME);
Serial.println(server_ip);
Serial.println(port_number);
} else {
Serial.printf("Sorry, %s.local not found\n", TARGET_HOSTNAME);
}
}
This will only work if your device advertises an "http", "tcp" mDNS service record.
If it doesn't, your best recourse is to use a third party library.
In that case, you'll want to follow the directions to install this library in your project:
https://github.com/madpilot/mDNSResolver
Your code will look something like this:
// your other necessary #include's first
#include <mDNSResolver.h>
#define TARGET_HOSTNAME "android"
WiFiUDP udp;
mDNSResolver::Resolver resolver(udp);
void setup() {
// get WiFi setup first
Serial.printf("Attempting to resolve %s\n", TARGET_HOSTNAME);
IPAddress answer = resolver.search(TARGET_HOSTNAME);
if(answer == IPADDR_NONE) {
Serial.println("no answer found");
} else {
Serial.println("Gotta result!");
Serial.println(answer);
}
}
The first method needs more code but doesn't require an external 3rd party library, and won't work in all cases.
Once you have the IP address you can use it to put together the URL you pass to http.begin()
and continue from there.
mDNS is an "unreliable" protocol - it doesn't guarantee you'll get an answer, or all the answers. So if you define DEBUG
in the first method, you may see slightly different sets of results each time through. And if your code fails to resolve the hostname, you might want to retry 2-3 times before giving up.
Upvotes: 4