ESP8266 实现TCP服务器功能 进行WIFI网络配置

一,基本原理

在ESP8266的 FLASH中开辟一块内存空间用于存储UTF-8格式的.HTML文件,网页要展示的内容就在.HTML文件中。

手机或者电脑连接到ESP8266的热点,访问ESP8266的设备IP地址,ESP8266返回wifi密码配置的网页内容.HTML文件内容在浏览器中呈现出来。

ESP8266接收从浏览器上传的数据,切换到Station模式,并连接到网络。

二,程序运行流程:

1.ESP8266上电启动配置为SoftAP模式。

2.使用手机或者电脑连接到ESP8266,访问ESP8266服务IP地址(默认192.168.4.1)。

3.ESP8266下发给电脑配置WIFI.HTML的文件。

4.通过浏览器输入账号及密码上传给ESP8266服务器。

5.ESP8266切换为Station模式并连接到网络。

三,程序讲解及具体实施

1.ESP8266_NONOSDk工程文件目录

1

/bin为烧录档输出目录

/driver_lib驱动目录GPIO,SPI,SDIO,UART

/examples为样例demo的目录

/html 主要是服务使用的.html文件存放目录

/include 存放驱动头文件的

/third_party主要存放基于网络的各种基本服务的驱动lwip,netif,mbedtls,ssl

任务执行为事件型调用

2.用户程序入口

在user_main.c文件的user_init(void)函数。调用user_webserver_init()

1

在webserver_listen()回调函数中配置数据发送和接收回调函数

1

在webserver_recv()函数中主要任务是解析从网络接收到的信息,从中找到目标信息,并执行相应动作,如数据发送,配置网络等

这里做简单展示函数具体请参考下文中。

1

浏览器下发数据如下

1

先经过parse_url()解析到pURL_Frame结构变量中,在接收回调函数中经过逻辑处理,执行相关应用。

webser.c文件内容主要是TCP服务相关的数据接收与发送回调函数。

#include "webser.h"

#include "c_types.h"

#include "ip_addr.h"

#include "eagle_soc.h"

#include "osapi.h"

#include "espconn.h"

#include "user_interface.h"

#include "driver/spi_interface.h"

//#include "user_webserver.h"

#include "spi_flash.h"

#include "mem.h"

static struct espconn webserver_espconn;

static esp_tcp webserver_esptcp;

#define INDEX_SIZE 1437

#define WEBCONFIG_SIZE 1541

#define WIFIDONE_SIZE 1293

static void ICACHE_FLASH_ATTR webserver_listen();

static void webserver_recv(void *arg,char *pusrdata,unsigned short length);

//初始化ap模式

static void ICACHE_FLASH_ATTR softAP_init(void)

{

struct softap_config soft_ap_Config;

wifi_set_opmode_current(SOFTAP_MODE);

soft_ap_Config.ssid_len = 14;

os_strcpy(soft_ap_Config.ssid,"zhihu-IAMLIUBO");

os_strcpy(soft_ap_Config.password,"imliubo123");

soft_ap_Config.authmode = AUTH_WPA2_PSK;

soft_ap_Config.beacon_interval = 100;

soft_ap_Config.channel = 1;

soft_ap_Config.max_connection = 2;

soft_ap_Config.ssid_hidden = 0;

wifi_softap_set_config_current(&soft_ap_Config);

os_printf("\r\n SSID: zhihu-IAMLIUBO \r\n PWD: IMLIUBO123 \r\n");

}

static ICACHE_FLASH_ATTR

void webserver_recon(void *arg, sint8 err)

{

struct espconn *pesp_conn = arg;

os_printf("webserver's %d.%d.%d.%d:%d err %d reconnect\n", pesp_conn->proto.tcp->remote_ip[0],

pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],

pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port, err);

}

static ICACHE_FLASH_ATTR

void webserver_discon(void *arg)

{

struct espconn *pesp_conn = arg;

os_printf("webserver's %d.%d.%d.%d:%d disconnect\n", pesp_conn->proto.tcp->remote_ip[0],

pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],

pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);

}

void ICACHE_FLASH_ATTR webserver_sent(void *arg){

struct espconn *pesp_conn = arg;

os_printf("webserver's %d.%d.%d.%d:%d sent\n", pesp_conn->proto.tcp->remote_ip[0],

pesp_conn->proto.tcp->remote_ip[1],pesp_conn->proto.tcp->remote_ip[2],

pesp_conn->proto.tcp->remote_ip[3],pesp_conn->proto.tcp->remote_port);

}

static void ICACHE_FLASH_ATTR

