Программирование ARM ESP-IDF mDNS Fri, March 29 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

ESP-IDF mDNS Печать
Добавил(а) microsin   

mDNS это широковещательная служба (multicast UDP), которая используется для предоставления локально сетевой службы распознавания имен хоста.

mDNS устанавливается по умолчанию на большинстве операционных систем, или её библиотека доступна как отдельный пакет. На Mac OS она устанавливается по умолчанию, и называется Bonjour. Apple выпустила инсталлятор для Windows, который можно найти на страничке поддержки Apple. На Linux mDNS предоставляется avahi, и обычно устанавливается по умолчанию.

[Свойства mDNS]

hostname: имя устройства, которое будет оно будет отвечать. Если оно не установлено, то hostname будет прочитано из интерфейса. Пример: имя my-esp32 будет разрешаться в my-esp32.local.

default_instance: дружественное имя для вашего устройства, наподобие Jhon's ESP32 Thing. Если не установлено, то будет использоваться hostname.

Пример запуска mDNS для интерфейса STA, и установка hostname и default_instance:

void start_mdns_service()
{
   // Инициализация службы mDNS:
   esp_err_t err = mdns_init();
   if (err) {
      printf("MDNS Init failed: %d\n", err);
      return;
   }
 
   // Установка hostname:
   mdns_hostname_set("my-esp32");
   // Установка default instance:
   mdns_instance_name_set("Jhon's ESP32 Thing");
}

[Службы mDNS]

mDNS может предоставлять информацию о сетевых службах, которые предоставляет ваше устройство. Каждая служба определяется несколькими свойствами.

instance_name: дружественное имя для службы, наподобие Jhon's ESP32 Web Server. Если не определено, то будет использоваться default_instance.

service_type: (необходимое свойство) тип службы, добавленное с символом нижнего подчеркивания. Некоторые общие типы можно найти в [2].

proto: (необходимое свойство) протокол, на котором работает служба, символом нижнего подчеркивания. Пример: _tcp или _udp.

port: (необходимое свойство) сетевой порт, через который работает служба.

txt: {var, val} массив строк, используемый для определения вашей службы.

Пример добавления нескольких служб и различных свойств:

void add_mdns_services()
{
   // Добавление служб:
   mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0);
   mdns_service_add(NULL, "_arduino", "_tcp", 3232, NULL, 0);
   mdns_service_add(NULL, "_myservice", "_udp", 1234, NULL, 0);
 
   // ПРИМЕЧАНИЕ: службы должны быть сначала добавлены, чтобы можно было
   // установить их свойства.
   // Настройка пользовательского экземпляра web-сервера.
   mdns_service_instance_name_set("_http", "_tcp", "Jhon's ESP32 Web Server");
 
   mdns_txt_item_t serviceTxtData[3] = {
      {"board","{esp32}"},
      {"u","user"},
      {"p","password"}
   };
   // Установка данных txt для службы (освободит и заменит текущие данные):
   mdns_service_txt_set("_http", "_tcp", serviceTxtData, 3);
 
   // Изменение сетевого порта службы:
   mdns_service_port_set("_myservice", "_udp", 4321);
}

[mDNS Query]

mDNS предоставляет методы для браузинга служб и распознавания IP-адресов (IPv4/IPv6) хоста. Результаты возвращаются в виде связанного списка объектов mdns_result_t.

Пример распознавания IP хоста:

void resolve_mdns_host(const char * host_name)
{
   printf("Query A: %s.local", host_name);
 
   struct ip4_addr addr;
   addr.addr = 0;
 
   esp_err_t err = mdns_query_a(host_name, 2000,  &addr);
   if(err){
      if(err == ESP_ERR_NOT_FOUND){
         printf("Host was not found!");
         return;
      }
      printf("Query Failed");
      return;
   }
 
   printf(IPSTR, IP2STR(&addr));
}

Пример распознавания локальных служб:

static const char * if_str[] = {"STA", "AP", "ETH", "MAX"};
static const char * ip_protocol_str[] = {"V4", "V6", "MAX"};
 
