文章目录

  • 公众号
  • esp8266教程目录
  • 前言
  • 一、ESP smartconfig是什么?
  • 1.1、常用的配网方式
  • 配网方式1:
  • 配网方式2:
  • 二、代码实现
  • 1.代码路径
  • 2.测试
  • 总结



前言


我们的手机有显示屏有触摸屏,可以使用界面的的方式选择连接那个wifi,然后输入密码用于连接网络。对于iot设备来说没有触摸屏也没有显示屏,如何把wifi名字和wifi密码传输到iot设备呢?为了解决这个问题所以就有了smartconfig。



一、ESP smartconfig是什么?


ESP smartconfig为ESP8266提供的两种智能配网使用demo,分别有ESPTouch和AirKiss,或者ESPTouch和AirKiss同时共存。ESPTouch为乐鑫研发的一种配网方式,AirKiss为TI研发的中配网方式,两种方式原理差不多。

1.1、常用的配网方式

配网方式1:


第一种是AP模式的方式配网,AP模式就是lot设备像路由器那样生成一个wifi,手机连接lot设备生成的wifi。iot设备运行一个tcp server,手机为tcp client,然后手机通过一个tcp方式将家庭路由器wifi的SSID和Password发送到iot设备。lot设备接收到wifi账号和密码之后从AP模式切换回Station模式,然后用过手机发送下来的SSID和Password连接家庭的路由器,lot连接上家庭路由器wifi之后,广播UDP数据包,数据包里面有lot设备名字和设备id和ip地址。手机在发送完家庭路由的wifi SSID和Password之后断开lot的wifi去连接家庭路由器wifi,然后监听等lot设备连上路由wifi后的发送的UDP数据包,然后通过UDP数据包中lot设备名字和设备id和ip地址知道那个设备已经连接上家庭路由,然后显示出来通知用户。

esp8266 AIRKISS配网教程 安信可 esp8266配网方式_UDP

配网方式2:


第二种配网方式就是我们要说的smartconfig方式,上面的AP模式的成功率为100%,但是有一点不好的是非常繁琐需要用户连接lot设备的wifi,smartconfig的方式优点是配网方式十分简单,但是不好的地方为由可能会配网失败或者有的家庭路由器不支持。smartconfig的原理是需要配网的iot设备配置为混杂模式,监听网络中的所有报文,然后手机发送UDP报文,在UDP报文中含有家庭路由的wifi密码和wifi ssid名字,因为在2.4g这个频段中有非常多的UDP报文和且有十几信道,所以iot需要解析很多报文,而且还需要不断的切换信道去抓取,所以有可能抓不到手机发送出来的UDP报文,从而配置失败。

esp8266 AIRKISS配网教程 安信可 esp8266配网方式_初始化_02

二、代码实现

1.代码路径

ESP8266_RTOS_SDK\examples\wifi\smart_config\main\smartconfig_main.c

代码如下(示例):

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event_loop.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
#include "esp_smartconfig.h"
#include "smartconfig_ack.h"

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

/* The event group allows multiple bits for each event,
   but we only care about one event - are we connected
   to the AP with an IP? */
static const int CONNECTED_BIT = BIT0;
static const int ESPTOUCH_DONE_BIT = BIT1;
static const char *TAG = "sc";

void smartconfig_example_task(void * parm);

static esp_err_t event_handler(void *ctx, system_event_t *event)
{
    /* For accessing reason codes in case of disconnection */
    system_event_info_t *info = &event->event_info;

    switch(event->event_id) {
    case SYSTEM_EVENT_STA_START:
        //step 4 wifi初始化化成功建立一个任务smartconfig_example_task
        xTaskCreate(smartconfig_example_task, "smartconfig_example_task", 4096, NULL, 3, NULL);
        break;
    case SYSTEM_EVENT_STA_GOT_IP:
        //step 8 lot设备连接上wifi
        xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
        break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
        ESP_LOGE(TAG, "Disconnect reason : %d", info->disconnected.reason);
        if (info->disconnected.reason == WIFI_REASON_BASIC_RATE_NOT_SUPPORT) {
            /*Switch to 802.11 bgn mode */
            esp_wifi_set_protocol(ESP_IF_WIFI_STA, WIFI_PROTOCAL_11B | WIFI_PROTOCAL_11G | WIFI_PROTOCAL_11N);
        }
        esp_wifi_connect();
        xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
        break;
    default:
        break;
    }
    return ESP_OK;
}