webconfig_get_wifi_ssid_pwd(char * urlparam)

{

char *p = NULL,*q = NULL;

char ssid[10],pass[15];

os_memset(ssid,0,sizeof(ssid));

os_memset(pass,0,sizeof(pass));

p = (char *)os_strstr(urlparam,"SSID=");

q = (char *)os_strstr(urlparam,"PASSWORD=");

if(p == NULL || q == NULL)

    {

return;

    }

os_memcpy(ssid, p + 5,q-p-6);

os_memcpy(pass,q+9,os_strlen(urlparam) - (q - urlparam) - 9);

os_printf("ssid[%s]pass[%s]\r\n",ssid,pass);

wifi_set_opmode(STATION_MODE);

struct station_config stConf;

stConf.bssid_set = 0;

os_memset(&stConf.ssid,0,sizeof(stConf.ssid));

os_memset(&stConf.password,0,sizeof(stConf.password));

os_memcpy(&stConf.ssid,ssid,os_strlen(ssid));

os_memcpy(&stConf.password,pass,os_strlen(stConf.password));

wifi_station_set_config(&stConf);

system_restart();

}

static bool ICACHE_FLASH_ATTR

parse_url(char *precv, URL_Frame *purl_frame)

{

char *str = NULL;

uint16 length = 0;

char *pbuffer = NULL;

char *pbufer = NULL;

if(purl_frame == NULL || precv == NULL)

    {

return false;

    }

pbuffer = (char *)os_strstr(precv,"Host:");

if(pbuffer != NULL)

    {

length = pbuffer - precv;

pbufer = (char *)os_zalloc(length + 1);

pbuffer = pbufer;

os_memcpy(pbuffer,precv,length);

os_memset(purl_frame->pSelect,0,URLSize);

os_memset(purl_frame->pCommand,0,URLSize);

os_memset(purl_frame->pFilename,0,URLSize);

if(os_strncmp(pbuffer,"GET ",4) == 0)

        {

purl_frame->Type = GET;

pbuffer += 4;

        }

else if(os_strncmp(pbuffer,"POST ",5) == 0)

        {

purl_frame->Type = POST;

pbuffer += 5;

        }

else

        {

return FALSE;

        }

os_printf("\r\n DDD_Type_DDD[%d] \r\n",purl_frame->Type);

pbuffer ++;

str = (char *)os_strstr(pbuffer, "HTTP");

if(str != NULL)

        {

length = str - pbuffer - 1;

os_memcpy(purl_frame->pFilename,pbuffer,length);

        }

os_printf("DDDpFilenameDDD[%s] \r\n",purl_frame->pFilename);

os_free(pbufer);

    }

pbuffer = (char *)os_strstr(precv, "SSID");

if (pbuffer != NULL)

    {

purl_frame->Type = POST;

os_memcpy(purl_frame->pCommand, "connect-wifi",strlen("connect-wifi"));

os_free(pbufer);

    }

}

static void ICACHE_FLASH_ATTR

data_send(void *arg,bool responseOK,char *psend)

{

uint16 length = 0 ;

char *pbuf = NULL;

char httphead[256];

struct espconn *ptrespconn = arg;

os_memset(httphead,0,256);

if(responseOK)

    {

os_printf(httphead,

"HTTP/1.0 200 OK\r\nContent-Length: %d\r\nServer: lwIP/1.4.0\r\n",

psend ? os_strlen(psend) : 0);

if(psend)

        {

os_sprintf(httphead + os_strlen(httphead),

"Content-type: text/html; charset=utf-8\r\nPragma: no-cache\r\n\r\n");

length = os_strlen(httphead) + os_strlen(psend);

pbuf = (char *)os_zalloc(length + 1);

os_memcpy(pbuf,httphead,os_strlen(httphead));

os_memcpy(pbuf + os_strlen(httphead),psend,os_strlen(psend));

        }

else

        {

os_printf(httphead + os_strlen(httphead),"\n");

length = os_strlen(httphead);

        }

    }

else

    {

os_sprintf(httphead,"HTTP/1.0 400 BadRequest\r\nContent-Length: 0\r\nServer: lwIP/1.4.0\r\n");

length = os_strlen(httphead);

    }

if(psend)

    {  

espconn_sent(ptrespconn,pbuf,length);

    }

else

    {

espconn_sent(ptrespconn,httphead,length);

    }

if(pbuf)

    {

os_free(pbuf);

pbuf = NULL; 

    }

}

static void ICACHE_FLASH_ATTR webserver_recv(void *arg,char *pusrdata,unsigned short length)

