【mesh】ESP32 官方文档(十六)ESP-MESH 编程指南

本文档详细介绍了ESP32的ESP-MESH编程模型,包括软件栈、系统事件、自组织网络特性及编程示例。ESP-MESH构建于Wi-Fi驱动/FreeRTOS之上,支持LwIP栈,适用于自动构建和维护网络拓扑。文中还提供了初始化、配置、启动ESP-MESH网络的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

ESP-MESH 编程指南

ESP-MESH 编程模型

软件栈

系统事件

LwIP & ESP-MESH

编写 ESP-MESH 应用程序​​​​​​​

初始化 Mesh

配置 ESP-MESH 网络

启动 Mesh

自组织网络

切换自组织网络

禁用自组织网络

启用自组织网络

调用 Wi-Fi 驱动程序 API

应用实例

API 参考头文件

ESP32 开发问题记录


前言

此处仅是对该文的备份,请到原文阅读:原文连接:ESP32 官方文档(十六)ESP-MESH 编程指南_

官方原文:无法找到该网页 - ESP32 - — ESP-IDF 编程指南 latest 文档

mesh网络组网流程:ESP32 官方文档(十五)ESP-MESH ESP32 官方文档(十五)ESP-MESH_InfiniteYuan的博客-优快云博客_rssi阈值

官网快速入门

ESP-IDF 编程指南 - ESP32 - — ESP-IDF 编程指南 latest 文档

快速入门 - ESP32 - — ESP-IDF 编程指南 latest 文档

ESP-MESH 编程指南

ESP-MESH 的编程指南,包括 API 参考和编码示例。本指南分为以下几部分:

  • ESP-MESH 编程模型
  • 编写 ESP-MESH 应用程序
  • 自组织网络
  • 应用实例
  • API 参考

有关 ESP-MESH 协议的文档,请参阅 ESP-MESH API 指南。


ESP-MESH 编程模型


软件栈

下图说明了 ESP-MESH 软件栈

ESP-MESH 软件栈
ESP-MESH 软件栈构建在 Wi-Fi 驱动/FreeRTOS 之上,并且在某些情况下可以使用 LwIP 栈(Lightweight IP, 是一个轻量级的开源 TCP/IP 协议栈)。

系统事件


应用程序通过 ESP-MESH 事件与 ESP-MESH 交互。由于 ESP-MESH 构建在 Wi-Fi 栈的顶部,因此应用程序也可以通过 Wi-Fi 事件任务与 Wi-Fi 驱动交互。下图说明了 ESP-MESH 应用程序中各种系统事件的接口。

mesh_event_id_t 定义所有可能的  ESP-MESH 系统事件,并且可以指示诸如父/子的连接/断开之类的事件。在可以使用 ESP-MESH 系统事件之前,应用程序必须通过 esp_mesh_set_config() 注册 Mesh 事件回调。 回调用于从 ESP-MESH 栈以及 LwIP 栈接收事件,并且应包含与应用程序相关的每个事件的处理程序。


系统事件的典型用例包括使用诸如 MESH_EVENT_PARENT_CONNECTED 和 MESH_EVENT_CHILD_CONNECTED 之类的事件来指示节点何时可以分别开始上游和下游传输数据。 同样,MESH_EVENT_ROOT_GOT_IP 和 MESH_EVENT_ROOT_LOST_IP 可用于指示根节点何时能够或不能将数据传输到外部 IP 网络。

在自组织模式下使用 ESP-MESH 时,用户必须确保不会调用 Wi-Fi API。这是因为自组织模式将在内部进行 Wi-Fi API 调用以连接/断开/扫描等。来自应用程序的任何 Wi-Fi 调用(包括来自回调函数和 Wi-Fi 事件处理程序的调用)可能干扰 ESP-MESH 的自组织行为。因此,在调用 esp_mesh_start() 之后,并且在调用 esp_mesh_stop() 之前,用户不应该调用 Wi-Fi API。

LwIP & ESP-MESH


应用程序可以直接访问 ESP-MESH 栈,而无需通过 LwIP 栈。仅根节点需要 LwIP 栈向/从外部 IP 网络发送/接收数据。 但是,由于每个节点都可能成为根节点(由于自动根节点选择),每个节点仍必须初始化 LwIP 栈。

每个节点都需要通过调用 tcpip_adapter_init() 来初始化 LwIP 栈。为了防止非根节点访问 LwIP 栈,应用程序应在 LwIP 栈初始化后停止以下服务:

  • SoftAP 接口上的 DHCP 服务器服务。
  • Station 接口上的 DHCP 客户端服务。

以下代码段演示了如何为 ESP-MESH 应用程序初始化 LwIP。

/* TCP/IP 初始化 */
tcpip_adapter_init();

