ESP-IDF ESP-WIFI-MESH 技术指南:自组织多跳网状网络的原理、构建与管理
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
本文以 docs/en/api-guides/esp-wifi-mesh.rst 为核心主体,结合 ESP-IDF 仓库中的
esp_mesh实现、示例工程与配置源码展开。ESP-WIFI-MESH 是乐鑫在 Wi-Fi 协议之上构建的自组织(self-organizing)、自愈(self-healing)网状网络协议,适用于大范围室内/室外多设备互联场景。读完本文,你将掌握 ESP-WIFI-MESH 的树形拓扑、根节点选举、路由表转发、信道切换等核心机制,并能够在真实工程中配置与部署一套多跳自愈网络。
概述:从单 AP 到多跳 WLAN
在传统基础设施(infrastructure)Wi-Fi 网络中,一个中心节点(Access Point,AP)以点对多点的方式直接连接所有站点(station),AP 负责站点间传输的仲裁与转发,部分 AP 还通过路由器把流量转发到外部 IP 网络。传统 Wi-Fi 有两个固有缺陷:
- 覆盖范围受限——每个站点都必须在 AP 的直连信号范围内;
- 容量易饱和——网络允许的站点总数受限于单个 AP 的处理能力。
ESP-WIFI-MESH 与上述架构的本质区别在于:节点不必连接中心节点,而是可以连接相邻节点,所有节点互相负责转发彼此的报文。这使得网络覆盖面积大幅扩展(节点即使不在中心节点范围内也能保持互联),同时不再受单个中心节点容量限制。官方文档将 ESP-WIFI-MESH 指南划分为以下八大部分:
- 介绍(Introduction)
- 核心概念(Concepts)
- 构建网络(Building a Network)
- 管理网络(Managing a Network)
- 数据传输(Data Transmission)
- 信道切换(Channel Switching)
- 网络性能(Network Performance)
- 补充说明(Further Notes)
API 使用层面请参阅 ESP-WIFI-MESH API Reference,本文专注协议原理与工程实践。
ESP-WIFI-MESH 核心概念
术语表
官方文档给出的术语定义如下(读者可对照 esp_mesh.h 中的类型与枚举理解):
| 术语 | 描述 |
|---|---|
| Node(节点) | 任何已经是或可以是ESP-WIFI-MESH 网络一部分的设备 |
| Root Node(根节点) | 网络中位于最顶层的节点 |
| Child Node(子节点) | 当节点 X 连接到节点 Y,且该连接使 X 比 Y 距离根节点更远(按连接数计)时,X 是子节点 |
| Parent Node(父节点) | 子节点的反义概念 |
| Descendant Node(后代节点) | 从父到子反复推进可到达的任何节点 |
| Sibling Nodes(兄弟节点) | 共享同一个父节点的节点 |
| Connection(连接) | AP 与站点之间一次传统 Wi-Fi 关联。节点用其 station 接口关联另一节点的 softAP 接口形成连接,过程包含 Wi-Fi 的认证与关联流程 |
| Upstream Connection(上行连接) | 节点到其父节点的连接 |
| Downstream Connection(下行连接) | 节点到其某个子节点的连接 |
| Wireless Hop(无线跳) | 源与目的节点之间对应单条无线连接的那段路径。穿越单条连接的数据包称单跳(single-hop),穿越多条连接称多跳(multi-hop) |
| Subnetwork(子网络) | 由一个节点及其全部后代节点组成的网络细分。根节点的子网络即整个 ESP-WIFI-MESH 网络 |
| MAC Address | 用于在 ESP-WIFI-MESH 网络中唯一标识每个节点或路由器的媒体访问控制地址 |
| DS | Distribution System,即外部 IP 网络 |
树形拓扑:为什么天然是树
ESP-WIFI-MESH 构建在基础设施 Wi-Fi 协议之上,可视为把许多独立 Wi-Fi 网络合并成一个 WLAN 的组网协议。Wi-Fi 协议限制:站点同一时刻只能与一个 AP 保持单条上行连接,而一个 AP 可同时连接多个站点(多条下行连接)。ESP-WIFI-MESH 允许节点同时扮演站点与 AP,因此:
- 一个节点可用 softAP 接口拥有多条下行连接;
- 同时用 station 接口保持单条上行连接。
这自然形成了带父子层级、包含多层的树形拓扑。由于是多跳网络,节点不仅要发送自己的数据包,还要为其他节点中继转发;只要物理层上任意两节点之间存在一条(经一跳或多跳的)路径,它们即可通信。
注意:网络总节点数由最大允许层数与每个节点的最大下行连接数共同决定,这两个变量均可配置以限制网络规模。
对应到工程代码,拓扑与层数通过 internal_communication 示例 中的接口设置:esp_mesh_set_topology(CONFIG_MESH_TOPOLOGY)与esp_mesh_set_max_layer(CONFIG_MESH_MAX_LAYER)。其中拓扑支持树形(MESH_TOPO_TREE)与链形(MESH_TOPO_CHAIN)两种,配置定义见 Kconfig.projbuild:MESH_MAX_LAYER在树形下范围为 1~25、链形下为 1~1000,默认 6。
节点类型
ESP-WIFI-MESH 中节点按角色分为四类:
- 根节点(Root Node):网络最顶层节点,是 ESP-WIFI-MESH 网络与外部 IP 网络之间的唯一接口。根节点连接一台常规 Wi-Fi 路由器,负责在外部 IP 网络与网络内节点之间中继数据包。一个 ESP-WIFI-MESH 网络只能有一个根节点,且根节点的上行连接只能与路由器建立。
- 叶节点(Leaf Node):不允许拥有任何子节点(无下行连接)的节点,只能收发自身数据包,不能转发他人数据包。位于网络最大允许层的节点会被自动指定为叶节点;没有 softAP 接口(仅 station)的节点同样会成为叶节点。
- 中间父节点(Intermediate Parent Node):既非根节点也非叶节点的已连接节点。必须有单条上行连接(唯一父节点),下行连接可有零到多条。它既可收发数据包,也能转发来自上行与下行连接的数据包。注意:没有下行连接的中间父节点(如 E/F/G 类节点)不等同于叶节点,它们将来仍被允许建立下行连接。
- 空闲节点(Idle Node):尚未入网的节点,会尝试与某个中间父节点建立上行连接,或在满足条件时尝试成为根节点(见"自动根节点选举")。
信标帧与 RSSI 阈值机制
每个具备 softAP 接口(即可建立下行连接)的节点都会周期性发送 Wi-Fi 信标帧(beacon frame),用于让其他节点探测其存在并获知其状态。空闲节点侦听信标帧以生成潜在父节点列表,并从中选择一个建立上行连接。ESP-WIFI-MESH 利用Vendor Information Element(厂商信息元素)携带如下元数据:
- 节点类型(根/中间父/叶/空闲)
- 节点当前所在层
- 网络允许的最大层数
- 当前子节点数
- 可接受的最大下行连接数
潜在上行连接的信号强度由潜在父节点信标帧的RSSI(Received Signal Strength Indication)表示。为防止节点建立弱上行连接,ESP-WIFI-MESH 实现了信标帧 RSSI 阈值机制:若某信标帧 RSSI 低于预配置阈值,则发送该信标帧的节点在建立上行连接时会被忽略。典型场景是射频屏蔽物降低了潜在父节点的 RSSI——即使该节点物理上近在咫尺,也会因 RSSI 低于阈值而被忽略,空闲节点转而选择物理距离更远但 RSSI 更强的节点。
注意:MAC 层技术上仍会收到所有信标帧。RSSI 阈值只是 ESP-WIFI-MESH 层面的过滤特性,将低于预配置阈值的信标帧过滤掉。
首选父节点(Preferred Parent Node)
当空闲节点有多个父节点候选时,会与首选父节点建立上行连接,判定依据是:
- 父节点候选所在的层;
- 父节点候选当前的子节点数。
选择永远优先选择处于网络最浅层的候选(包含根节点),这有助于最小化网络总层数——例如给定第二层与第三层节点时,第二层节点总是被优先选择。若同一层存在多个候选,则子节点数最少者被优先选择,从而在同层节点间均衡下行连接数量。
用户也可以自定义首选父节点算法,或强制节点只连接指定父节点——参见 Mesh Manual Networking 示例,其中通过
esp_mesh_set_self_organized(0, 0)关闭自组织行为,并调用esp_mesh_set_parent()指定父节点(详见后文"父节点选择")。
路由表与转发决策
网络内每个节点维护各自的路由表,用于把 ESP-WIFI-MESH 数据包正确路由到目的节点。某节点的路由表由该节点子网络内所有节点的 MAC 地址组成(含节点自身 MAC)。路由表内部按每个子节点对应的子网络划分为多个子表(subtable)。
例如节点 B 的路由表包含 B~I 的 MAC 地址(即 B 的子网络),内部划分为两个子表:C~F(节点 C 的子网络)与 G~I(节点 G 的子网络)。ESP-WIFI-MESH 依据以下两条规则决定数据包向上游还是下游转发:
- 若数据包目的 MAC 在当前节点路由表内且不是当前节点,则选择包含该目的 MAC 的子表,把数据包下行转发到子表对应的子节点;
- 若目的 MAC 不在当前节点路由表内,则把数据包上行转发到当前节点的父节点;重复该过程,数据包最终到达根节点(其路由表包含全网所有节点)。
工程层面,可用
esp_mesh_get_routing_table()获取节点的路由表,esp_mesh_get_routing_table_size()获取路由表大小,esp_mesh_get_subnet_nodes_list()获取某子节点对应的子表,esp_mesh_get_subnet_nodes_num()获取子表大小。这些 API 在 esp_mesh.h 中声明,示例见 internal_communication/main/mesh_main.c:根节点通过esp_mesh_get_routing_table()获得全网节点列表后,逐个调用esp_mesh_send()向每个节点发送点对点数据。
构建一个 ESP-WIFI-MESH 网络
通用构建流程
警告:网络构建开始前,网络中每个节点的部分配置必须一致(见
mesh_cfg_t)——每个节点必须配置相同的 Mesh Network ID、路由器配置和 softAP 配置。这些字段在 internal_communication 示例 中通过mesh_cfg_t cfg = MESH_INIT_CONFIG_DEFAULT()填充,包括cfg.mesh_id(Mesh ID)、cfg.channel、cfg.router.ssid/password以及cfg.mesh_ap.max_connection/nonmesh_max_connection。
构建过程是:先选定根节点,再逐层建立下行连接,直到所有节点入网。网络最终布局受根节点选择、父节点选择、异步上电复位等因素影响,但可概括为以下步骤:
- 根节点选择:根节点可在配置时指定(见"用户指定根节点"),或基于各节点与路由器的信号强度动态选举(见"自动根节点选举")。选定后,根节点连接路由器并开始允许下行连接形成。
- 第二层形成:根节点连上路由器后,其范围内的空闲节点开始与之连接,形成第二层。连接后第二层节点成为中间父节点(假设最大允许层 > 2),进而形成下一层。
- 其余层形成:剩余空闲节点与范围内中间父节点连接形成新层;连接后空闲节点根据网络最大允许层成为中间父节点或叶节点。该步骤重复,直到网络内不再有空闲节点或达到最大允许层。
- 限制树深度:为防止网络超过最大允许层数,位于最大层的节点连接后自动成为叶节点,阻止新层形成;但若空闲节点没有其他潜在父节点,它将无限期保持空闲。
自动根节点选举
自动选举是所有空闲节点基于其与路由器的信号强度进行的选举过程:
- 每个空闲节点通过信标帧广播自己的MAC 地址(唯一标识)与路由器 RSSI(指示相对路由器的信号强度);
- 所有节点同时扫描其他空闲节点的信标帧。若某节点检测到路由器 RSSI 更强的信标帧,便开始转发该信标帧的内容(即为信号更强的节点投票);
- 收发扫描过程重复预配置的最少迭代次数(默认 10 次),最终使路由器 RSSI 最强的信标帧在整个网络传播;
- 迭代结束后,每个节点检查自己的得票率(
得票数/参与选举节点数)。得票率大于预配置阈值(默认 90%)的节点成为根节点。
示例:节点 C 的路由器 RSSI 最强(-10 dB),其信标帧传播至全网,所有参与选举的节点投票给 C,得票率 100%,C 成为根节点并连接路由器;随后 A/B/D/E 因 C 是最浅层节点而连向 C 形成第二层;F/G 再分别连向 D/E,建网完成。
选举最少迭代次数可用
esp_mesh_set_attempts()配置。用户应根据网络节点数调整迭代次数(网络越大所需扫描迭代越多)。
警告:得票率阈值可用
esp_mesh_set_vote_percentage()配置。阈值设置过低可能导致同一网络中出现两个或更多根节点,从而构建出多个网络。此时 ESP-WIFI-MESH 有内部机制自主解决根节点冲突:多个根节点的网络会合并为单一根节点的单一网络。但若两个及以上根节点具有相同路由器 SSID 却不同路由器 BSSID,则不处理这种冲突。
用户指定根节点
用户也可以直接指定根节点:指定节点将直接连接路由器并跳过选举过程。此时网络内所有其他节点也必须跳过选举,以避免根节点冲突。
指定根节点时,根节点应调用
esp_mesh_set_parent()直接连接路由器;其余所有节点应调用esp_mesh_fix_root()以跳过选举。两者的启用/禁用语义见 esp_mesh.h 中esp_mesh_fix_root(bool enable)的注释:通过该 API 可开启/关闭网络"固定根节点"设置。
父节点选择
默认情况下 ESP-WIFI-MESH 是自组织的:每个节点自主选择与哪个潜在父节点建立上行连接(即首选父节点),判据旨在减少网络层数并均衡潜在父节点间的下行连接数。
但用户也可关闭自组织行为,自定义父节点选择判据,或为节点配置指定的父节点。Mesh Manual Networking 示例 展示了完整做法:在MESH_EVENT_STARTED事件中调用esp_mesh_set_self_organized(0, 0)关闭自组织,随后用esp_wifi_scan_start()发起被动扫描;在扫描完成回调mesh_scan_done_handler()中读取各 AP 的关联信息(esp_mesh_scan_get_ap_ie_len()/esp_mesh_scan_get_ap_record()),根据 RSSI、层数、连接容量等条件筛选父节点,最终调用esp_mesh_set_parent(&parent, &mesh_id, my_type, my_layer)建立上行连接。该示例同时演示了通过CONFIG_MESH_SET_ROOT让指定节点直接连接路由器成为根节点(同样经由esp_mesh_set_parent,my_type为MESH_ROOT,my_layer为MESH_ROOT_LAYER)。
异步上电复位对建网的影响
节点上电顺序会影响建网结果。若某些节点异步上电(间隔数分钟),最终网络结构可能与全体同步上电的理想情况不同。延迟上电的节点遵循以下规则:
- 规则 1:若网络中已存在根节点,延迟节点不会尝试选举新根节点,即使它与路由器的 RSSI 更强。延迟节点会像普通空闲节点一样连接首选父节点入网。若延迟节点是指定根节点,则网络内所有其他节点将保持空闲,直到延迟节点上电。
- 规则 2:若延迟节点建立上行连接成为中间父节点,它可能成为其他节点的新首选父节点(因为层更浅),导致其他节点切换上行连接(见"父节点切换")。
- 规则 3:若空闲节点有指定父节点且该父节点延迟上电,则空闲节点在父节点缺席期间不会尝试建立任何上行连接,将无限期保持空闲直至指定父节点上电。
官方示例(以异步上电为例):A/C/D/F/G/H 同步上电开始选举,A 以最强 RSSI 当选根节点,其余节点逐层连接形成 5 层网络;随后 B/E 延迟上电,虽然它们路由器 RSSI(-20 dB、-10 dB)强于 A,但都不尝试成为根节点,而是分别连接首选父节点 A 与 C 成为中间父节点;D/G 因 B 处于更浅层(第二层)而切换上行连接到 B,最终网络由 5 层变为 3 层。
若所有节点同步上电,E 将因最强路由器 RSSI(-10 dB)成为根节点,网络布局会显著不同。同步上电的布局仍可通过手动切换根节点实现(调用
esp_mesh_waive_root(),见"根节点切换")。
异步上电造成的父节点选择差异,会在一定程度上由 ESP-WIFI-MESH 自主纠正(见"父节点切换")。
回环避免、检测与处理
回环(loop-back)指某节点与自身子网络内的后代节点建立上行连接,形成环形连接路径,破坏树形拓扑。ESP-WIFI-MESH 在父节点选择阶段就排除已存在于选择节点路由表中的节点,从而防止节点尝试连接子网络内任意节点。若回环仍发生,ESP-WIFI-MESH 利用路径验证机制与能量传递机制检测回环;造成回环的上行连接的父节点会告知子节点回环发生,并主动发起断开。
管理一个 ESP-WIFI-MESH 网络
ESP-WIFI-MESH 是自愈网络,可检测并纠正网络路由故障。故障发生在带子节点的父节点宕机、或父节点与子节点连接不稳定时。子节点会自主选择新父节点并建立上行连接以维持互联,可处理根节点故障与中间父节点故障两类。
根节点故障
根节点宕机后,与其直连的第二层节点会迅速检测到故障,先尝试重连根节点;多次重连失败后,第二层节点发起新一轮根节点选举。路由器 RSSI 最强的第二层节点当选新根节点,其余第二层节点与新根节点(或范围内相邻父节点)建立上行连接。
若根节点与多层下游同时宕机(如根、第二层、第三层同时失效),则由仍然正常工作的最浅层发起根节点选举。示例:C 为根节点,A/B/D/E 为第二层;C 宕机后多次重连失败,第二层开始广播 RSSI 选举,B 信号最强当选新根节点并接受下行连接,A/D/E 连接 B,网络自愈并恢复正常运行。
若指定根节点(fixed root)宕机,剩余节点不会自主发起新选举——只要使用指定根节点,选举过程就永远不会被尝试。
中间父节点故障
中间父节点宕机后,被断开的子节点先尝试重连原父节点;多次失败后,每个子节点开始扫描潜在父节点。若存在其他候选,每个子节点独立选择新的首选父节点并建立上行连接;若无可用候选,则保持空闲。示例:C 宕机后 F/G 检测并重连失败,开始选择新父节点;G 不在任何其他父节点范围内暂时保持空闲,F 在 B/E 范围内且选择更浅的 B,F 连接 B 成为中间父节点后 G 得以连接 F,网络自愈,但路由被改变且多了一层。
若子节点有指定父节点且该父节点宕机,子节点不会尝试连接新父节点,将无限期保持空闲。
根节点切换(Root Node Switching)
除非根节点宕机,ESP-WIFI-MESH不会自动切换根节点——即使根节点路由器 RSSI 恶化到断连程度,根节点也保持不变。根节点切换是显式发起新一轮选举、让 RSSI 更强的节点当选新根节点的操作,适用于应对根节点性能退化。
触发方式:当前根节点显式调用esp_mesh_waive_root()触发新选举。当前根节点会通知全网节点开始收发信标帧(期间保持连接网络,不进入空闲)。若其他节点得票多于当前根节点,则发起根节点切换;否则根节点保持不变。
切换流程:新当选根节点向当前根节点发送切换请求(switch request),当前根节点回确认(acknowledgment),双方就绪后——新根节点断开父节点、立即与路由器建立上行连接成为新根节点;旧根节点断开路由器但保持所有下行连接进入空闲状态,随后扫描并选择新首选父节点。
示例:C 为当前根节点但路由器信号退化(-85 dB),触发选举后 B 当选;B 发切换请求、C 确认;B 断父连路由器成为新根节点;C 断路由器、保持下行连接、入空闲、选择 B 为首选父节点并成为第二层节点。切换后 C 的子网络布局相似,但 C 子网络内每个节点都因切换而深了一层;若节点因切换获得新首选父节点,后续"父节点切换"会进一步调整布局。
根节点切换必须依赖选举,因此仅支持自组织网络。换言之,使用指定根节点时无法进行根节点切换。
父节点切换(Parent Node Switching)
父节点切换指子节点把上行连接切换到更浅层的另一父节点,自动发生:当更浅层的潜在父节点可用时(例如因异步上电复位出现),子节点自动更换上行连接。所有潜在父节点周期性发送信标帧,子节点据此扫描更浅层父节点的可用性。凭借父节点切换,自组织网络能动态调整布局,保证每条连接有良好 RSSI 并最小化网络层数。
由于父节点切换的存在,上行传输过程中可能发生丢包(官方文档明确警告)。
数据传输
ESP-WIFI-MESH 数据包
网络数据传输使用 ESP-WIFI-MESH 数据包,其完全包含在 Wi-Fi 数据帧的帧体(frame body)内。多跳传输中,同一个 ESP-WIFI-MESH 数据包每经过一跳由不同的 Wi-Fi 数据帧承载。
- 头部(header):包含源与目的节点的 MAC 地址。选项字段(options)存放特殊类型数据包的信息,如组播传输、来自外部 IP 网络的数据包(对应宏
MESH_OPT_SEND_GROUP与MESH_OPT_RECV_DS_ADDR,定义见 esp_mesh.h,取值分别为 7 与 8)。 - 负载(payload):实际应用数据,可为原始二进制数据,或以应用层协议(如 HTTP、MQTT、JSON)编码(对应
mesh_proto_t类型)。
向外部 IP 网络发送 ESP-WIFI-MESH 数据包时,头部目的地址字段存放目标服务器的IP 地址与端口而非节点 MAC 地址(对应
mesh_addr_t);TCP/IP 报文的组包由根节点完成。
组控制与组播(Multicasting)
组播允许单个 ESP-WIFI-MESH 数据包同时发送给网络内多个节点,可通过指定目标节点列表或指定预配置节点组实现,两种方式都经由esp_mesh_send()调用:
- 按目标列表组播:先把数据包目的地址设为组播组地址(
01:00:5E:xx:xx:xx),表示这是带地址组的组播包、地址应从头部选项获取;再把各目标节点 MAC 地址作为选项列出(mesh_opt_t与MESH_OPT_SEND_GROUP)。此方式无需预先设置,但因每个目标 MAC 都要写入头部选项,会产生较大额外开销。 - 按组 ID 组播:发送给预配置的节点组。每个组由唯一 ID 标识,节点通过
esp_mesh_set_group_id()加入组;发送时把目的地址设为组 ID,并置位MESH_DATA_GROUP标志(值为 0x40)。此方式开销更小,但要求节点预先分组。
组播期间网络内所有节点在 MAC 层仍会收到该数据包,但不在 MAC 地址列表或目标组中的节点会直接将其过滤丢弃。
广播(Broadcasting)
广播允许单个数据包同时发送给网络内所有节点。每个节点本质上把广播包转发给所有上行/下行连接,使其尽快传播全网。为避免浪费带宽,ESP-WIFI-MESH 采用如下规则:
- 中间父节点从父节点收到广播包时,转发给每个子节点并为自己保留一份副本;
- 中间父节点作为广播源时,向父节点上行发送、向每个子节点下行发送;
- 中间父节点从某子节点收到广播包时,转发给父节点与其余子节点并保留副本;
- 叶节点作为广播源时,直接把包发送给父节点;
- 根节点作为广播源时,向所有子节点发送;
- 根节点从某子节点收到广播包时,转发给其余子节点并保留副本;
- 节点收到源地址等于自身 MAC 的广播包时,将其丢弃;
- 中间父节点收到来自父节点的广播包,而该包最初源自其某个子节点时,将其丢弃。
上行流控(Upstream Flow Control)
ESP-WIFI-MESH 依靠父节点控制其直连子节点的上行数据流。为防止上行传输过载导致父节点消息缓冲区溢出,父节点会为每个子节点分配一个上行传输配额,称为接收窗口(receiving window)。每个子节点在允许上行传输前必须先申请接收窗口,窗口大小可动态调整。一次上行传输步骤如下:
- 每次传输前,子节点向父节点发送窗口请求,其中包含与待传数据包对应的序列号;
- 父节点收到请求后,将该序列号与该子节点上一个已发送包的序列号比较,据此计算接收窗口大小并回传给子节点;
- 子节点按父节点指定的窗口大小发送数据包;窗口耗尽后必须再次申请才能继续发送。
ESP-WIFI-MESH不支持下行流控。
另外,由于根节点是外部 IP 网络的唯一接口,下游节点必须知晓根节点与外部 IP 网络的连接状态,否则会在根节点断网时仍向上游发送数据,造成无谓传输与丢包。ESP-WIFI-MESH 提供了基于根节点与外部 IP 网络连接状态稳定输出吞吐量的机制:根节点调用esp_mesh_post_toDS_state()向所有节点广播其外部网络连接状态。MESH_EVENT_TODS_STATE事件即携带该状态(见 internal_communication 示例 中事件处理)。
双向数据流
由于使用了路由表,ESP-WIFI-MESH 可完全在 mesh 层处理包转发;仅当根节点与外部 IP 网络收发数据包时才需要 TCP/IP 协议栈。这保证了网络内部任意节点之间的多跳传输无需经过 IP 层。
信道切换(Channel Switching)
背景:Wi-Fi 中的信道切换
传统 Wi-Fi 中,信道是预定义的频率范围。基础设施基本服务集(BSS)内,服务 AP 与其连接站点必须工作在同一工作信道(1~14),信标在该信道发送。物理相邻、同信道工作的 BSS 会相互干扰、性能下降。
为让 BSS 适应变化的物理层条件,Wi-Fi 提供网络信道切换机制:尝试把 BSS 迁移到新工作信道并尽量减小切换扰动——但一次切换未必能成功把所有站点迁移到新信道。基础设施网络中,信道切换由 AP 触发,目标为 AP 与所有连接站点同步切到新信道。实现方式是 AP 在周期性信标帧内嵌入Channel Switch Announcement(CSA)元素,向所有连接站点通告即将到来的切换,且 CSA 会出现在多个信标帧中直到切换发生。
CSA 元素包含新信道号(New Channel Number)与信道切换计数(Channel Switch Count)——后者表示距离切换还有多少个信标间隔(TBTT),每个信标帧递减一次,使站点与 AP 同步切换。
ESP-WIFI-MESH 网络信道切换
ESP-WIFI-MESH 同样利用携带 CSA 元素的信标帧。但多跳网络使切换更复杂:信标帧未必能单跳到达所有节点,因此依赖节点转发 CSA 元素使其传播全网。当带一个或多个子节点的中间父节点收到含 CSA 的信标帧时,会把 CSA(相同的新信道号与切换计数)包含在自身下一个信标帧中继续转发。由于所有节点收到相同 CSA,可依据信道切换计数同步切换——仅存在因 CSA 转发引入的短暂延迟。
网络信道切换可由路由器或根节点触发:
- 根节点触发:仅当网络未连接路由器时可用。调用
esp_mesh_switch_channel()后,根节点设置初始信道切换计数值并在信标帧中加入 CSA,第二层节点收到后在自己的信标帧中继续向下游转发。 - 路由器触发:网络连接路由器时,全网必须与路由器同信道,根节点将不被允许触发切换。根节点收到来自路由器的含 CSA 信标帧后,把 CSA 中的信道切换计数值改为自定义值再经信标帧下行转发,并相对该自定义值递减后续 CSA 的计数值。该自定义值可基于网络层数、当前节点数等因素确定。
自定义计数值的原因在于:ESP-WIFI-MESH 网络与路由器可能具有不同且变化的信标间隔,路由器提供的计数值对 mesh 网络无意义。使用自定义值后,网络内节点能相对 mesh 网络自身的信标间隔同步切换;但代价是 mesh 网络的信道切换与路由器及其连接站点的切换不同步。
网络信道切换的影响
- 因 mesh 切换与路由器切换不同步,二者间存在短暂信道差异:
- mesh 网络切换时刻取决于自身信标间隔与根节点自定义的信道切换计数值;
- 信道差异期间,根节点与路由器之间无法交换数据;
- 切换期间,根节点与中间父节点通过把 CSA 中Channel Switch Mode 字段置 1,要求已连接子节点停止发送直到切换完成;
- 频繁的路由器触发切换会降低 mesh 网络性能(可能由 mesh 网络自身引发,如与 mesh 网络的无线介质竞争)。若属此类,建议禁用路由器上的自动信道切换,改用指定信道。
- 存在短暂信道差异时,根节点技术层面仍与路由器保持连接:
- 若根节点在固定数量的路由器信标间隔内收不到任何信标或探测响应,才会断开;
- 断开后根节点自动重新扫描所有信道查找路由器。
- 若根节点收不到路由器的 CSA 信标帧(如路由器给的切换时间过短),路由器会在 mesh 网络不知情的情况下切换信道:
- 切换后根节点收不到路由器信标与探测响应,固定信标间隔数后断开;
- 断开后根节点重扫所有信道查找路由器;
- 整个过程根节点保持下行连接。
虽然网络信道切换目标是把所有节点迁移到新工作信道,但一次切换未必全部成功(例如因节点故障等原因)。
信道与路由器切换的配置组合
ESP-WIFI-MESH 支持通过配置启用/禁用自主信道切换与自主路由器切换(根节点自主连接另一台路由器)。两者取决于以下配置参数与运行条件:
- Allow Channel Switch(允许信道切换):
mesh_cfg_t结构体的allow_channel_switch字段,置位后允许网络动态切换信道。 - Preset Channel(预设信道):
mesh_cfg_t结构体的channel字段设为目标信道号。若该字段未设置,allow_channel_switch将被覆盖,始终允许信道切换。 - Allow Router Switch(允许路由器切换):
mesh_router_t结构体的allow_router_switch字段,置位后允许动态切换到不同路由器。 - Preset Router BSSID(预设路由器 BSSID):
mesh_router_t结构体的bssid字段设为期望路由器 BSSID。若该字段未设置,allow_router_switch将被覆盖,始终允许路由器切换。 - Root Node Present(根节点存在):根节点的存在与否也会影响切换是否被允许。
下表展示参数/条件组合对信道切换与路由器切换许可的影响(X表示"不关心"):
| 预设信道 | 允许信道切换 | 预设路由器 BSSID | 允许路由器切换 | 根节点存在 | 允许的切换 |
|---|---|---|---|---|---|
| N | X | N | X | X | 信道与路由器 |
| N | X | Y | N | X | 仅信道 |
| N | X | Y | Y | X | 信道与路由器 |
| Y | Y | N | X | X | 信道与路由器 |
| Y | N | N | X | N | 仅路由器 |
| Y | N | N | X | Y | 信道与路由器 |
| Y | Y | Y | N | X | 仅信道 |
| Y | N | Y | N | N | 无 |
| Y | N | Y | N | Y | 仅信道 |
| Y | Y | Y | Y | X | 信道与路由器 |
| Y | N | Y | Y | N | 仅路由器 |
| Y | N | Y | Y | Y | 信道与路由器 |
对应到示例配置:internal_communication/main/mesh_main.c 中cfg.channel = CONFIG_MESH_CHANNEL,而 Kconfig.projbuild 中MESH_CHANNEL范围为 0~14、默认 0(0 即"未预设信道",对应上表中 Preset Channel = N 的行为)。
网络性能
ESP-WIFI-MESH 网络性能可从以下指标评估:
- 网络构建时间(Network Building Time):从零开始构建网络所需时间;
- 自愈时间(Healing Time):检测到节点故障并执行相应自愈动作(如产生新根节点、建立新连接)所需时间;
- 每跳延迟(Per-hop Latency):单条无线跳的数据传输延迟,即数据包在父节点与子节点间单向传输的时间;
- 网络节点容量(Network Node Capacity):网络可同时支持的节点总数,由节点可接受的最大下行连接数与网络允许的最大层数共同决定。
官方文档给出的常见性能指标(基于以下测试条件测得,实际因配置与运行环境而异):
- 网络构建时间:< 60 秒
- 自愈时间:
- 根节点故障:< 10 秒
- 子节点故障:< 5 秒
- 每跳延迟:10 ~ 30 毫秒
测试条件:测试设备数100、最大可接受下行连接数6、最大允许层数6。
吞吐量取决于丢包率与跳数。
根节点访问外部 IP 网络的吞吐量直接受网络节点数与路由器带宽影响。
不同部署的性能数据可能因网络配置与运行环境差异而波动较大。
补充说明
- 数据传输使用Wi-Fi WPA2-PSK 加密;
- Mesh 组网 IE(信息元素)使用 AES 加密。
在工程实践中,建议读者进一步阅读:
- 协议级 API 全集:components/esp_wifi/include/esp_mesh.h(含
esp_mesh_send/recv、esp_mesh_set_attempts、esp_mesh_set_vote_percentage、esp_mesh_waive_root、esp_mesh_fix_root、esp_mesh_set_parent、esp_mesh_switch_channel、esp_mesh_post_toDS_state、esp_mesh_set_group_id等全部接口); - 自组织建网参考实现:internal_communication 示例(覆盖路由表查询、点对点收发、全量 MESH_EVENT 事件处理)与 其 Kconfig 配置;
- 手动组网参考实现:manual_networking 示例(覆盖关闭自组织、扫描选父、
esp_mesh_set_parent指定父节点/根节点); - 网络层/应用层接入:ip_internal_network 示例(mesh netif 与 MQTT 应用)。
以上示例均可通过 ESP-IDF 构建系统直接编译烧录,实际搭建一个多跳 ESP-WIFI-MESH 网络进行验证。
【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考