{

URL_Frame *pURL_Frame = NULL;

char *pParseBuffer = NULL;

char *html = NULL;

SpiFlashOpResult ret = 0;

os_printf("\r\n\r\n length:%d \r\n", length);

os_printf("recv:%s",pusrdata);

pURL_Frame = (URL_Frame *)os_zalloc(sizeof(URL_Frame));

parse_url(pusrdata,pURL_Frame);     //解析网页数据

os_printf("\r\n Type[%d] \r\n",pURL_Frame->Type);

os_printf("pSelect[%s] \r\n",pURL_Frame->pSelect);

os_printf("pCommand[%s] \r\n",pURL_Frame->pCommand);

os_printf("pFilename[%s] \r\n",pURL_Frame->pFilename);

switch ( pURL_Frame->Type )

    {

case GET:

os_printf("We have a GET request.\n");

if(pURL_Frame->pFilename[0] == 0)

                        {

html = (char *)os_zalloc(INDEX_SIZE);

if(html == NULL)

                            {

os_printf("os_zalloc error !\r\n");

goto _temp_exit;

                            }

ret = spi_flash_read(508*4096,((uint32 *)html),INDEX_SIZE);

if(ret != SPI_FLASH_RESULT_OK)

                            {

os_printf("spi_flash_read err:%d \r\n",ret);

os_free(html);

html = NULL;

goto _temp_exit;

                            }

html[INDEX_SIZE] = 0;

data_send(arg,true,html);

os_free(html);

html = NULL;

                        }

if(strncmp(pURL_Frame->pFilename,"WebConfig.html",strlen("WebConfig.html")) == 0)

                        {

html = (char *)os_zalloc(WEBCONFIG_SIZE);

if(html == NULL)

                            {

os_printf("os_zalloc error!\r\n");

goto _temp_exit;

                            }

ret = spi_flash_read(510*4096,(uint32 *)html,WEBCONFIG_SIZE);

if(ret != SPI_FLASH_RESULT_OK)

                            {

os_printf("spi_flash_read err:%d\r\n",ret);

os_free(html);

html = NULL;

goto _temp_exit;

                            }

html[WEBCONFIG_SIZE] = 0;

data_send(arg,true,html);

os_free(html);

html = NULL;

                        }

break;

case POST:

os_printf("We have a POST request.\r\n");

if(strncmp(pURL_Frame->pCommand,"connect-wifi",strlen("connect-wifi"))==0)

                    {

os_printf("connect wifi \r\n");

html = (char *)os_zalloc(WIFIDONE_SIZE);

if(html == NULL)

                        {

os_printf("os_zalloc error! \r\n");

goto _temp_exit;

                        }

ret = spi_flash_read(512*4096,(uint32 *)html,WIFIDONE_SIZE);

if(ret != SPI_FLASH_RESULT_OK)

                        {

os_printf("spi_flash_read err:%d \r\n",ret);

os_free(html);

html = NULL;

goto _temp_exit;

                        }

html[WIFIDONE_SIZE] = 0;

data_send(arg,true,html);

os_free(html);

html = NULL;

//这里要做个等待检测到wifi发送停止后再进行接下去的动作

webconfig_get_wifi_ssid_pwd(pusrdata);

                    }

break;

default:

break;

    }

_temp_exit:

        ;

if( pURL_Frame != NULL )

    {

os_free(pURL_Frame);

pURL_Frame = NULL;    

    }

}

static void ICACHE_FLASH_ATTR

webserver_listen(void *arg)

{

struct espconn *pesp_conn = arg;

espconn_regist_recvcb(pesp_conn, webserver_recv);

espconn_regist_disconcb(pesp_conn, webserver_discon);

espconn_regist_sentcb(pesp_conn, webserver_sent);

}

void ICACHE_FLASH_ATTR user_webserver_init(uint32 port)

{

softAP_init();

webserver_espconn.type = ESPCONN_TCP;

webserver_espconn.state = ESPCONN_NONE;

webserver_espconn.proto.tcp = &webserver_esptcp; 

webserver_espconn.proto.tcp->local_port = port;

espconn_regist_connectcb(&webserver_espconn,webserver_listen);

espconn_regist_reconcb(&webserver_espconn,webserver_recon);

espconn_accept(&webserver_espconn);

}


源码下载地址

https://gitee.com/LogicExpress/esp8266.git

项目合作交朋友扯淡都可以联系我 18665321219

posted @ 2021-02-19 16:24  steven_lg  阅读(2470)  评论(0编辑  收藏  举报