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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM