ESP32 WiFi Mesh开发(二):ESP WiFi Mesh接口简析

2023-05-16

1 ESP-MDF架构

ESP-MDF是ESP-Mesh Development Framework的缩写,也就是”ESP Mesh开发架构”,其结构如下:

红框部分是WiFi Mesh协议栈,其代码路径是:

\esp-mdf\components\protocol_stacks\mdf_wifi_mesh

 

2 ESP WiFi Mesh协议栈

 

2.1 ESP WiFi Mesh配置

CONFIG_WIFI_MESH_MAX_LAYER                  

ESP WiFi Mesh树状拓扑结构最大层数

 

CONFIG_WIFI_MESH_AP_CONNECTIONS

AP模式支持最大连接数(应该是单个父节点可连接的最大子节点个数)

 

CONFIG_WIFI_MESH_VOTE_PERCENTAGE

投票比例阈值,ESP-MESH选举生成根节点时使用,即Mesh网络所有设备中超过多少比例赞成某节点成为根节点。

 

CONFIG_WIFI_MESH_AP_ASSOC_EXPIRE

softAP模式下连接失效时间,若softAP节点此时间内未收到子节点任何数据,则与子节点断开连接

 

CONFIG_WIFI_MESH_ATTEMPT_SCAN_TIME

ESP WiFi MESH内某节点成为根节点前最低扫描时间

 

CONFIG_WIFI_WIFI_MESH_AUTH_MODE

WiFi MESH认证模式 OPEN/WEP/WAP_PSK……

 

2.2 ESP WiFi Mesh数据结构

 

2.2.1 wifi_mesh_config_t

 

2.2.2 wifi_mesh_data_type_t

 

2.2.3 wifi_mesh_head_data_t

 

wifi_mesh_addr_t实际上的定义是:

初步看来,在ESP WiFi Mesh内的节点,用MAC来识别;如需通过根节点转发到外部IP网络,用IP+PORT模式。

 

2.3 ESP WiFi Mesh API

 

2.3.1 mdf_wifi_mesh_init

函数mdf_wifi_mesh_init(const wifi_mesh_config_t *config)用于初始化ESP WiFi Mesh,主要步骤:

<1> 设置ESP WiFi Mesh(默认)事件回调函数为esp_mesh_event_cb

<2> 设置ESP WiFI Mesh的主要参数,见2.1

这里涉及到一个数据结构:mesh_cfg_t

mdf_wifi_mesh_init参数wifi_mesh_config_t *config内的数据会被填入mesh_config最终通过esp_mesh_set_config设置。

<3> 调用esp_mesh_start启动ESP WiFi Mesh

 

2.3.2 mdf_wifi_mesh_send

2.3.2.1 mdf_wifi_mesh_send

函数mdf_wifi_mesh_send用于向ESP WiFi Mesh内任意节点或者外部IP网络发送数据包,输入参数是目的地址,数据类型,数据地址,数据大小;

发送的数据包会被拆成最大WIFI_MESH_PACKET_MAX_SIZE字节的单个包,并且加入序列号发送,发送最终调用esp_mesh_send执行;esp_mesh_send可以设置重发,并且有响应错误码。

2.3.2.2 esp_mesh_send

重点关注函数esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data,

int flag, const mesh_opt_t opt[],  int opt_count):

该函数是抽象出的用于ESP Mesh的通用接口。

<1> 该函数用于通过ESP WiFi Mesh发送数据包,可以向WiFi Mesh内任意设备或外部IP网络发送。该函数不可重入

<2> 参数const mesh_addr_t *to:

数据包目的地址(MAC/IP);

若数据包发送给根节点,该参数设置为NULL;

若数据包发送给外部IP网络,该数据包会首先传输给根节点,再由根节点传递到外部网络,此时需将IPv4:PORT写入参数。

<3> 参数const mesh_data_t *data:

发送的ESP Mesh数据包指针;

需指定数据协议,默认是二进制数据

(MESH_PROTO_BIN/MESH_PROTO_HTTP/MESH_PROTO_JSON/MESH_PROTO_MQTT)

需指定传输类型,默认是P2P类型

(MESH_TOS_P2P/MESH_TOS_E2E/MESH_TOS_DEF)

<4> 参数int flag:

MESH_DATA_ENC        /**< data encrypted(Unimplemented) */

MESH_DATA_P2P        /**< point-to-point delivery over the mesh network */

MESH_DATA_FROMDS    /**< receive from external IP network */

MESH_DATA_TODS       /**< identify this packet is target to external IP network */

MESH_DATA_NONBLOCK  /**< esp_mesh_send() non-block */

MESH_DATA_DROP       /**< in the situation of root having been changed, identify this packet can be dropped by new root */

MESH_DATA_GROUP      /**< identify this packet is target to a group address */

若数据包发送给ESP Mesh内部节点,需设置MESH_DATA_P2P;

若数据包发送给外部IP节点,需设置MESH_DATA_TODS;

若数据包由根节点发送给ESP Mesh内部节点,需设置MESH_DATA_FROMDS;

若数据包发送不阻塞,需设置MESH_DATA_NONBLOCK,默认阻塞;

在出现根节点变更时,MESH_DATA_DROP标识位意味着上传到外部IP网络的数据包可以被新的根节点丢弃。虽然尽力避免在根节点变更时的丢包现象,但因(新的根节点)调用esp_mesh_recv_toDS却未能及时读取而挂起过多数据包造成的新节点内存溢出仍然是个风险。总的来说,建议在于IP网络建立连接后再调用esp_mesh_recv_toDS,这样的话通过socket传输到外部网络的数据只来自于esp_mesh_recv_toDS,以避免不必要的内存拷贝动作。

<5> const mesh_opt_t opt[]:

若数据包发送给指定组,MESH_OPT_SEND_GROUP需被设置,且需指定目标接收地址(?);

若根节点发送来自外部IP网络的数据包到ESP Mesh内部设备,且需要该内部设备回复该数据包(到外部IP网络?),标识位MESH_OPT_RECV_DS_ADDR需要添加到目标域名地址。

<6> int opt_count:选项个数,通常情况下若只有1个opt即设置为1。

 

2.3.3 mdf_wifi_mesh_recv

2.3.3.1 mdf_wifi_mesh_recv

         函数mdf_wifi_mesh_recv接收通过ESP WiFi Mesh网络发送到自身的数据包。通过该函数可以获取数据包的源地址,数据包类型,数据包大小等。

         该函数调用esp_mesh_recv实现

 

2.3.4 mdf_wifi_mesh_root_send

         函数mdf_wifi_mesh_root_send用于接收来自外部IP网络的数据包并发送到ESP WiFi Mesh。

         参考:mdf_reconfig_network

 

2.3.5 mdf_wifi_mesh_root_recv

         函数mdf_wifi_mesh_root_recv用于接收来自ESP WiFi Mesh网络内且目的地址是外网的数据包(应该只有根节点使用)。根节点接收到这类数据包后会通过socket通讯传输到外网。

         若接收到此类数据包时根节点还未创建socker连接或者应用程序未调用接口

esp_mesh_recv_toDS发送数据包到外网,这些数据包会挂起到“toDS队列”(?)。

使用接口esp_mesh_get_rx_pending查询挂起的数据包个数以避免根节点内存溢出。

使用接口esp_mesh_set_xon_qsize配置队列的大小。若队列过大且esp_mesh_recv_toDS未及时调用(将数据包发送出列),会有导致大量系统内存溢出的风险;若队列设置过小,则会影响数据上传的效力。应根据实际应用调整接收队列大小,该队列默认大小是72。

 

2.3.6 esp_mesh_event_cb

 ESP WiFi Mesh协议栈的事件回调函数,事件:

<1> MESH_EVENT_PARENT_CONNECTED:连接到父节点

若当前节点为根节点,tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA)

否则tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)

<2> MESH_EVENT_PARENT_DISCONNECTED:与父节点连接断开

连接断开原因:

WIFI_REASON_HANDSHAKE_TIMEOUT/ WIFI_REASON_MIC_FAILURE/

WIFI_REASON_BEACON_TIMEOUT/ WIFI_REASON_AUTH_LEAVE/ WIFI_REASON_ASSOC_EXPIRE

(以上原因多为密码错误?)若当前节点为根节点,执行mdf_network_enable_blufi。(应该是蓝牙配网)

WIFI_REASON_AUTH_EXPIRE

认证超时且超过最大限定的超时次数,重启设备esp_restart

最后会执行mdf_server_deinit关闭相关网络服务。

<3> MESH_EVENT_ROOT_GOT_IP:获取到路由器分配的IP,启动根节点的相关服务任务mdf_server_init

