1. 程式人生 > >Esp8266學習之旅⑥ 瞭解SmartConfig與Airkiss一鍵配網,給8266一鍵配網上雲端。(帶Demo)

Esp8266學習之旅⑥ 瞭解SmartConfig與Airkiss一鍵配網,給8266一鍵配網上雲端。(帶Demo)

目錄:

一、前言

聽到 SmartConfig這個單詞,字義上就是智慧配置,但是我們電子發燒友都是稱之為一鍵配網,

聽到Airkiss這個單詞就有點意思了。飛吻,象徵著速度飛一般的快。

這裡寫圖片描述

本博文的配網截圖:

這裡寫圖片描述

8266串列埠列印資訊:

這裡寫圖片描述

1.1、問題來了。

①、都不懂!SmartConfig和AirKiss是什麼東東!

  • 答:大家買智慧裝置時候都會出現以下介面提示您要輸入wifi賬號和密碼!然後下一步操作搜尋,裝置成功連線網路成功就可以使用啦!這裡就引出了, SmartConfig 和 AirKiss 就是給裝置配網的方式,皆為無線操作給裝置發wifi名字和密碼的方式。

①、既然方式一樣,二者有啥不同嗎!

  • 答:其實原理都是一樣,手機發出廣播,這廣播裡面有WIfi的名字 和密碼,也就是接下來裝置要接收的廣播,以及去連線這個Wifi! 其然 ,Airkiss是微信專門為物聯網配網開發的,是對SmartConfig的進一步封裝。如果你沒有去整合微信開發環境去給裝置配網,大不可去了解airkiss,只需要懂得用SmartConfig配網就好了!

二、原理。

這裡我引用微信官網畫的一個通俗易懂一張圖片。圖下的智慧插座是要配網的裝置,而微信客戶端也就是我們的傳送端:APP軟體 ;

  • 步驟

    • 在APP軟體輸入將要連線的WIfi的名字和密碼。

    • 之後App會空中髮網,帶有wifi的名字和密碼的資訊暴露。

    • 智慧裝置收到資訊廣播之後,嘗試不斷去連線,一旦連線成功。就會返回資訊給APP通知配網成功!

配網原理

三、走進8266一鍵配網的SmartConfig。

1. 翻開8266的程式設計SDK手冊,看看有哪些已經封裝好的介面,如圖 :

這裡寫圖片描述

2. 主要的函式方法,如圖 :

這裡寫圖片描述

這裡寫圖片描述

3. 為了更好展示主要方法,我做個表格,大家可以方便查閱,如下 :

函式名字 函式引數 返回值 備註
smartconfig_start() sc_callback_t cb:SmartConfig 狀態發⽣生改變時,進⼊入回撥函式 true:成功 ,false:失敗 開啟快連模式,快速連線 ESP8266 Station 到 AP
smartconfig_stop () SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISS true:成功 ,false:失敗 關閉快連模式,釋放 smartconfig_start 佔⽤用的記憶體。

三、電路圖與程式碼分析。

3、1 電路圖。

僅僅只是一個按鍵觸發配網模式,這個按鍵接GPIO14與GND端。

這裡寫圖片描述

3、2 程式碼分析。

第一步:按鍵初始化,這裡我使用的是機智雲SOC方案提煉出來的按鍵中斷初始化 hal_key.h 和 hal_key.c 檔案封裝。

第二步:按鍵觸發回撥的函式 :如下,其中的smartconfig_done是方法回撥函式,見第三步驟。


//短按按鍵函式回撥
LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) {

    //配置一鍵配網型別
    smartconfig_set_type(SC_TYPE_ESPTOUCH); 

    //開啟station模式
    wifi_set_opmode(STATION_MODE);

    //開始一鍵配網等待
    smartconfig_start(smartconfig_done);
}

第三步: smartconfig_done函式 : 如下