void mdns_print_results(mdns_result_t * results)
{
   mdns_result_t * r = results;
   mdns_ip_addr_t * a = NULL;
   int i = 1, t;
 
   while(r){
      printf("%d: Interface: %s, Type: %s\n",
             i++, if_str[r->tcpip_if], ip_protocol_str[r->ip_protocol]);
      if(r->instance_name){
         printf("  PTR : %s\n", r->instance_name);
      }
      if(r->hostname){
         printf("  SRV : %s.local:%u\n", r->hostname, r->port);
      }
      if(r->txt_count){
         printf("  TXT : [%u] ", r->txt_count);
         for(t=0; t<r->txt_count; t++){
            printf("%s=%s; ", r->txt[t].key, r->txt[t].value);
         }
         printf("\n");
      }
      a = r->addr;
      while(a){
         if(a->addr.type == IPADDR_TYPE_V6){
            printf("  AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6));
         } else {
           printf("  A   : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4)));
         }
         a = a->next;
      }
      r = r->next;
   }
}
 
void find_mdns_service(const char * service_name, const char * proto)
{
   ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto);
 
   mdns_result_t * results = NULL;
   esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20,  &results);
   if(err){
      ESP_LOGE(TAG, "Query Failed");
      return;
   }
   if(!results){
      ESP_LOGW(TAG, "No results found!");
      return;
   }
 
   mdns_print_results(results);
   mdns_query_results_free(results);
}

Пример использования этих методов:

void my_app_some_method()
{
   // Поиск esp32-mdns.local:
   resolve_mdns_host("esp32-mdns");
 
   // Поиск серверов HTTP:
   find_mdns_service("_http", "_tcp");
   // ... или файловых серверов:
   find_mdns_service("_smb", "_tcp");           // общий доступ к файлам Windows
   find_mdns_service("_afpovertcp", "_tcp");    // общий доступ к файлам Apple
   find_mdns_service("_nfs", "_tcp");           // сервер NFS
   find_mdns_service("_ftp", "_tcp");           // сервер FTP
   // ... или сетевого принтера:
   find_mdns_service("_printer", "_tcp");
   find_mdns_service("_ipp", "_tcp");
}

[Оптимизация производительности]

Cкорость выполнения. mDNS создает задачу, и по делает это умолчанию с низким приоритетом 1 (опция CONFIG_MDNS_TASK_PRIORITY), если опция CONFIG_FREERTOS_UNICORE разрешена и прикреплена к CPU0 (CONFIG_MDNS_TASK_AFFINITY). Подробнее про оптимизацию скорости см. [3].

Использование RAM. mDNS создает задачи с размерами стека, сконфигурированным опцией CONFIG_MDNS_TASK_STACK_SIZE. Подробнее про оптимизацию использования ОЗУ см. [4].

Пример использования mDNS см. в папке examples репозитория mDNS [5].

[API mDNS]

