567|0

274

帖子

2

TA的资源

纯净的硅(初级)

「玩ESP32开发板」mDNS实现设备发现功能(无需服务器嗅探设备) [复制链接]

mDNS(Multicast DNS)是一种多播域名系统协议,它允许设备在局域网内通过名称解析互相发现,而无需依赖中央DNS服务器。以下是对mDNS的详细介绍:

工作原理

  1. 多播查询:设备发送DNS查询请求到多播地址224.0.0.251:5353,请求解析局域网内的某个设备名称。

  2. 设备响应:拥有该名称的设备会响应查询,并提供自己的IP地址。

  3. 设备广播:设备启动时会广播自己的mDNS服务信息,包括设备名称、IP地址等。

  4. 定时更新:设备会定时重发mDNS广播消息,以保持设备间的连接状态。

协议特点

  • 无需中央DNS服务器:mDNS不依赖于中央DNS服务器,设备可以在没有配置DNS服务器的情况下,通过主机名进行相互发现。

  • 支持零配置网络:mDNS支持零配置网络(Zeroconf),设备无需手动配置就可以进行通信和发现。

  • 多播通信:mDNS使用多播地址224.0.0.251(IPv4)和FF02::FB(IPv6),以及UDP端口5353

应用场景

  • 智能家居:家庭智能设备通过mDNS广播自己的名字和服务信息,手机和电脑能够快速发现并与它们通信。

  • 文件和媒体共享:在macOS或Linux系统中,设备通过mDNS发现局域网中的共享文件夹、媒体服务器等服务。

  • 开发设备连接:树莓派等开发板通过mDNS注册名字,用户可以通过简单的名称(如raspberrypi.local)进行访问。

  • 打印机自动发现:通过mDNS协议,打印机可以广播自己的服务信息,使得用户可以方便地在网络中找到并连接打印机。


现实生活里,我们会接触到非常多使用mDNS的设备,例如摄像头、智能音箱、电视机 、打印机等等。如果是树莓派单板计算机,或者一些国产的单板计算机,一般都支持使用 主机名.local直接访问。像我之前经常刷的CircuitPython,也默认打开了mDNS功能,方便用户快速找到设备。

 

而esp idf的官方组件库里,也有mdns库。https://components.espressif.com/

image.png   第一个mdns就是了,然后我们可以在命令行使用 idf.py add-dependency "espressif/mdns^1.7.0"  这个指令把库添加到依赖里。

添加依赖之后,我们需要按下面步骤修改

image.png  

1、添加网络协议头文件依赖,修改idf_component.yml文件,添加以下内容

  protocol_examples_common:
    path: ${IDF_PATH}/examples/common_components/protocol_examples_common

添加这个之后,就不需要从idf目录里复制protocol_examples_common对应头文件了,这个头文件是esp idf很多使用了网络的案例用到的

2、从mDNS仓库里,复制Kconfig.projbuild目录过来,这个文件是配置mDNS相关的配置

3、复制案例文件到自己的源码文件里,这里懒得折腾了,直接复制到helloworld文件里。

复制完代码后,可以把多余的解析mDNS和注册多台设备的代码删除,然后打开menuconfig,配置好wifi信息

删除多余的代码后,其实可以看到整体的逻辑是非常简单的,初始化wifi后,就初始化mDNS功能,并注册对应的属性即可。

/*
 * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */

/*
 * MDNS-SD Query and advertise Example
*/
#include <string.h>
#include "esp_event.h"
#include "esp_log.h"
#include "mdns.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"

#define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE
#define EXAMPLE_BUTTON_GPIO   CONFIG_MDNS_BUTTON_GPIO

static const char *TAG = "mdns-test";
static char *generate_hostname(void);

static void initialise_mdns(void)
{
    char *hostname = generate_hostname();

    //initialize mDNS
    ESP_ERROR_CHECK( mdns_init() );
    //set mDNS hostname (required if you want to advertise services)
    ESP_ERROR_CHECK( mdns_hostname_set(hostname) );
    ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname);
    //set default mDNS instance name
    ESP_ERROR_CHECK( mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE) );

    //structure with TXT records
    mdns_txt_item_t serviceTxtData[3] = {
        {"board", "esp32"},
        {"u", "user"},
        {"p", "password"}
    };

    //initialize service
    ESP_ERROR_CHECK( mdns_service_add("ESP32-WebSocket", "_http", "_tcp", 80, serviceTxtData, 3) );

    //add another TXT item
    ESP_ERROR_CHECK( mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar") );
    //change TXT item value
    ESP_ERROR_CHECK( mdns_service_txt_item_set_with_explicit_value_len("_http", "_tcp", "u", "admin", strlen("admin")) );
    free(hostname);
}

void app_main(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    initialise_mdns();

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

#if defined(CONFIG_MDNS_ADD_CUSTOM_NETIF) && !defined(CONFIG_MDNS_PREDEF_NETIF_STA) && !defined(CONFIG_MDNS_PREDEF_NETIF_ETH)
    /* Demonstration of adding a custom netif to mdns service, but we're adding the default example one,
     * so we must disable all predefined interfaces (PREDEF_NETIF_STA, AP and ETH) first
     */
    ESP_ERROR_CHECK(mdns_register_netif(EXAMPLE_INTERFACE));
    /* It is not enough to just register the interface, we have to enable is manually.
     * This is typically performed in "GOT_IP" event handler, but we call it here directly
     * since the `EXAMPLE_INTERFACE` netif is connected already, to keep the example simple.
     */
    ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4 | MDNS_EVENT_ENABLE_IP6));
    ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4 | MDNS_EVENT_ANNOUNCE_IP6));

#endif // CONFIG_MDNS_ADD_CUSTOM_NETIF
}

/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it.
 *  [url=home.php?mod=space&uid=784970]@return[/url] host name string allocated from the heap
 */
static char *generate_hostname(void)
{
#ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME
    return strdup(CONFIG_MDNS_HOSTNAME);
#else
    uint8_t mac[6];
    char   *hostname;
    esp_read_mac(mac, ESP_MAC_WIFI_STA);
    if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) {
        abort();
    }
    return hostname;
#endif
}

 

如下图,修改好wifi名称和密码,其他默认也可以了

image.png  

然后编译好,下载到板子上,运行。这时候找一个可以搜索mDNS设备的程序,例如下图的mDNS浏览器,就可以搜索到设备了

image.png   点击Details按钮后,还可以看到mDNS服务的其他特性,其实我们使用mDNS,就是可以通过主机.local直接访问设备,也可以使用_http._tcp或者其他特性描述来搜索相关的设备。

假如网络里有多个设备,我们可以将设备名称添加上设备号或者其他标识符,然后还可以通过txt属性附带的文本来区别设备,或者提供其他的一些信息。

image.png  

 

总结:mDNS功能还是非常强大的,有兴趣的话,大家可以自行尝试一下。

 

此帖出自无线连接论坛

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
快速回复 返回顶部 返回列表