/* * 针对 mesh 网络
* 默认情况下,停止 softAP 接口上的 DHCP 服务器
* 默认情况下,停止 station 接口上的 DHCP 客户端 */

ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));

/* 不指定系统事件回调函数,使用 NULL 代替 */
ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL));

ESP-MESH 要求根节点与路由器连接。因此,如果节点成为根节点,则相应的处理程序必须启动 DHCP 客户端服务并立即获取 IP 地址。这样做将允许其他节点开始向/从外部 IP 网络发送/接收分组。但是,如果使用静态 IP 设置,则不需要此步骤。

编写 ESP-MESH 应用程序


启动 ESP-MESH 的先决条件是初始化 LwIP 和 Wi-Fi。 以下代码片段演示了初始化 ESP-MESH 之前必要的先决条件步骤。

tcpip_adapter_init();

/*
 * 针对 mesh 网络
 * 默认情况下,停止 softAP 接口上的 DHCP 服务器
 * 默认情况下,停止 station 接口上的 DHCP 客户端
 */
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
ESP_ERROR_CHECK(tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA));

/* 不指定系统事件回调函数,使用 NULL 代替 */
ESP_ERROR_CHECK(esp_event_loop_init(NULL, NULL));

/* Wi-Fi 初始化 */
wifi_init_config_t config = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&config));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH));
ESP_ERROR_CHECK(esp_wifi_start());


初始化 LwIP 和 Wi-Fi 后,启动和运行 ESP-MESH 网络的过程可归纳为以下三个步骤:

  • 初始化 Mesh
  • 配置 ESP-MESH 网络
  • 启动 Mesh

初始化 Mesh


以下代码段演示了如何初始化 ESP-MESH

/*  mesh initialization */
ESP_ERROR_CHECK(esp_mesh_init());

配置 ESP-MESH 网络


ESP-MESH 通过 esp_mesh_set_config() 配置,它使用 mesh_cfg_t 结构接收其参数。 该结构包含用于配置 ESP-MESH 的以下参数:


以下代码段演示了如何配置 ESP-MESH。

/* 默认启用 Mesh IE 加密 */
mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT();

/* mesh ID */
memcpy((uint8_t *) &cfg.mesh_id, MESH_ID, 6);

/* mesh 事件回调 */
cfg.event_cb = &mesh_event_handler;

/* 信道(必须与路由器的信道匹配) */
cfg.channel = CONFIG_MESH_CHANNEL;

/* 路由器配置 */
cfg.router.ssid_len = strlen(CONFIG_MESH_ROUTER_SSID);
memcpy((uint8_t *) &cfg.router.ssid, CONFIG_MESH_ROUTER_SSID, cfg.router.ssid_len);
memcpy((uint8_t *) &cfg.router.password, CONFIG_MESH_ROUTER_PASSWD,
       strlen(CONFIG_MESH_ROUTER_PASSWD));

/* mesh softAP 配置 */
cfg.mesh_ap.max_connection = CONFIG_MESH_AP_CONNECTIONS;
memcpy((uint8_t *) &cfg.mesh_ap.password, CONFIG_MESH_AP_PASSWD,
       strlen(CONFIG_MESH_AP_PASSWD));

/* 设置 mesh 配置 */
ESP_ERROR_CHECK(esp_mesh_set_config(&cfg));


启动 Mesh


以下代码段演示了如何启动 ESP-MESH。

/* mesh start */
ESP_ERROR_CHECK(esp_mesh_start());

启动 ESP-MESH 后,应用程序应检查 ESP-MESH 事件以确定它何时连接到网络。连接后,应用程序可以使用 esp_mesh_send() 和 esp_mesh_recv() 通过 ESP-MESH 网络开始发送和接收数据包。

自组织网络

自组织网络是 ESP-MESH 的核心功能之一,节点可以自动扫描、选择、连接和重新连接到其他节点和路由器。此功能使 ESP-MESH 网络能够动态适应拓扑变化(如节点加入、离开或故障),从而实现高度自治和鲁棒性。启用自组织网络后,ESP-MESH 栈会自动处理以下操作,应用层无需干预:

  • 自动选择根节点(通常是连接到路由器的节点)。

  • 自动选择最优的父节点(基于信号强度或跳数)。

  • 在检测到断开连接时,自动尝试重新连接或寻找新的父节点。

启用自组织网络后,ESP-MESH 栈会直接管理 Wi-Fi 驱动层的操作(如扫描、连接、信道切换等)。因此,应用层应避免直接调用 Wi-Fi 驱动程序 API(如 esp_wifi_scan_start() 或 esp_wifi_connect()),否则可能会干扰 ESP-MESH 的正常运行。


切换自组织网络


应用程序在运行时通过调用 esp_mesh_set_self_organized() 函数可以启用或禁用自组织网络。该函数具有以下两个参数:

bool enable 指定是启用还是禁用自组织网络。
bool select_parent 指定在启用自组织网络时是否应选择新的父节点。根据节点类型和节点的当前状态,选择新父级具有不同的效果。禁用自组织网络时,此参数未使用。

禁用自组织网络


以下代码段演示了如何禁用自组织网络。

//Disable self organized networking
esp_mesh_set_self_organized(false, false);

当禁用自组织网络时,ESP-MESH 将尝试维持节点当前的 Wi-Fi 状态。

如果节点先前已连接到其他节点,则它将保持连接状态。
如果节点先前已断开连接并且正在扫描父节点或路由器,则它将停止扫描。
如果节点先前尝试重新连接到父节点或路由器,它将停止重新连接。

启用自组织网络

在启用自组织网络时,ESP-MESH 将尝试维持节点当前的 Wi-Fi 状态。但是,根据节点类型以及是否选择了新父节点,节点的 Wi-Fi 状态可能会发生变化。下表显示了启用自组织网络的效果。

选择父节点是否根节点效果
N(否)N(否)- 已连接到父节点的节点将保持连接。
- 已扫描父节点的节点将停止扫描。可以通过调用esp_mesh_connect()来重新启动。
N(否)Y(是)- 已连接到路由器的根节点将保持连接。
- 从路由器断开连接的根节点需要通过调用esp_mesh_connect()来重新连接。
Y(是)N(否)- 没有父节点的节点将自动选择一个首选的父节点并连接。
- 已连接到父节点的节点将断开连接,重新选择一个首选的父节点并连接。
Y(是)Y(是)- 要让根节点连接到父节点,必须让根节点放弃其作为根节点的角色。因此,根节点将从路由器断开连接,并且所有子节点将选择一个首选的父节点并连接。

在这里插入图片描述

以下代码演示了如何启用自组织网络。

//Enable self organized networking and select a new parent
esp_mesh_set_self_organized(true, true);

...

//Enable self organized networking and manually reconnect
esp_mesh_set_self_organized(true, false);
esp_mesh_connect();



调用 Wi-Fi 驱动程序 API


应用程序可能希望在使用 ESP-MESH 时直接调用 Wi-Fi 驱动程序 API 的情况。例如,应用程序可能想要手动扫描相邻的 AP。但是,在应用程序调用任何 Wi-Fi 驱动程序 API 之前,必须禁用自组织网络。 这将阻止 ESP-MESH 栈尝试调用任何 Wi-Fi 驱动程序 API ,ESP-MESH 栈的这些调用可能干扰应用程序的调用。

因此,应该在调用 esp_mesh_set_self_organized() 进行禁用和启用自组织网络之间放置对 Wi-Fi 驱动程序 API 的调用。

以下代码段演示了应用程序在使用 ESP-MESH 时如何安全地调用 esp_wifi_scan_start()。

// 禁用自组织网络
esp_mesh_set_self_organized(0, 0);

// 停止任何正在进行的扫描
esp_wifi_scan_stop();

// 手动启动扫描。扫描完成后会自动停止
esp_wifi_scan_start();

// 处理扫描结果
...

// 如果仍然连接,则重新启用自组织网络
esp_mesh_set_self_organized(1, 0);

...

// 如果是非根节点且已断开连接,则重新启用自组织网络
esp_mesh_set_self_organized(1, 1);

...

// 如果是根节点且已断开连接,则重新启用自组织网络
esp_mesh_set_self_organized(1, 0);  // 不选择新的父节点
esp_mesh_connect();                 // 手动重新连接到路由器


应用实例


ESP-IDF 包含这些 ESP-MESH 示例项目:
内部通信示例演示了如何设置 ESP-MESH 网络并让根节点向网络中的每个节点发送数据包。
手动网络示例演示了如何在没有自组织功能的情况下使用 ESP-MESH。此示例显示如何对节点进行编程以手动扫描潜在父节点列表,并根据自定义条件选择父节点。


API 参考
头文件

esp32/include/esp_mesh.h

相关函数

