ESP8266 - HTTPClient не работает при использовании локального адреса mDNS - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть локальный веб-сервер с mDNS - http://android.local:8182 Я хочу использовать его с ESP8266, используя класс HTTPClient из библиотеки ESP8266HTTPClient.Код выглядит так:

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());

Но он всегда возвращает -1 код.Когда я буквально копирую ссылку в мой веб-браузер, она работает.Я попытался заменить «android.local» на IP-адрес моего сервера, и это сработало, но не с адресом mDNS.Может кто-нибудь сказать мне, как заставить это работать должным образом?

1 Ответ

0 голосов
/ 23 сентября 2018

Windows, macOS и Linux работают на гораздо более мощных компьютерах, чем ESP8266.Хотя обычные DNS и mDNS являются практически одним и тем же протоколом, они используются по-разному и реализуются отдельно.Фактически, для Windows и Linux характерно не поддерживать mDNS без установки дополнительного программного обеспечения («Bonjour» под Windows и «avahi» под Linux).

Есть два способа достичь этого на ESP8266 с помощьюArduino SDK.

В любом случае вам потребуется разрешить android.local для его IP-адреса, а затем переписать URL-адрес, включив в него IP-адрес вместо имени хоста.

К сожалению, mDNS ESP8266библиотека не поддерживает прямое разрешение имени хоста для IP-адреса, поэтому это будет немного искажено.

Первый способ: если устройство, которое рекламирует android.local, предлагает запись службы mDNS для «http»,«tcp» и предоставляет IP-адрес и номер порта (8182) в объявлении, затем вы можете просмотреть служебную запись с помощью библиотеки ESP8266mDNS.

Ваш код будет выглядеть примерно так:

// 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);
  }
}

Это будет работать только в том случае, если ваше устройство объявляет служебную запись mDNS «http», «tcp».

Если этого не произойдет, лучше всегоСначала необходимо использовать стороннюю библиотеку.

В этом случае вам нужно будет следовать указаниям по установке этой библиотеки в вашем проекте:

https://github.com/madpilot/mDNSResolver

Ваш код будет выглядеть примерно так:

// 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);
  }
}

Первый метод требует больше кода, но не требует внешней сторонней библиотеки и не будет работать во всех случаях.

Один разу вас есть IP-адрес, который вы можете использовать, чтобы собрать URL-адрес, который вы передаете http.begin(), и продолжить с него.

mDNS - это «ненадежный» протокол - он не гарантирует, что вы получите ответили все ответы.Поэтому, если вы определите DEBUG в первом методе, вы можете каждый раз видеть несколько разные наборы результатов.И если ваш код не может разрешить имя хоста, вы можете повторить попытку 2-3 раза, прежде чем отказаться.

...