https://www.cnblogs.com/yangfengwu/p/11432795.html
注:這節實現的功能是WIFI模塊作為TCP 客戶端,連接咱的TCP服務器,然后實現透傳
本來想着做成斷線重連,但是無論如何測試,使用官方給的API默認大約2個小時以后就會主動斷開連接......
其實和咱 https://www.cnblogs.com/yangfengwu/p/11112014.html (TCP 服務器差不多)
先看下程序測試 (連接路由器測試,讓電腦和WIFI連接同一個路由器)
打開網絡調試助手



我的TCP服務器IP是 192.168.1.93 端口號是 60000 根據自己的修改


下載進去
配網就不說了,如果不是從前面看過來的,去看前面文章哈

正常運行后

測試通信


不用這個調試助手了,關掉這個調試助手,咱用另一個網絡調試助手,帶自動發送的
關掉調試助手以后,會發現客戶端一直在嘗試重新連接



啟動以后客戶端會自動連接上



好,現在看一下程序

連接放在了



#include "esp_common.h" #include "gpio.h" #include "uart.h" #include "esp_timer.h" #include "hw_timer.h" #include "pwm.h" #include "data_dispose.h" #include "espconn.h" #include "esp_wifi.h" #include "lwip/api.h" #include "crc.h" #include "smart_config.h" LOCAL os_timer_t public_timer;//定時器 u32 public_timer_cnt=0;//累加 u32 public_timer_state=0;//狀態 u32 public_timer_out=0;//超時 u32 public_timer_cnt1=0;//累加 extern u8 Usart1ReadBuff[Usart1ReadLen];//接收數據的數組 extern u32 Usart1ReadCnt;//串口1接收到的數據個數 extern u32 Usart1ReadCntCopy;//串口1接收到的數據個數拷貝 extern u8 Usart1ReadFlage;//串口1接收到一條完整數據 #define SSID "Learn8266" //無線名稱 #define PWD "11223344" //密碼 struct softap_config soft_ap_Config;//AP模式配置 //連接的路由器信息 #define APssid "qqqqq" #define APpassword "11223344" struct station_config stationConf; //TCP客戶端 struct espconn TcpClient; esp_tcp esptcp; ResolveData ResolveDataTest;//解析數據IEEE754 //uint32 pin_info_list[1][3]={PERIPHS_IO_MUX_GPIO5_U,FUNC_GPIO5,5};//配置GPIO5作為PWM輸出 //int duty[1]={0};//高電平時間是0us /****************************************************************************** * FunctionName : user_rf_cal_sector_set * Description : SDK just reversed 4 sectors, used for rf init data and paramters. * We add this function to force users to set rf cal sector, since * we don't know which sector is free in user's application. * sector map for last several sectors : ABCCC * A : rf cal * B : rf init data * C : sdk parameters * Parameters : none * Returns : rf cal sector *******************************************************************************/ uint32 user_rf_cal_sector_set(void) { 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 UartReadCallback()//定義一個函數 { espconn_send(&TcpClient,Usart1ReadBuff,Usart1ReadCntCopy);//串口接收的數據發給網絡 } //網絡接收到數據 void TcpClientRecv(void *arg, char *pdata, unsigned short len) { while(len--) { uart0_write_char(*(pdata++));//發送到串口 } } //斷開了連接 void TcpClientDisCon(void *arg) { dbg_printf("\nTcpClientDisCon\n"); espconn_connect(&TcpClient);//重新連接服務器 } int keep_alive_sec = 1;//設置心跳包 //連接上服務器 void TcpConnected(void *arg) { dbg_printf("\nTcpConnected\n"); //設置啟用心跳包 dbg_printf("\nespconn_set_opt=%d\n",espconn_set_opt(&TcpClient,ESPCONN_KEEPALIVE));//成功:0 失敗:其它 //客戶端斷開直接釋放內存 dbg_printf("\nespconn_set_opt=%d\n",espconn_set_opt(&TcpClient,ESPCONN_REUSEADDR));//成功:0 失敗:其它 //每隔ESPCONN_KEEPIDLE 開始啟動心跳包探測, //如果探測失敗,則每每隔 ESPCONN_KEEPINTVL 發送一次探測, //探測 ESPCONN_KEEPCNT 次以后還是無相應,則進入 espconn_reconnect_callback 回調函數 (espconn_regist_reconcb(&TcpClient, TcpConnectErr);//注冊連接出錯函數) keep_alive_sec = 30;//每隔30S開始一次探測 espconn_set_keepalive(&TcpClient,ESPCONN_KEEPIDLE,&keep_alive_sec); keep_alive_sec = 1;//開始探測后,心跳包每隔1S發送一次 espconn_set_keepalive(&TcpClient,ESPCONN_KEEPINTVL,&keep_alive_sec); keep_alive_sec = 3;//心跳包總共發送3次 espconn_set_keepalive(&TcpClient,ESPCONN_KEEPCNT,&keep_alive_sec); espconn_regist_recvcb(&TcpClient, TcpClientRecv);//設置接收回調 espconn_regist_disconcb(&TcpClient, TcpClientDisCon);//設置斷開連接回調 } //連接出錯 void TcpConnectErr(void *arg, sint8 err) { dbg_printf("\nTcpConnectErr=%d\n",err); espconn_connect(&TcpClient);//鏈接 } //監聽WiFi狀態改變 void wifi_event_monitor_handle_event_cb(System_Event_t *evt) { switch (evt->event_id) { case EVENT_STAMODE_CONNECTED://連接上路由器 dbg_printf("\n\tSTAMODE_CONNECTED\n"); dbg_printf("\tConnected to SSID %s, Channel %d\n", evt->event_info.connected.ssid, evt->event_info.connected.channel); break; case EVENT_STAMODE_DISCONNECTED://和路由器斷開 dbg_printf("\n\tSTAMODE_DISCONNECTED\n"); dbg_printf("\tDisconnect from SSID %s, reason %d\n", evt->event_info.disconnected.ssid, evt->event_info.disconnected.reason); break; case EVENT_STAMODE_AUTHMODE_CHANGE://這個是 啥.. dbg_printf("\n\tSTAMODE_AUTHMODE_CHANGE\n"); dbg_printf("\tAuthmode: %u -> %u\n", evt->event_info.auth_change.old_mode, evt->event_info.auth_change.new_mode); break; case EVENT_STAMODE_GOT_IP://連接上路由器,並獲取了IP dbg_printf("\n\tGOT_IP\n"); dbg_printf("\tIP:" IPSTR ",Mask:" IPSTR ",GW:" IPSTR "\n", IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), IP2STR(&evt->event_info.got_ip.gw)); if(public_timer_state == 0)//正常運行下連接的路由器 { espconn_connect(&TcpClient);//連接TCP服務器 } break; case EVENT_STAMODE_DHCP_TIMEOUT://連接上路由器,但是路由器給WIFI模塊分配IP等信息超時了 dbg_printf("\n\tSTAMODE_DHCP_TIMEOUT\n"); break; case EVENT_SOFTAPMODE_STACONNECTED://AP模式下,有設備連接WIFI模塊的無線 dbg_printf("\n\tSOFTAPMODE_STACONNECTED\n"); dbg_printf("\tStation: " MACSTR "join, AID = %d\n", MAC2STR(evt->event_info.sta_connected.mac), evt->event_info.sta_connected.aid); break; case EVENT_SOFTAPMODE_STADISCONNECTED://AP模式下,有設備斷開和WIFI模塊的無線連接 dbg_printf("\n\tSOFTAPMODE_STADISCONNECTED\n"); dbg_printf("\tstation: " MACSTR "leave, AID = %d\n", MAC2STR(evt->event_info.sta_disconnected.mac), evt->event_info.sta_disconnected.aid); break; case EVENT_SOFTAPMODE_PROBEREQRECVED://這是啥??,,,信號強度改變了 dbg_printf("\n\tSOFTAPMODE_PROBEREQRECVED\n"); dbg_printf("Station PROBEREQ: " MACSTR " RSSI = %d\n", MAC2STR(evt->event_info.ap_probereqrecved.mac), evt->event_info.ap_probereqrecved.rssi); break; default://其它錯誤 dbg_printf("\n\tswitch/case default\n"); break; } } //所有需要定時操作的函數在此函數中執行 LOCAL void ICACHE_FLASH_ATTR public_timer_callback(void) { if(GPIO_INPUT_GET(0) == 0)//按鍵按下 { public_timer_cnt++; if(public_timer_cnt>=300 && public_timer_state==0)//3S { dbg_printf("\nstartsmart\n"); public_timer_state=1; wifi_station_disconnect(); wifi_set_opmode(STATION_MODE); smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS);//SmartConfig + AirKiss xTaskCreate(smartconfig_task, "smartconfig_task", 256, NULL, 2, NULL); } } else { if(public_timer_state!=1 && public_timer_cnt>0 && public_timer_cnt<300)//短按復位 { dbg_printf("\nsystem_restart\n"); system_restart();//復位 } public_timer_cnt=0; } switch(public_timer_state) { case 0:break; case 1: public_timer_out++; public_timer_cnt1++; if(public_timer_out>=6000)//60S { dbg_printf("\nsmartconfig_timeout\n"); system_restart();//復位 } if(public_timer_cnt1>10)//LED快閃 { public_timer_cnt1=0; GPIO_OUTPUT_SET(2, 1-GPIO_INPUT_GET(2));//LED快閃 } break; default:break; } } /****************************************************************************** * FunctionName : user_init * Description : entry of user application, init user function here * Parameters : none * Returns : none *******************************************************************************/ void user_init(void) { GPIO_OUTPUT_SET(5, 1); GPIO_OUTPUT_SET(2, 0);//讓兩個燈初始的狀態一樣,GOIO2是反接的,0的時候是亮 GPIO_OUTPUT_SET(0, 1); uart_init_new(); printf("SDK version:%s\n", system_get_sdk_version()); wifi_set_opmode(STATIONAP_MODE);//配置WiFi的模式STATION + AP AP--連接WIFI自身的無線實現通信 STATION--wifi連接路由器,手機或者電腦也連接路由器,實現通信 soft_ap_Config.ssid_len = strlen(SSID);//熱點名稱長度,與你實際的名稱長度一致就好 memcpy(soft_ap_Config.ssid,SSID,soft_ap_Config.ssid_len);//實際熱點名稱設置,可以根據你的需要來 memcpy(soft_ap_Config.password,PWD,strlen(PWD));//熱點密碼設置 soft_ap_Config.authmode = AUTH_WPA2_PSK;//加密模式 soft_ap_Config.channel = 1;//信道,共支持1~13個信道 soft_ap_Config.max_connection = 4;//最大連接數量,最大支持四個,默認四個 wifi_softap_set_config_current(&soft_ap_Config);//設置 Wi-Fi SoftAP 接口配置,不保存到 Flash // wifi_softap_set_config(&soft_ap_Config);//設置 Wi-Fi SoftAP 接口配置,保存到 Flash UartCallbackRegister(UartReadCallback);//把 UartReadCallback 函數地址傳過去,在串口里面調用 os_timer_disarm(&public_timer); os_timer_setfn(&public_timer, (os_timer_func_t *)public_timer_callback, NULL); os_timer_arm(&public_timer, 10, 1);//10ms //設置連接的路由器,如果想直接測試不想配網,請去掉屏蔽 // stationConf.bssid_set = 0; // memcpy(stationConf.ssid,APssid,strlen(APssid));//路由器名稱 // memcpy(stationConf.password,APpassword,strlen(APpassword));//路由器密碼 // wifi_station_disconnect(); // wifi_station_set_config(&stationConf); wifi_set_event_handler_cb(wifi_event_monitor_handle_event_cb);//監聽WiFi狀態改變 //初始化TCP espconn_init(); TcpClient.type = ESPCONN_TCP; TcpClient.state = ESPCONN_NONE; TcpClient.proto.tcp = &esptcp; //服務器IP 地址 TcpClient.proto.tcp->remote_ip[0]=192; TcpClient.proto.tcp->remote_ip[1]=168; TcpClient.proto.tcp->remote_ip[2]=1; TcpClient.proto.tcp->remote_ip[3]=93; TcpClient.proto.tcp->remote_port = 60000;//連接端口號 espconn_regist_connectcb(&TcpClient, TcpConnected);//注冊連接函數 espconn_regist_reconcb(&TcpClient, TcpConnectErr);//注冊連接出錯函數 //espconn_regist_time(&TcpClient,0,0);//測試2個小時自動斷開問題 }
大家自己去測試。
https://www.cnblogs.com/yangfengwu/p/11458917.html
