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工程文件目录
/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()
在webserver_listen()回调函数中配置数据发送和接收回调函数
在webserver_recv()函数中主要任务是解析从网络接收到的信息,从中找到目标信息,并执行相应动作,如数据发送,配置网络等
这里做简单展示函数具体请参考下文中。
浏览器下发数据如下
先经过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