文章目录
- 一.Smartconfig与Airkiss用于智能配网
- 1.Smartconfig
- 2.Airkiss
- 3.demo代码分析
- 二.保存和读取参数
- 三.socket连接(tcp client)
注:该部分的学习需要参考esp-idf下的2个demo程序:
- …\esp-idf\examples\wifi\smart_config:这里展示了如何智能配网
- …\esp-idf\examples\protocols\sockets\tcp_client:这里展示了如何用socket套接字做客户端的tcp连接,并收发数据
一.Smartconfig与Airkiss用于智能配网
上一章给模块wifi联网的例程中,模块连接的ssid和key是预先设定好的,但在实际的产品中不可能采用这种方式。能不能像手机一样,展示所有的wifi列表,然后点击输入密码连接,这种方式当然式可以的,问题就在于会增加产品的成本,而且在有些场景下不一定适合。所以这时候就引用了“空中配网技术”,比如smartconfig,airkiss,蓝牙辅助配网,阿里的零配等等。这里介绍ESP32如何通过smartconfig和airkiss两种方式连接上网络。
1.Smartconfig
智能硬件处于混杂模式下,监听网络中的所有报文;手机APP将当前连接的ssid和key编码到UDP报文中,通过广播或者组播的方式发送报文;智能硬件接收到UDP报文后解码,得到ssid和key,然后使用该组ssid和key去连接网络。这里需要用到esptouch手机app,下载地址在乐鑫科技官网上有展示
2.Airkiss
AirKiss是微信硬件平台提供的一种WIFI设备快速入网配置技术,要使用微信客户端的方式配置设备入网,需要设备支持AirKiss技术。Aiskiss的原理和smartconfig很类似,设备工作在混杂模式下,微信客户端发送包含ssid和key的广播包,设备收到广播包解码得到ssid和password。详细的可以参考微信官方的介绍。demo所用微信二维码如下(esp32进入智能配网模式后,直接用手机扫微信二维码即可完成对esp32的配网):
3.demo代码分析
esp32的wifi智能配网有两种模式,在代码中找到如下语句进行修改即可:
1、ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH)); //仅能使用esptouch的手机app配置
2、ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS)); //可以使用微信小程序配置
核心代码注释和分析如下
//事件处理句柄
static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data)
{
//初始状态,启动智能配网任务
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START)
{
xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
}
//如果连接ap失败,事件状态位会变为WIFI_EVENT_STA_DISCONNECTED,继续连接,并清除连接标志
else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED)
{
esp_wifi_connect();
xEventGroupClearBits(s_wifi_event_group, CONNECTED_BIT);
}
//在拿到IP之后事件状态会变更为IP_EVENT_STA_GOT_IP。在这里我们使用了xEventGroupSetBits,设置事件组标志,
else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP)
{
xEventGroupSetBits(s_wifi_event_group, CONNECTED_BIT);
}
//扫描完成
else if (event_base == SC_EVENT && event_id == SC_EVENT_SCAN_DONE)
{
ESP_LOGI(TAG, "Scan done");
}
//扫描后发现wifi信道
else if (event_base == SC_EVENT && event_id == SC_EVENT_FOUND_CHANNEL)
{
ESP_LOGI(TAG, "Found channel");
}
//获取了wifi的ssid和密码,则尝试连接ap
else if (event_base == SC_EVENT && event_id == SC_EVENT_GOT_SSID_PSWD)
{
ESP_LOGI(TAG, "Got SSID and password");
//格式化事件传递过来的参数,以便获取ssid和密码
smartconfig_event_got_ssid_pswd_t *evt = (smartconfig_event_got_ssid_pswd_t *)event_data;
wifi_config_t wifi_config; //定义一个wifi配置变量
uint8_t ssid[33] = {0};
uint8_t password[65] = {0};
bzero(&wifi_config, sizeof(wifi_config_t)); //wifi配置全部清除
memcpy(wifi_config.sta.ssid, evt->ssid, sizeof(wifi_config.sta.ssid)); //复制ssid到wifi配置变量
memcpy(wifi_config.sta.password, evt->password, sizeof(wifi_config.sta.password)); //复制密码到wifi配置变量
wifi_config.sta.bssid_set = evt->bssid_set; //复制是否需要设置目标ap的mac地址到wifi配置变量
if (wifi_config.sta.bssid_set == true) //如果需要则复制
{
memcpy(wifi_config.sta.bssid, evt->bssid, sizeof(wifi_config.sta.bssid));
}
memcpy(ssid, evt->ssid, sizeof(evt->ssid));
memcpy(password, evt->password, sizeof(evt->password));
ESP_LOGI(TAG, "SSID:%s", ssid);
ESP_LOGI(TAG, "PASSWORD:%s", password);
ESP_ERROR_CHECK(esp_wifi_disconnect()); //断开wifi
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); //设置wifi的sta参数
ESP_ERROR_CHECK(esp_wifi_connect()); //连接wifi
//保存wifi配网参数到nvs中
saveWifiConfig(&wifi_config);
}
//获取后应答完成
else if (event_base == SC_EVENT && event_id == SC_EVENT_SEND_ACK_DONE)
{
xEventGroupSetBits(s_wifi_event_group, ESPTOUCH_DONE_BIT); //事件组职位表示智能配网完成
}
}
//智能配网任务----------------------------------------
static void smartconfig_example_task(void *parm)
{
EventBits_t uxBits;
//ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH)); //仅能使用esptouch的手机app配置
ESP_ERROR_CHECK(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS)); //可以使用微信小程序配置
smartconfig_start_config_t cfg = SMARTCONFIG_START_CONFIG_DEFAULT(); //智能配网用默认的参数
ESP_ERROR_CHECK(esp_smartconfig_start(&cfg)); //智能配网启动
while (1)
{
//等待连接成功或配网结束的事件到来
uxBits = xEventGroupWaitBits(s_wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT, true, false, portMAX_DELAY);
if (uxBits & CONNECTED_BIT) //连接成功
{
ESP_LOGI(TAG, "WiFi Connected to ap");
}
if (uxBits & ESPTOUCH_DONE_BIT) //配网结束
{
ESP_LOGI(TAG, "smartconfig over");
esp_smartconfig_stop(); //结束配网
vTaskDelete(NULL); //自删除任务
}
}
}
以上的过程就完成了智能配网。
二.保存和读取参数
智能配网结束后,参数并没有保存,下次启动又得再次配网,那么就需要我们保存一下,保存在esp32的nvs存储中即可,保存和再次读取的核心代码如下:
//保存wifi配置参数结构体变量wifi_config到nvs------------------------------------------------
static void saveWifiConfig(wifi_config_t *wifi_config)
{
nvs_handle my_handle;
nvs_open("WIFI_CONFIG", NVS_READWRITE, &my_handle); //打开
ESP_ERROR_CHECK(nvs_set_blob(my_handle, "wifi_config", wifi_config, sizeof(wifi_config_t)));
ESP_ERROR_CHECK(nvs_commit(my_handle)); //提交
nvs_close(my_handle); //退出
}
//从nvs中读取wifi配置到给定的sta_config结构体变量
static esp_err_t readWifiConfig(wifi_config_t *sta_config)
{
nvs_handle my_handle;
nvs_open("WIFI_CONFIG", NVS_READWRITE, &my_handle); //打开
// sta_config = {
// .sta = {
// .ssid = "ssid",
// .password = "password",
// .bssid_set = false}}
uint32_t len = sizeof(wifi_config_t);
esp_err_t err = nvs_get_blob(my_handle, "wifi_config", sta_config, &len);
nvs_close(my_handle); //退出
return err;
}
按照以上操作保存了以后,下次再上电开机,直接读取就是用就可以了,不用再次配网。
假如我们想清除网络配置,比如我们到了一个新的地方,网络环境变了,需要配置,可以采用长按键的方式清除,重新配置,清除nvs保存参数的核心代码如下:
ESP_ERROR_CHECK(nvs_flash_erase());
三.socket连接(tcp client)
在联网操作中,最常用的就是tcp连接的客户端模式。
这里直接参看历程即可,过程比较明了,其中需要注意其中用到了一个公共组件example_connect():
/* 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.
*/
//注意去读example_connect的代码,里边有启动时wifi的一些配置,比如连接的wifi、用户名密码之类的
//这些配置在工程配置里有选项,比如选择wifi还是以太网之类的
ESP_ERROR_CHECK(example_connect());
这个公共组件位于:…\esp-idf\examples\common_components\protocol_examples_common文件夹之下,经过简单配置就可以选择我们要使用的网络、比如wifi还是以太网,是否ipv6及一些参数,这些东西就不再需要我们编写代码,其中如果你希望wifi的ssid和密码使用保存好的而不是配置的话,进入其中源代码文件connect.c下的esp_err_t example_connect(void)和void start(void)函数进行改写即可,建议改写这两个函数成为能够接收传递参数的形式进行联网,参数中直接把wifi配置传递过来。
更多推荐
ESP32学习笔记(4)wifi配网、参数保存、socket连接
发布评论