28-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(官方API版,非RTOS版)

Posted yangfengwu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了28-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(官方API版,非RTOS版)相关的知识,希望对你有一定的参考价值。

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个小时自动断开问题

 

大家自己去测试。

 

以上是关于28-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(官方API版,非RTOS版)的主要内容,如果未能解决你的问题,请参考以下文章

26-ESP8266 SDK开发基础入门篇--编写WIFI模块 SmartConfig/Airkiss 一键配网

19-ESP8266 SDK开发基础入门篇--C# TCP客户端编写 , 连接和断开

6-ESP8266 SDK开发基础入门篇--操作系统入门使用

12-ESP8266 SDK开发基础入门篇--PWM,呼吸灯

7-ESP8266 SDK开发基础入门篇--串口处理数据,控制LED

21-ESP8266 SDK开发基础入门篇--C# TCP客户端 , 控制LED亮灭