ESP8266_SDK基礎(5)智慧插座_完整專案程式碼

志遠電子發表於2019-05-10

環境及工具與第一章相同,這裡就不在重複!

這個專案用了幾天的時間才搞定,期間遇到了很多問題,也調整了很多程式碼,在這裡免費分享給大家,希望同行可以借鑑!版權所有,請勿轉載!!!

程式碼說明:
GPIO02用於指示wifi聯網狀態;
GPIO12用於指示開關動作;
GPIO14用於讀取按鍵,按下後裝置重啟進入配網狀態;
wifi模組重啟時20秒用於airkiss和esptouch配網;
聯網後會以3秒一次向伺服器傳送請求資料,反饋回來的資料讀取後進行控制;

user_main.c全部程式碼如下:

#include "ets_sys.h"
#include "osapi.h"

#include "user_interface.h"
#include "smartconfig.h"//配網
#include "espconn.h"//連線
#include "mem.h"
#include "gpio.h"//io口

#include "user_devicefind.h"
#include "user_webserver.h"

#if ESP_PLATFORM
#include "user_esp_platform.h"
#endif

void user_rf_pre_init(void){}
/*******************************************************************************
 * 結構體宣告
*******************************************************************************/
LOCAL struct espconn user_conn;//網路連線結構體
LOCAL os_timer_t os_timer;//定時器結構體
/*******************************************************************************
 * 全域性變數宣告
*******************************************************************************/
LOCAL uint8 order=0;//執行順序標記,1完成路由器連線,2完成TCP連線,3TCP連線斷開
LOCAL uint32 send=0;//傳送標記
LOCAL const uint8 remote_ip[4]={192,168,1,1};//遠端伺服器ip地址
LOCAL const uint8 remote_port=8080;//遠端伺服器埠號
LOCAL char headbuf[110]="GET /switch_gear.php?token=abcd&id=";//待傳送的字元開頭
LOCAL char *id="0000000000";//裝置id
LOCAL char *endbuf="&series=WP&version=01 HTTP/1.1
Host: www.abcd.com