esp_err_tesp_mesh_init(void)
esp_err_tesp_mesh_deinit(void)
esp_err_tesp_mesh_start(void)
esp_err_tesp_mesh_stop(void)
esp_err_tesp_mesh_send(constmesh_addr_t *to, constmesh_data_t *data, int flag, constmesh_opt_topt[], int opt_count)
esp_err_tesp_mesh_recv(mesh_addr_t *from, mesh_data_t *data, int timeout_ms, int *flag, mesh_opt_topt[], int opt_count)
esp_err_tesp_mesh_recv_toDS(mesh_addr_t *from, mesh_addr_t *to, mesh_data_t *data, int timeout_ms, int *flag, mesh_opt_topt[], int opt_count)
esp_err_tesp_mesh_set_config(constmesh_cfg_t *config)
esp_err_tesp_mesh_get_config(mesh_cfg_t *config)
esp_err_tesp_mesh_set_router(constmesh_router_t *router)
esp_err_tesp_mesh_get_router(mesh_router_t *router)
esp_err_tesp_mesh_set_id(constmesh_addr_t *id)
esp_err_tesp_mesh_get_id(mesh_addr_t *id)
esp_err_tesp_mesh_set_type(mesh_type_ttype)
mesh_type_tesp_mesh_get_type(void)
esp_err_tesp_mesh_set_max_layer(int max_layer)
int esp_mesh_get_max_layer(void)
esp_err_tesp_mesh_set_ap_password(const uint8_t *pwd, int len)
esp_err_tesp_mesh_set_ap_authmode(wifi_auth_mode_tauthmode)
wifi_auth_mode_tesp_mesh_get_ap_authmode(void)
esp_err_tesp_mesh_set_ap_connections(int connections)
int esp_mesh_get_ap_connections(void)
int esp_mesh_get_layer(void)
esp_err_tesp_mesh_get_parent_bssid(mesh_addr_t *bssid)
bool esp_mesh_is_root(void)
esp_err_tesp_mesh_set_self_organized(bool enable, bool select_parent)
bool esp_mesh_get_self_organized(void)
esp_err_tesp_mesh_waive_root(constmesh_vote_t *vote, int reason)
esp_err_tesp_mesh_set_vote_percentage(float percentage)
float esp_mesh_get_vote_percentage(void)
esp_err_tesp_mesh_set_ap_assoc_expire(int seconds)
int esp_mesh_get_ap_assoc_expire(void)
int esp_mesh_get_total_node_num(void)
int esp_mesh_get_routing_table_size(void)
esp_err_tesp_mesh_get_routing_table(mesh_addr_t *mac, int len, int *size)
esp_err_tesp_mesh_post_toDS_state(bool reachable)
esp_err_tesp_mesh_get_tx_pending(mesh_tx_pending_t *pending)
esp_err_tesp_mesh_get_rx_pending(mesh_rx_pending_t *pending)
int esp_mesh_available_txupQ_num(constmesh_addr_t *addr, uint32_t *xseqno_in)
esp_err_tesp_mesh_set_xon_qsize(int qsize)
int esp_mesh_get_xon_qsize(void)
esp_err_tesp_mesh_allow_root_conflicts(bool allowed)
bool esp_mesh_is_root_conflicts_allowed(void)
esp_err_tesp_mesh_set_group_id(constmesh_addr_t *addr, int num)
esp_err_tesp_mesh_delete_group_id(constmesh_addr_t *addr, int num)
int esp_mesh_get_group_num(void)
esp_err_tesp_mesh_get_group_list(mesh_addr_t *addr, int num)
bool esp_mesh_is_my_group(constmesh_addr_t *addr)
esp_err_tesp_mesh_set_capacity_num(int num)
int esp_mesh_get_capacity_num(void)
esp_err_tesp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs)
esp_err_tesp_mesh_set_ie_crypto_key(const char *key, int len)
esp_err_tesp_mesh_get_ie_crypto_key(char *key, int len)
esp_err_tesp_mesh_set_root_healing_delay(int delay_ms)
int esp_mesh_get_root_healing_delay(void)
esp_err_tesp_mesh_set_event_cb(constmesh_event_cb_tevent_cb)
esp_err_tesp_mesh_fix_root(bool enable)
bool esp_mesh_is_root_fixed(void)
esp_err_tesp_mesh_set_parent(constwifi_config_t *parent, constmesh_addr_t *parent_mesh_id, mesh_type_tmy_type, int my_layer)
esp_err_tesp_mesh_scan_get_ap_ie_len(int *len)
esp_err_tesp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer)
esp_err_tesp_mesh_flush_upstream_packets(void)
esp_err_tesp_mesh_get_subnet_nodes_num(constmesh_addr_t *child_mac, int *nodes_num)
esp_err_tesp_mesh_get_subnet_nodes_list(constmesh_addr_t *child_mac, mesh_addr_t *nodes, int nodes_num)
esp_err_tesp_mesh_disconnect(void)
esp_err_tesp_mesh_connect(void)
esp_err_tesp_mesh_flush_scan_result(void)
esp_err_tesp_mesh_switch_channel(const uint8_t *new_bssid, int csa_newchan, int csa_count)
esp_err_tesp_mesh_get_router_bssid(uint8_t *router_bssid)


 

ESP32 开发问题记录

2019-11-27 09:12:58

USB线一定要用数据线,不要用电源线

ESP32连接电脑在设备管理器中看不到设备,找不到“端口”。

(win10 设备管理器中没端口选项是怎么回事?)

被隐藏了,点击上面的查看,勾选显示隐藏的设备就可以找到端口了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值