環境及工具與第一章相同,這裏就不在重複!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);//系統初始化完成的回調函數 }