<4> MESH_EVENT_ROOT_LOST_IP:失去分配的IP,重连esp_wifi_connect

<5> MESH_EVENT_ROUTING_TABLE_ADD/MESH_EVENT_ROUTING_TABLE_REMOVE:路由表变更

 

另外,事件还会被转发到用户自定义的处理函数中处理,大致的处理流程是:

mdf_device_init_handle注册用户自定义的回调函数

mdf_event_loop_init初始化事件处理任务mdf_event_loop_task

mdf_event_loop_task接收xQueueEvent队列的事件,调用回调函数处理

在esp_mesh_event_cb 的最后,通过mdf_event_loop_send将事件发送到mdf_event_loop_task, mdf_event_loop_task调用

用户自定义的事件回调函数执行用户处理。

 

3 ESP WiFi Mesh应用

由于ESP WiFi Mesh只有根节点可以与外部云服务器连接,其他节点必须通过根节点与云服务器交互,因此事实上根节点需要实现物联网关的功能。且由于根节点可能出现breakdown的情形,对于重新选举出的根节点(根节点变更意味着网关变更),仍然要继续维护整个ESP Mesh网络在云端状态的功能。

从mdf_wifi_mesh_send等接口来看,通过填写目的地址为IP:PORT可以让ESP Mesh子网节点数据包转发到外网,手机APP控制就是如此实现的。但若是云平台开发者以库形式提供认证流程(可能拿不到直接IP+PORT,只有收发回调接口)或者节点过多时,是通过根节点维护所有节点信息还是每个节点通过根节点转发自己维护,实现起来就比较复杂了。

相关还需具体项目的实践。目前为了实现demo,个人使用的方法是:

整个ESP WiFi Mesh只有根节点在云端实现认证;

认证完毕云端获取根节点保存的路由表,路由表内有当前Mesh网络所有设备的MAC信息;

