前言
玩esp-01有断时间了,自己使用homeassistant搭建后台控制中心,esp-01做终端控制灯、控制风扇、温度检测等等。但在控制之前esp-01需要配网,说到配网baidu搜索到最多应该就是smartconfig,以及微信的airkiss。但是不管是smartconfi或airkiss配置网,配置过程很不稳定,经常无法配置成功然后就只能断电重来;另一个原因是smartconfig需要app上配置很是麻烦。以上原因让我去寻找找到了另一种配网方式webconfig
webconfig基本思路
基本思路是ESP8266工作AP模式下,作为TCP Server监听TCP Client的连接。因为网页HTTP默认的端口是80,所以ESP8266作为TCP Server的端口需要设置为80。电脑连接上ESP8266的AP后,网页访问默认IP地址192.168.4.1,此时ESP8266就会收到来自网页的HTTP的Get请求,此请求数据为HTML格式。ESP8266收到请求后,读出保存在Flash中的HTML格式网页,并将带有HTML应答头的HTML网页发送给网页,网页端就可以显示出网页。
实现过程
从flash中读取上次保留的wifi信息,若有wifi信息进入station模式反之进程softap模式等待配网
void ICACHE_FLASH_ATTR
init_done_cb_init(void)
{
struct station_config stconfig;
struct softap_config apconfig;
print_chip_info();
os_memset(&stconfig, 0, sizeof(struct station_config));
wifi_station_get_config_default(&stconfig);
if(os_strlen(stconfig.ssid) != 0){
os_printf("ssid[%s]pass[%s]", stconfig.ssid, stconfig.password);
wifi_set_opmode(STATION_MODE);
wifi_station_set_reconnect_policy(TRUE);
wifi_station_set_auto_connect(TRUE);
}
else{
wifi_set_opmode(SOFTAP_MODE);
wifi_softap_get_config(&apconfig);
os_memset(apconfig.ssid, 0, 32);
os_memset(apconfig.password, 0, 64);
os_sprintf(apconfig.ssid,"ESP_%X",system_get_chip_id());
apconfig.authmode = AUTH_OPEN;
apconfig.ssid_len = 0;
apconfig.max_connection = 5;
wifi_softap_set_config(&apconfig);
wifi_station_set_reconnect_policy(FALSE);
wifi_station_set_auto_connect(FALSE);
wifi_station_disconnect();
}
#if PLUG_DEVICE
user_plug_init();
#elif FAN_DEVICE
user_fan_init();
#elif DS18B20_DEVICE
ds_init();
#endif
user_webserver_init(SERVER_PORT);
}
在TCP Server接收函数中实现解析GET请求获取配网页面,POST请求配置
#define HTML "<html><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/></head>" \
"<body align=\"center\"><h2>WiFi Settings</h2><form method='post'>" \
"<input type='text' name='ssid' placeholder='ssid'><br>" \
"<input type='text' name='pass' placeholder='pass'><br>" \
"<input type='submit'><br></form></body></html>"
LOCAL void ICACHE_FLASH_ATTR
webconfig_set_wifi(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, "pass=");
if ( p == NULL || q == NULL ){
return;
}
os_memcpy(ssid, p + 5, q - p - 6);
os_memcpy(pass, q + 5, os_strlen(urlparam) - (q - urlparam) - 5);
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(pass));
wifi_station_set_config(&stConf);
//重启
system_restart();
return ;
}
LOCAL void ICACHE_FLASH_ATTR
webserver_recv(void *arg, char *pusrdata, unsigned short length){
struct espconn *ptrespconn = arg;
URL_Frame *pURL_Frame = NULL;
char *pParseBuffer = NULL;
char szOut[512];
int stat = -1;
static char post_data[1024];
static bool last_post = false;
os_printf("length[%d]\r\n", length);
os_printf("recv[%s]\r\n", pusrdata);
if(check_data(pusrdata, length) == false){
os_printf("check error\r\n");
data_send(ptrespconn, false, NULL);
return ;
}
if(save_data(pusrdata, length) == false){
os_printf("save_data error\r\n");
data_send(ptrespconn, false, NULL);
return ;
}
pURL_Frame = (URL_Frame *)os_zalloc(sizeof(URL_Frame));
parse_url(precvbuffer, pURL_Frame);
os_printf("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((strlen(pURL_Frame->pSelect) == 1) &&
(os_strncmp(pURL_Frame->pSelect, "/", 1) == 0)){
//获取webconfig页面
html_send(ptrespconn, true, HTML);
}
if(os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
os_memset(szOut, 0, sizeof(szOut));
#if PLUG_DEVICE
stat = user_plug_getmethed(szOut);
#elif FAN_DEVICE
stat = user_fan_getmethed(szOut);
#elif DS18B20_DEVICE
stat = user_ds18b20_getmethed(szOut);
#endif
if(stat==0){
os_printf("get22szOut[%s]\r\n", szOut);
data_send(ptrespconn, true, szOut);
}else
data_send(ptrespconn, false, NULL);
}else
data_send(ptrespconn, false, NULL);
break ;
case POST:
os_printf("We have a POST request.\n");
pParseBuffer = (char *)os_strstr(precvbuffer, "\r\n\r\n");
if (pParseBuffer == NULL) {
break;
}
pParseBuffer += 4;
os_printf("pParseBuffer[%s]\r\n", pParseBuffer);
if((strlen(pURL_Frame->pSelect) == 1) &&
(os_strncmp(pURL_Frame->pSelect, "/", 1) == 0)){
//webconfig配网
webconfig_set_wifi(pParseBuffer);
data_send(ptrespconn, false, NULL);
break ;
}else if (os_strcmp(pURL_Frame->pSelect, "config") == 0 &&
os_strcmp(pURL_Frame->pCommand, "command") == 0) {
os_memset(szOut, 0, sizeof(szOut));
#if PLUG_DEVICE
stat = user_plug_postmethed(pParseBuffer, szOut);
#elif FAN_DEVICE
stat = user_fan_postmethed(pParseBuffer, szOut);
#elif DS18B20_DEVICE
stat = user_ds18b20_postmethed(pParseBuffer, szOut);
#endif
if(stat == 0){
os_printf("post22szOut[%s]\r\n", szOut);
data_send(ptrespconn, true, szOut);
}else
data_send(ptrespconn, false, NULL);
} else {
os_printf("\r\nparse error!\r\n");
data_send(ptrespconn, false, NULL);
}
break ;
}
if (precvbuffer != NULL){
os_free(precvbuffer);
precvbuffer = NULL;
}
os_free(pURL_Frame);
pURL_Frame = NULL;
}
最后
很简单。本人参考使用Web页面配置ESP8266的参数思路开发修改。