void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) {

switch (status) {

    //連線未開始,請勿在此階段開始連線。
    case SC_STATUS_WAIT:
        os_printf("SC_STATUS_WAIT\n");
        break;

    //發現WIfi通道
    case SC_STATUS_FIND_CHANNEL:
        os_printf("SC_STATUS_FIND_CHANNEL\n");
        break;

    //得到wifi名字和密碼
    case SC_STATUS_GETTING_SSID_PSWD:
        os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
        sc_type *type = pdata;
        if (*type == SC_TYPE_ESPTOUCH) {
            os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
        } else {
            os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
        }
        break;

     //已經獲取wifi名字與密碼在連線路由器
    case SC_STATUS_LINK:
        os_printf("SC_STATUS_LINK\n");
        struct station_config *sta_conf = pdata;
        wifi_station_set_config(sta_conf);
        wifi_station_disconnect();
        wifi_station_connect();
        break;

    //成功獲取到IP,連線路由完成。
    case SC_STATUS_LINK_OVER:
        if (pdata != NULL) {
        uint8 phone_ip[4] = { 0 };          
        os_memcpy(phone_ip, (uint8*) pdata, 4);     

        //打印發廣播過來的裝置IP地址    
        os_printf("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1],  phone_ip[2], phone_ip[3]);
        } 

        //停止配置
        smartconfig_stop();
        break;
    }

}

四、完整程式碼。


#include "../include/debug.h"
#include "hal_key.h"
#include "../include/uart.h"
#include "ets_sys.h"
#include "osapi.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"
#include "user_interface.h"
#include "smartconfig.h"
#include "airkiss.h"

//按鍵定義
#define GPIO_KEY_NUM                            1
#define KEY_0_IO_MUX                            PERIPHS_IO_MUX_MTMS_U
#define KEY_0_IO_NUM                            14
#define KEY_0_IO_FUNC                           FUNC_GPIO14

LOCAL key_typedef_t * singleKey[GPIO_KEY_NUM]; 
LOCAL keys_typedef_t keys; 

LOCAL esp_udp ssdp_udp;
LOCAL struct espconn pssdpudpconn;
LOCAL os_timer_t ssdp_time_serv;

uint8_t lan_buf[200];
uint16_t lan_buf_len;
uint8 udp_sent_cnt = 0;

void ICACHE_FLASH_ATTR smartconfig_done(sc_status status, void *pdata) {

    switch (status) {

    //連線未開始,請勿在此階段開始連線
    case SC_STATUS_WAIT:
        os_printf("SC_STATUS_WAIT\n");
        break;

    //發現通道
    case SC_STATUS_FIND_CHANNEL:
        os_printf("SC_STATUS_FIND_CHANNEL\n");
        break;


    //得到wifi名字和密碼
    case SC_STATUS_GETTING_SSID_PSWD:
        os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
        sc_type *type = pdata;
        if (*type == SC_TYPE_ESPTOUCH) {
            os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
        } else {
            os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
        }
        break;

    case SC_STATUS_LINK:
        os_printf("SC_STATUS_LINK\n");
        struct station_config *sta_conf = pdata;

        wifi_station_set_config(sta_conf);
        wifi_station_disconnect();
        wifi_station_connect();
        break;

    //成功獲取到IP,連線路由完成。
    case SC_STATUS_LINK_OVER:
        os_printf("SC_STATUS_LINK_OVER \n\n");
        if (pdata != NULL) {
            uint8 phone_ip[4] = { 0 };
            os_memcpy(phone_ip, (uint8*) pdata, 4);
            os_printf("Phone ip: %d.%d.%d.%d\n", phone_ip[0], phone_ip[1],  phone_ip[2], phone_ip[3]);
        }

        //停止配置
        smartconfig_stop();
        break;
    }

}

//使用者自定義 RF_CAL 引數存放在 Flash 的扇區號
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void) {
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
    case FLASH_SIZE_4M_MAP_256_256:
        rf_cal_sec = 128 - 5;
        break;

    case FLASH_SIZE_8M_MAP_512_512:
        rf_cal_sec = 256 - 5;
        break;

    case FLASH_SIZE_16M_MAP_512_512:
    case FLASH_SIZE_16M_MAP_1024_1024:
        rf_cal_sec = 512 - 5;
        break;

    case FLASH_SIZE_32M_MAP_512_512:
    case FLASH_SIZE_32M_MAP_1024_1024:
        rf_cal_sec = 1024 - 5;
        break;

    default:
        rf_cal_sec = 0;
        break;
    }

    return rf_cal_sec;
}

void ICACHE_FLASH_ATTR user_rf_pre_init(void) {
}

//長按五秒按鍵回撥
LOCAL void ICACHE_FLASH_ATTR keyLongPress(void) {

}

//短按按鍵回撥
LOCAL void ICACHE_FLASH_ATTR keyShortPress(void) {
    os_printf("----------2 開始進去SmartConfig配網模式\n\n\n-----");
    smartconfig_set_type(SC_TYPE_ESPTOUCH); 
    wifi_set_opmode(STATION_MODE);
    smartconfig_start(smartconfig_done);
}

//按鍵初始化
LOCAL void ICACHE_FLASH_ATTR keyInit(void) {
    singleKey[0] = keyInitOne(KEY_0_IO_NUM, KEY_0_IO_MUX, KEY_0_IO_FUNC,
            keyLongPress, keyShortPress);
    keys.singleKey = singleKey;
    keyParaInit(&keys);
}

void ICACHE_FLASH_ATTR

user_init(void) {
    uart_init(BIT_RATE_115200, BIT_RATE_115200);
    os_printf("SDK version:%s\n", system_get_sdk_version());
    os_printf("----------BIT_RATE_115200\n\n\n-----");
    keyInit();
}

附加:相關除錯工具下載。