";//待傳送的字元結尾
LOCAL char *pbuf=&headbuf[0];
/*******************************************************************************
 * 快連模式回撥函式||init_done_cb()內呼叫
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
smartconfig_done(sc_status status, void *pdata){
    switch(status){
        case SC_STATUS_WAIT://連線未開始,請勿在此階段開始連線
            os_printf("SC_STATUS_WAIT
");
            break;
        case SC_STATUS_FIND_CHANNEL://在此階段進行配對連線
            os_printf("SC_STATUS_FIND_CHANNEL
");
            break;
        case SC_STATUS_GETTING_SSID_PSWD://得到wifi名字和密碼
            os_printf("SC_STATUS_GETTING_SSID_PSWD
");
            break;
        case SC_STATUS_LINK://正在連線路由器
            os_printf("SC_STATUS_LINK
");
            struct station_config *sta_conf=pdata;
            wifi_station_set_config(sta_conf);//設定WiFi station介面的配置引數,並儲存到flash
            wifi_station_disconnect();//WiFi station介面從AP斷開連線
            wifi_station_connect();//WiFi station介面連線AP
            break;
        case SC_STATUS_LINK_OVER://獲取到ip,連線路由完成
            os_printf("SC_STATUS_LINK_OVER
");
            if(pdata!=NULL){
                uint8 phone_ip[4]={0};
                os_memcpy(phone_ip,(uint8*)pdata, 4);
                os_printf("Phone ip: %d.%d.%d.%d
",phone_ip[0],phone_ip[1],phone_ip[2],phone_ip[3]);//列印發廣播過來的裝置IP地址
            }
            smartconfig_stop();//停止配置
            break;
        default:break;
    }
}
/*******************************************************************************
 * 顯示函式||定時器回撥函式內呼叫
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
display(){
    LOCAL bool io=false;//io引腳標記
    LOCAL uint8 lag=0;//延遲標記

    if(lag<200){lag++;}
    switch(order){
        case 0:
            if(io==true){
                io=false;
                GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//GPIO12輸出低電平
            }else{
                io=true;
                GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//GPIO12輸出高電平
            }
            break;
        case 1:
            if(lag>10){
                lag=0;
                if(io==true){
                    io=false;
                    GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//點亮
                }else{
                    io=true;
                    GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄滅
                }
            }
            break;
        case 2:
            GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 0);//點亮
            break;
        case 3:
            GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄滅
            break;
        default:
            GPIO_OUTPUT_SET(GPIO_ID_PIN(2), 1);//熄滅
            break;
    }
}
/*******************************************************************************
 * TCP_client連線
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR//資料傳送成功
user_sent_cb(void *arg){
    send=0;
    order=2;
    os_printf("Data transmission completion!
");
}

LOCAL void ICACHE_FLASH_ATTR//連線正常斷開
user_discon_cb(void *arg){
    order=3;
    os_printf("Normal disconnection!
");
}

LOCAL void ICACHE_FLASH_ATTR//接收到資料
user_recv_cb(void *arg,char *pdata,unsigned short len){
    uint32 i=0;

    os_printf("Receive data:%s
",pdata);//列印接收到的資料
    for(i=0;i<(os_strlen(pdata));i++){
        if(*(pdata+i)==`&`&&*(pdata+i+1)==`{`){
            if(*(pdata+i+2)==`1`){
                os_printf("Output low level
");//輸出低電平
                GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);
            }else{
                os_printf("Output high level
");//輸出高電平
                GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 1);
            }
        }
    }
    os_free(pdata);//釋放接收記憶體
}

LOCAL void ICACHE_FLASH_ATTR//TCP連線建立成功
user_connect_cb(void *arg){
    struct espconn *pespconn=arg;

    espconn_regist_recvcb(pespconn,user_recv_cb);//資料接收
    espconn_regist_sentcb(pespconn,user_sent_cb);//資料傳送完成
    espconn_regist_disconcb(pespconn,user_discon_cb);//連線正常斷開
    espconn_send(pespconn, pbuf, os_strlen(pbuf));//傳送資料
}

LOCAL void ICACHE_FLASH_ATTR//TCP連線發生異常而斷開
user_recon_cb(void *arg, sint8 err){
    order=3;
    os_printf("Abnormal disconnection, error code for%d
",err);
}

LOCAL void ICACHE_FLASH_ATTR
user_connect(struct ip_addr *remote_ip,struct ip_addr *local_ip,int remote_port){
    /*espconn引數配置*/
    user_conn.type=ESPCONN_TCP;
    user_conn.state=ESPCONN_NONE;
    user_conn.proto.tcp=(esp_tcp *)os_zalloc(sizeof(esp_tcp));
    os_memcpy(user_conn.proto.tcp->local_ip,local_ip,4);
    os_memcpy(user_conn.proto.tcp->remote_ip,remote_ip,4);
    user_conn.proto.tcp->local_port=espconn_port();
    user_conn.proto.tcp->remote_port=remote_port;
    /*註冊連線回撥函式和重連回撥函式*/
    espconn_regist_connectcb(&user_conn,user_connect_cb);//註冊tcp連線成功後的回撥函式
    espconn_regist_reconcb(&user_conn,user_recon_cb);//註冊tcp連線發生異常時的回撥函式
    /*啟用連線*/
    espconn_connect(&user_conn);
}
/*******************************************************************************
 * 定時器回撥函式||init_done_cb()內呼叫
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
os_timer_cb(void){
    LOCAL uint32 lag[2]={0,0};

    LOCAL bool boot=false;//使用一次標記
    LOCAL struct ip_info info; //用於獲取IP地址的資訊

    if(lag[0]<500){lag[0]++;}
    if(lag[1]<500){lag[1]++;}

    if(lag[0]>200){//開機上電20秒用於快連模式
        wifi_get_ip_info(STATION_IF,&info);//獲取介面ip地址
        if(wifi_station_get_connect_status()==STATION_GOT_IP&&info.ip.addr!=0){//獲取到IP
            if(lag[1]>30){//每3秒處理一次資料
                lag[1]=0;
                switch(order){
                    case 0:
                        order=1;//標記已完成路由器連線
                        os_printf("got ip
");//列印獲取到ip
                        break;
                    case 1:
                        user_connect((struct ip_addr *)remote_ip,&info.ip,remote_port);//建立tcp連線
                        os_printf("connect to TCP
");//連線到tcp
                        break;
                    case 2:
                        espconn_send(&user_conn, pbuf, os_strlen(pbuf));//傳送資料
                        break;
                    case 3:
                        espconn_connect(&user_conn);//嘗試重新建立連線
                        os_printf("reconnect to TCP
");//連線到tcp
                        break;
                    default:break;
                }
            }
        }else{
            if(!boot){//未進行快連配置,則嘗試連線原AP
                boot=true;
                smartconfig_stop();//停止配置
                wifi_station_disconnect();//WiFi station介面從AP斷開連線
                wifi_station_connect();//WiFi station介面連線AP
                os_printf("connect to AP
");//列印連線AP
            }
        }

        /*復位按鍵掃描*/
        if(!GPIO_INPUT_GET(14)){
            system_restart();//系統重啟
        }

       /*自制看門狗,約10分鐘無響應,則重啟*/
        if(send<6500){send++;}
        if(send>6000){
            send=0;
            system_restart();//系統重啟
        }
    }

    /*呼叫顯示處理函式*/
    display();
}
/*******************************************************************************
 * 系統初始化完成回撥函式||user_init()內呼叫
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
init_done_cb(void){
    uint32 id_cache=system_get_chip_id();//獲取裝置id
    os_sprintf(id, "%d", id_cache);//將裝置id轉換為陣列
    os_printf("id:%s
", id);
    os_free(id_cache);//釋放記憶體
    strcat(pbuf,id);strcat(pbuf,endbuf);//拼接字串
    /*配置SmartConfig模式*/
    smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS);//設定快連模式的協議型別(esptouch與airkiss)
    smartconfig_start(smartconfig_done);//開啟快連模式
    /*配置軟體定時器 */
    os_timer_disarm(&os_timer);//關閉定時器
    os_timer_setfn(&os_timer,(ETSTimerFunc *) (os_timer_cb), NULL);//配置回撥函式
    os_timer_arm(&os_timer,100,true);//啟動定時器
}
/******************************************************************************
 * FunctionName : user_init
 * Description  : entry of user application, init user function here
 * Parameters   : none
 * Returns      : none
*******************************************************************************/
void user_init(void)
{
    /*設定串列埠波特率*/
    uart_init(115200,9600);
    /*配置GPIO2和GPIO12*/
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U ,FUNC_GPIO2);//用於指示連線狀態
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U,FUNC_GPIO12);//用於輸出動作
    PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U,FUNC_GPIO14);//用於按鍵輸入
    wifi_set_opmode(STATION_MODE);//配置為客戶端模式,並儲存到flash
    /*列印版本資訊*/
    os_printf("
");
    os_printf("SDK version:%s
", system_get_sdk_version());
    /*系統初始化*/
    system_init_done_cb(init_done_cb);//系統初始化完成的回撥函式
}

相關文章