Функция Описание
mdns_init Инициализирует mDNS на имеющемся интерфейсе.
mdns_free Остановит сервер DNS.
mdns_hostname_set Установит имя хоста для mDNS, которое необходимо, если вы собираетесь представлять службы хоста (advertise services).
mdns_delegate_hostname_add Добавит в базу данных сервера DNS сопоставление имени хоста (hostname) и его адреса (address) для удовлетворения запросов A/AAAA для имени хоста и служб, которые могут быть добавлены для этого хоста.
mdns_delegate_hostname_remove Удалит делегированное имя хоста. Также будет удалена информация всех его служб.
mdns_hostname_exists Запрашивает, было ли добавлено указанное имя хоста.
mdns_instance_name_set Установит имя по умолчанию для экземпляра (сервера mDNS?).
mdns_service_add Добавит службу на сервер mDNS.
mdns_service_add_for_host Добавит службу в базу данных сервера mDNS, связанную с делегированным именем хоста.
mdns_service_exists Проверяет, была ли добавлена служба для указанного имени хоста.
mdns_service_exists_with_instance Проверяет, была ли добавлена служба для указанного экземпляра хоста.
mdns_service_remove Удалит службу с сервера mDNS.
mdns_service_remove_for_host Удалит службу из базы данных сервера mDNS, связанную с именем хоста.
mdns_service_instance_name_set Установит имя экземпляра для службы.
mdns_service_instance_name_set_for_host Установит имя экземпляра для службы с именем хоста.
mdns_service_port_set Установит порт службы.
mdns_service_port_set_for_host Установит порт службы для хоста.
mdns_service_txt_set Заменит все элементы TXT для службы.
mdns_service_txt_set_for_host Заменит все элементы TXT службы для хоста.
mdns_service_txt_item_set Установит/добавит элемент TXT для записи TXT службы.
mdns_service_txt_item_set_with_explicit_value_len  Установит/добавит элемент TXT для записи TXT службы.
mdns_service_txt_item_set_for_host Установит/добавит элемент TXT для записи TXT службы указанного хоста.
mdns_service_txt_item_set_for_host_with_explicit_value_len Установит/добавит элемент TXT для записи TXT службы указанного хоста, с указанием длины текста.
mdns_service_txt_item_remove Удалит элемент TXT для записи TXT службы.
mdns_service_txt_item_remove_for_host Удалит элемент TXT для записи TXT службы указанного хоста.
mdns_service_subtype_add_for_host Добавит подтип для службы.
mdns_service_remove_all Удалит и освободит все службы из сервера mDNS.
mdns_query_async_delete Удалит и завершит запрос. Вызывайте эту функцию только после окончания поиска!
mdns_query_async_get_results Извлекает результаты по указателю поиска. Результаты доступны в виде указателя, возвращаемого из функции. Указатель на объект поиска должен быть удален вызовом mdns_query_async_delete, как только запрос завершится. Однако результаты должны быть освобождены вручную.
mdns_query_async_new Асинхронный запрос к mDNS для имени хоста или службы. Состояние прогресса поиска должно быть проверено, и поиск должен быть удален вручную!
mdns_query_generic Традиционный запрос mDNS. Все следующие методы являются производными из mdns_query_generic.
mdns_query Опрашивает mDNS для информации о хосте или службе. Обратите внимание, что что при запросе типов PTR отправляется многоадресный запрос (multicast query), все другие типы посылают одноадресные запросы (unicast query).
mdns_query_results_free Освободит результаты запроса.
mdns_query_srv Опрашивает mDNS для получения записи SRV.
mdns_query_txt Опрашивает mDNS для получения записи TXT.
mdns_query_a Опрашивает mDNS для получения записи A.
mdns_register_netif Регистрирует пользовательский esp_netif с функционалом mDNS, который по умолчанию запускается на предварительно сконфигурированных интерфейсах (STA, AP, ETH). Эта API-функция позволяет запустить службу на любом настроенном пользователем интерфейсе, либо с использованием стандартного драйвера WiFi или Ethernet, или любого другого вида драйвера, определенного пользователем.
mdns_unregister_netif Отменяет регистрацию esp-netif, который уже был зарегистрирован в службе mDNS.
mdns_netif_action Установит esp_netif в желаемое состояние, или выполнит желаемое действие, такое как разрешение/запрет этого интерфейса, или отправка пакетов оповещения в этот интерфейс. Подробнее см. [1].

Полное описание параметров и возвращаемых результатов из этих API-функций, а также связанных с ними макросов, перечислений и типов см. документацию [1].

[Ссылки]

1. ESP-IDF mDNS Service site:espressif.github.io.
2. DNS SRV (RFC 2782) Service Types site:dns-sd.org.
3. ESP-IDF Maximizing Execution Speed site:espressif.com.
4. ESP-IDF Minimizing RAM Usage site:espressif.com.
5. Репозиторий mDNS (espressif / esp-protocols).

 

Добавить комментарий


Защитный код
Обновить

Top of Page