ESP8266_SDK基礎(5)智能插座_完整項目代碼

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

這個項目用了幾天的時間才搞定,期間遇到了不少問題,也調整了不少代碼,在這裏免費分享給你們,但願同行能夠借鑑!版權全部,請勿轉載!!!web

代碼說明:
GPIO02用於指示wifi聯網狀態;
GPIO12用於指示開關動做;
GPIO14用於讀取按鍵,按下後設備重啓進入配網狀態;
wifi模塊重啓時20秒用於airkiss和esptouch配網;
聯網後會以3秒一次向服務器發送請求數據,反饋回來的數據讀取後進行控制;api

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\nHost: www.abcd.com\n\n";//待發送的字符結尾
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\n");
            break;
        case SC_STATUS_FIND_CHANNEL://在此階段進行配對鏈接
            os_printf("SC_STATUS_FIND_CHANNEL\n");
            break;
        case SC_STATUS_GETTING_SSID_PSWD://獲得wifi名字和密碼
            os_printf("SC_STATUS_GETTING_SSID_PSWD\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接口的配置參數,並保存到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\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]);//打印發廣播過來的設備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!\n");
}

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

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

    os_printf("Receive data:%s\r\n",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\n");//輸出低電平
                GPIO_OUTPUT_SET(GPIO_ID_PIN(12), 0);
            }else{
                os_printf("Output high level\n");//輸出高電平
                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\r\n",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\n");//打印獲取到ip
                        break;
                    case 1:
                        user_connect((struct ip_addr *)remote_ip,&info.ip,remote_port);//創建tcp鏈接
                        os_printf("connect to TCP\n");//鏈接到tcp
                        break;
                    case 2:
                        espconn_send(&user_conn, pbuf, os_strlen(pbuf));//發送數據
                        break;
                    case 3:
                        espconn_connect(&user_conn);//嘗試從新創建鏈接
                        os_printf("reconnect to TCP\n");//鏈接到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\n");//打印鏈接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\r\n", 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("\r\n");
    os_printf("SDK version:%s\r\n", system_get_sdk_version());
    /*系統初始化*/
    system_init_done_cb(init_done_cb);//系統初始化完成的回調函數
}
相關文章
相關標籤/搜索