//step 3
static void initialise_wifi(void)
{
    //初始化tcpip 适配器
    tcpip_adapter_init();
    //初始化事件标准组用来事件同步
    wifi_event_group = xEventGroupCreate();
    ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    //设置为station模式启动wifi
    ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
    ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
    ESP_ERROR_CHECK( esp_wifi_start() );
}
//step 6
static void sc_callback(smartconfig_status_t status, void *pdata)
{
    switch (status) {
        case SC_STATUS_WAIT:
            ESP_LOGI(TAG, "SC_STATUS_WAIT");
            break;
        case SC_STATUS_FIND_CHANNEL:
            ESP_LOGI(TAG, "SC_STATUS_FINDING_CHANNEL");
            break;
        case SC_STATUS_GETTING_SSID_PSWD:
            ESP_LOGI(TAG, "SC_STATUS_GETTING_SSID_PSWD");
            break;
        //step 7    
        case SC_STATUS_LINK:
            //解析UPD包获取到路由器的wifi和密码
            ESP_LOGI(TAG, "SC_STATUS_LINK");
            wifi_config_t *wifi_config = pdata;
            ESP_LOGI(TAG, "SSID:%s", wifi_config->sta.ssid);
            ESP_LOGI(TAG, "PASSWORD:%s", wifi_config->sta.password);
            ESP_ERROR_CHECK( esp_wifi_disconnect() );
            //配置wifi账号和wifi密码
            ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, wifi_config) );
            //开始连接wifi
            ESP_ERROR_CHECK( esp_wifi_connect() );
            break;
        case SC_STATUS_LINK_OVER:
            ESP_LOGI(TAG, "SC_STATUS_LINK_OVER");
            if (pdata != NULL) {
                sc_callback_data_t *sc_callback_data = (sc_callback_data_t *)pdata;
                switch (sc_callback_data->type) {
                    case SC_ACK_TYPE_ESPTOUCH:
                        ESP_LOGI(TAG, "Phone ip: %d.%d.%d.%d", sc_callback_data->ip[0], sc_callback_data->ip[1], sc_callback_data->ip[2], sc_callback_data->ip[3]);
                        ESP_LOGI(TAG, "TYPE: ESPTOUCH");
                        break;
                    case SC_ACK_TYPE_AIRKISS:
                        ESP_LOGI(TAG, "TYPE: AIRKISS");
                        break;
                    default:
                        ESP_LOGE(TAG, "TYPE: ERROR");
                        break;
                }
            }
            xEventGroupSetBits(wifi_event_group, ESPTOUCH_DONE_BIT);
            break;
        default:
            break;
    }
}
//step 5
void smartconfig_example_task(void * parm)
{
    EventBits_t uxBits;
    //设置smartconfig为ESPTOUCH和AIRKISS两种方式共存
    ESP_ERROR_CHECK( esp_smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS) );
    //启动esp_smartconfig_start
    ESP_ERROR_CHECK( esp_smartconfig_start(sc_callback) );
    while (1) {
        uxBits = xEventGroupWaitBits(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);
        }
    }
}

void app_main()
{
    //step 1初始化nvs flash
    ESP_ERROR_CHECK( nvs_flash_init() );
    //step 2初始化wifi
    initialise_wifi();
}

2.测试

1.make flash -j8

2.在苹果商店或者安卓商店搜索ESPTOUCH,下载手机端软件。或者自己下载源代码编译
安卓:(https://github.com/EspressifApp/EsptouchForAndroid)
苹果:(https://github.com/EspressifApp/EsptouchForIOS)

下面是esp8266烧录后的打印输出。

I (162) boot: Loaded app from partition at offset 0x10000
mode : sta(ec:fa:bc:1d:33:e0)
add if0
SC version: V2.5.4
scandone
scandone
I (5) sc: SC_STATUS_FINDING_CHANNEL

TYPE: ESPTOUCH
T|PHONE MAC: 90 f0 52 0c 16 2d
T|AP MAC   : bc 5f f6 1b e8 1c
I (8) sc: SC_STATUS_GETTING_SSID_PSWD
T|pswd: 1234567890
T|ssid: TEST001
I (17) sc: SC_STATUS_LINK
I (17) sc: SSID:TEST001
I (17) sc: PASSWORD:1234567890
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 2
pm open phy_2,type:2 0 0
cnt 

connected with TEST001, channel 3
I (22) event: sta ip: 192.168.0.108, mask: 255.255.255.0, gw: 192.168.0.1
I (22) sc: WiFi Connected to ap
I (25) sc: SC_STATUS_LINK_OVER
I (25) sc: Phone ip: 192.168.0.108

I (25) sc: smartconfig over

总结


通过上面的代码smartconfig_main.c,上面的step1到step8就是smartconfig配置的步骤,不理解的同学可以仔细看看步骤加深理解