拓 2023/04/09-2022/04/11
1. 简介
- github仓库
https://github.com/tonyp7/esp32-wifi-manager
- 说明
esp32-wifi-manager是esp32的纯C esp-idf组件,可通过门户网站轻松管理wifi网络。
esp32-wifi-manager是一个集所有功能于一身的wifi扫描仪、http服务器和dns守护程序,尽可能地使用最少的RAM。
esp32-wifi-manager将在启动时自动尝试重新连接到以前保存的网络,如果找不到保存的wifi,它将启动自己的接入点,您可以通过该接入点管理和连接到wifi网络。连接成功后,软件将在一段时间后(默认为1分钟)自动关闭接入点。
esp32-wifi-manager与esp idf 4.2及更高版本一起编译
2. 开发环境
《Ubuntu构建ESP32 ESP-IDF开发环境(简约版)》
3. 构建项目
3.1 复制代码
- 进入项目目录
cd ~/esp442
- 复制代码
进入https://github.com/tonyp7/esp32-wifi-manager
点击Latest进入最新发布版本:
右击Source code(tar.gz),复制链接地址。
下载v3.3.1.tar.gz
wget https://github.com/tonyp7/esp32-wifi-manager/archive/refs/tags/v3.3.1.tar.gz
- 改名
mv mv v3.3.1.tar.gz esp32-wifi-manager.tar.gz
- 解压
tar -zxvf esp32-wifi-manager.tar.gz
3.2 构建项目
- 进入example目录
cd ~/esp442/esp32-wifi-manager-3.3.1/examples/
- 进入default_demo目录
- 刷新esp-idf环境
get_idf
- 设定目标芯片
idf.py set-target esp32
- 配置项目
idf.py menuconfig
1) 将闪存设置为4MB
2) AP设置
可以在这里更改AP的SSID、Password以及其他参数。强烈建议保留默认值。
保存,退出。
- 编译项目
idf.py build
- 烧写项目
查看USB转串口的设备:
修改/dev/ttyUSB0设备权限:
sudo chmod 777 /dev/ttyUSB0
烧写:
idf.py -p /dev/ttyUSB0 -b 115200 flash
- 启用监视器
idf.py monitor -p /dev/ttyUSB0
当示例正常运行时,将观察到以下输出:
4. 测试
现在,使用任何具有wifi功能的设备,PC、平板、手机,您都会看到一个名为esp32的新wifi接入点。使用默认密码esp32pwd连接到它。您也可以访问wifi管理器的默认IP地址:http://10.10.0.1.
下面我用Win10 PC测试。
- 找到AP接入点
SSID为esp32
- 连接到esp32
密码:
esp32pwd
显示WiFi SSID列表。
- 选择要连接的SSID
- 输入Password,点击Join:
如果停在这里,或出现连接错误
把ESP32板子与WiFi路由器靠近一些试试。
- 等待连接
设置成功。
断开PC的esp32连接,连接的局域网WiFi上。
在串口上可以看到相应的操作信息:
STA的地址为:192.168.0.102。
一旦STA设置成功AP自动关闭。
如果STA连接失败,比如换了WiFi,AP自动打开。
- 通过WiFi连接ESP32
在浏览器输入STA地址就可以连接ESP32了:
5. 将esp32-wifi-manager作为组件添加到代码中
为了在esp-idf项目中有效地使用esp32-wifi-manager,请将整个esp32 wifi管理器存储库复制到组件子文件夹中。
您的项目应该是这样的:
- project_folder
- build
- components
- esp32-wifi-manager
- main
- main.c
完成后,您需要编辑项目根目录下的CMakeLists.txt文件来注册组件文件夹。这是通过添加以下行来完成的:
set(EXTRA_COMPONENTS_DIRS components/)
一个典型的CmakeLists.txt文件应该如下所示:
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS components/)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(name_of_your_project)
完成后,您现在可以在用户代码中添加头文件:
#include "wifi_manager.h"
您现在所需要做的就是调用wifi_manager_start();在您的代码中。如果您不确定,请参阅examples/default_demo。
6. 与esp32-wifi-manager互动
- 事件回调
典型的用例是在wifi管理程序最终连接到接入点时收到通知。为了做到这一点,您可以定义一个回调函数:
void cb_connection_ok(void *pvParameter){
ESP_LOGI(TAG, "I have a connection!");
}
然后进行回调注册:
wifi_manager_set_callback(WM_EVENT_STA_GOT_IP, &cb_connection_ok);
现在,每当事件被触发时,它都会调用这个函数。examples/default_demo包含了使用回调的示例代码。
- 事件列表
可以添加到回调函数的可能事件列表由wifi_manager.h中的message_code_t定义。它们如下:
WM_ORDER_START_HTTP_SERVER
WM_ORDER_STOP_HTTP_SERVER
WM_ORDER_START_DNS_SERVICE
WM_ORDER_STOP_DNS_SERVICE
WM_ORDER_START_WIFI_SCAN
WM_ORDER_LOAD_AND_RESTORE_STA
WM_ORDER_CONNECT_STA
WM_ORDER_DISCONNECT_STA
WM_ORDER_START_AP
WM_EVENT_STA_DISCONNECTED
WM_EVENT_SCAN_DONE
WM_EVENT_STA_GOT_IP
WM_ORDER_STOP_AP
在实践中,跟踪WM_EVENT_STA_GOT_IP和WM_EVENT_STA_DISCONNECTED是了解您的esp32是否有连接的关键。在使用esp32-wifi-manager的典型应用程序中,大多数情况下可以忽略其他消息。
- 事件参数
回调签名包括一个void*指针。对于大多数事件,此附加参数为空,并作为NULL值发送。一些选择事件具有用户代码可以利用的附加数据。它们如下所示:
WM_EVENT_SCAN_DONE与wifi_event_sta_scan_done_t*对象一起发送。
WM_EVENT_STA_DISCONNECTED与wifi_event_sta_disconnected_t*对象一起发送。
WM_EVENT_STA_GOT_IP与ip_event_got_ip_t*对象一起发送。
这些对象是标准的esp-idf结构,并在官方文档中进行了相应的说明。请参考:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_wifi.html
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/api-reference/network/esp_wifi.html
examples/default_demo演示了如何读取ip_event_got_ip_t对象来访问分配给esp32的ip地址。
7. 与http服务器交互
由于esp32-wifi-manager有自己的http服务器,您可能需要扩展此服务器,以便在应用程序中为自己的页面提供服务。可以使用标准的esp_http_server签名注册您自己的URL处理程序:
esp_err_t my_custom_handler(httpd_req_t *req){
然后注册处理程序:
http_app_set_handler_hook(HTTP_GET, &my_custom_handler);
examples/http_hook包含一个在/helloworld注册网页的示例
8. 线程安全和访问NVS
esp32-wifi-manager访问非易失性存储器进行存储,并将其配置加载到专用命名空间“espwifimgr”中。如果您想确保对NVS的并发访问永远不会发生冲突,可以包含NVS_sync.h并使用对NVS_sync_lock和NVS_sync_unlock的调用。
nvs_handle handle;
if(nvs_sync_lock( portMAX_DELAY )){
if(nvs_open(wifi_manager_nvs_namespace, NVS_READWRITE, &handle) == ESP_OK){
/* do something with NVS */
nvs_close(handle);
}
nvs_sync_unlock();
}
nvs_sync_lock等待作为参数发送给它的tick计数,以获取互斥。建议使用portMAX_DELAY。在实践中,nvs_sync_lock几乎永远不会等待。