云端通过MAC对设备进行控制;手机APP不在本地的情况下,过云端也是依此控制。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ESP32 WiFi Mesh开发(二):ESP WiFi Mesh接口简析 的相关文章

  • 在监控模式下使用 libpcap 嗅探 wifi

    问题陈述 Calling pcap activate 结果是PCAP ERR RFMON NOTSUP错误 即不支持 RF 监控模式 Context 我正在编写一个小型 C 程序 其工作是在监视器模式下监听我的笔记本电脑的 wifi 卡 该
  • 通过发送意图来启动 Android WiFi 管理器?

    我正在开发一个应用程序 我想要一个按钮 打开Android内置的WiFi菜单 我真的不想自己实现扫描和连接代码 我可以发送任何打开此菜单的意图吗 你应该使用ACTION PICK WIFI NETWORK http developer an
  • 如果未找到 Wi-Fi AP,则不会调用 NetworkCallback 的 onUnavailable() 方法

    我正在尝试将我的智能手机连接到 IOT 设备制作的 AP 我将connectivitymanager requestNetwork 与NetworkCallback 一起使用 一切正常 直到我关闭我的AP 并且显然requestNetwor
  • QML 将纹理应用于网格

    我正在尝试将图像纹理应用到 QML Qt 5 6 2 中的网格 我从示例 Shadow Map QML 开始 我想对 GroundPlane 进行纹理处理 材质和效果 qml 类应用于该 GroundPlane 网格 但我看不到如何应用图像
  • 有没有办法在 iOS 中以编程方式打开和关闭蓝牙和/或 WiFi?

    我正在寻找一种简单的方法来在 iOS 4 x 设备 iPhone 和 iPad 上切换蓝牙和 WiFi 的打开和关闭状态 当我在不同的位置和使用场景之间移动时 我会不断切换这些功能 现在需要多次点击并访问 设置 应用程序 我希望创建一个简单
  • iOS 获取链接速度(路由器速度测试)

    我想从 iOS 应用程序测试连接的路由器 wifi 调制解调器 的速度 我在这里找到了一些东西以编程方式获取链接速度 https stackoverflow com questions 2872058 get link speed prog
  • LibGDX 网格高度图法线和灯光

    我正在尝试让网格法线和灯光在 LibGDX 项目中工作 我已经有了从高度图纹理像素生成的纹理网格 问题是我无法正确点亮法线 另外 我不能 100 确定我在 TerrainChunk 类中正确设置了法线顶点 这是主类代码 package co
  • 如何使用 Objective-C 判断 iPhone 是否连接到 wifi 网络?

    在 Objective C iPhone 应用程序的上下文中 我需要能够判断 iPhone 是否已连接到 wifi 网络 并在可能的情况下侦听此状态的变化 有谁知道如何做到这一点 谢谢 加布伊 正如其他人提到的 可达性样本 https de
  • 通过 Wi-Fi 扫描 MFI 产品

    在 iOS 8 中 Apple 允许我们通过 Wifi direct 连接到设备并与其共享 WiFi 网络凭据 我们可以在 wifi 设置页面中执行此操作 也可以在应用程序中执行此操作 我正在尝试启动扫描来查找 wifi MFI 设备 我可
  • 删除 Meshlab 或 vcglib 中的自相交

    如何使用 Meshlab 应用程序或 vcglib 消除网格的自相交 这超出了范围 但 CGAL 中有一些函数 这仍然是实验性的 没有记录 但您可以使用该功能remove self intersections https github co
  • 在未越狱的 iOS 设备上启用/禁用 Wifi

    我的内部应用程序需要这个 我想在 ios 设备上切换 wifi 任何框架都可用 我尝试了以下代码 但它没有为我提供任何帮助 这不会改变我的 wifi 设置 Class BluetoothManager objc getClass Bluet
  • Android,在网络共享和连接到接入点时检测 WiFi 的本地 IP 和子网掩码

    我需要检测本地IP地址和子网掩码在 WiFi 网络上 在 Android 设备上 为了严格计算本地子网的 UDP 广播地址 当设备连接到接入点时 以下功能正常工作 Only works when NOT tethering WifiMana
  • 解释 802.11 Wireshark 跟踪中的帧控制字节

    我有一个 Wi Fi 捕获 pcap 我正在分析并发现 802 11 规范与 Wireshark 对数据的解释之间存在不一致之处 具体来说 我想要分解的是 2 字节 802 11帧控制 field 取自http www4 ncsu edu
  • Android 智能手机与其他设备之间的直接 Wifi 通信

    我想在 Android 设备和另一个设备 不是另一个 Android 智能手机 而是使用 C 实现的带 wifi 的设备 之间建立通信 通过 WIFI 我已经发现android提供了直接无线网络 http developer android
  • Android wifimanager总是返回true

    这简直要了我的命 任何帮助将不胜感激 我想使用 wifi 管理器连接到开放网络 我遇到的问题是该代码声称连接到任何网络 甚至是不存在的网络 下面是执行并使用网络 SSID 调用的完整代码 无论您传递给它什么字符串作为网络的 SSID 即使不
  • Unity:将网格物体轻轻包裹在其他网格物体周围?

    给定一个网格 如左侧的立方体对象 和另一个自定义的球状网格 右侧 如果更容易的话 它可以是另一种形状 Unity 和 C 中的一个在运行时如何将第二个网格轻轻包裹在第一个网格周围 谢谢 下面的方法 借助 VirtualMethodStudi
  • 我如何使用肘节检查连接性?

    我需要使用连接库检查应用程序内每个页面的连接性 所以我将在提供者内部使用一肘 问题是何时关闭流以便在用户关闭应用程序时可以处理它 像这样 import package connectivity connectivity dart overr
  • 用于平滑开放 3D 网格边缘的算法

    我有一个 3D 网格 它代表一个具有一些粗糙边界的表面 我想对其进行平滑处理 我使用半边数据结构来存储几何图形 因此我可以轻松地迭代边界边 顶点和面 我还可以使用点积和叉积轻松确定给定的一对边是否是凸 凹的 平滑边缘的最佳方法是什么 使它们
  • iPhone 在个人热点模式下不发送网络广播/组播

    根据最近的实证研究结果以及网络上的各种帖子 在启用了个人热点的 iPhone 上运行的应用程序似乎无法将广播和 或多播发送到个人热点的网络上 任何人都可以阐明这个问题的原因吗 应用程序 我有一个用跨平台 C 代码构建的 IOS 应用程序 它
  • Android 上的热点/网络共享模式下的组播支持

    我有一个原型 Android 应用程序 它正在侦听多播数据包以 发现 要与之通信的客户端 套接字设置类似于 InetAddress group InetAddress getByName 228 1 2 3 MulticastSocket

随机推荐