esp8266是一块很火的wifi模块,本文讲的是以esp8266作为服务器,PC作为客户端通信的。esp8266是在station模式的。SDK的版本号是ESP8266_NONOS_SDK-2.2.0.
在嵌入式的设备联网过程中,最大的痛点是联网要输入账号和密码。而大多数的嵌入式设备是没有GUI的。本文用的是airkiss通信协议。airkiss可以用在没有显示器交互的嵌入式设备联网中。联网步骤是:
1.打开手机wifi,连接至路由器上(该路由器也是嵌入式设备需要连接的路由器).
2.打开微信,进入乐鑫微信公众后,点击airkiss设备并点击。
,
。
3.出现上图,填上用户名和密码,点击连接。
下面我们进入代码讲解阶段。
一.airkiss讲解。在设备中,我们想要实现的功能是:没有连接到wifi的情况下,需要通过airkiss联网。之后保存wifi账号和密码。在下次开机时能自动联网。在要修改wifi账号和密码时,要通过airkiss修改账号和密码。
通过长按5s按键进入airkiss配置账号和密码。
按键初始化代码如下:
代码中,key_init_single是定义按键的,AIRKISS_KEY_IO_NUM,是对应引脚的ID号,AIRKISS_KEY_IO_MUX为引脚名称。AIRISSS_KEY_IO_FUNC为引脚功能设为GPIO功能。而smart_long_press_callback与smart_press_callback分别为长按与短按按键后的回调函数。长按回调函数如下:
.
在airkiss初始化之前,需要停止airkiss,smartconfig_stop为停止airkiss.而smartconfig_set_type为设置smartconfig类型。这里设置SC_TYPE_ESPTOUCH_AIRKISS,表示esptouch与airkiss兼容。当然也可以用SC_TYPE_AIRKISS.注意,在airkiss功能中,wifi只能在station模式,所以,要把wifi设置为STATION_MODE模式。smartconfig_start,开始airkiss配置。smartconfig_done.smartconfig_done为airkiss的回调函数。smartconfig_done代码如下:
void ICACHE_FLASH_ATTR
smartconfig_done(sc_status status, void *pdata)
{
switch(status) {
case SC_STATUS_WAIT:
os_printf("SC_STATUS_WAIT\n");
break;
case SC_STATUS_FIND_CHANNEL: //Open the application link at this stage
os_printf("SC_STATUS_FIND_CHANNEL\n");
break;
case SC_STATUS_GETTING_SSID_PSWD:
os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
sc_type *type = pdata;
if (*type == SC_TYPE_ESPTOUCH) {
os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
} else {
os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
}
break;
case SC_STATUS_LINK:
os_printf("SC_STATUS_LINK\n");
struct station_config *sta_conf = pdata;
wifi_station_set_config(sta_conf);
wifi_station_disconnect();
wifi_station_connect();
break;
case SC_STATUS_LINK_OVER:
os_printf("SC_STATUS_LINK_OVER\n");
if (pdata != NULL) {
//SC_TYPE_ESPTOUCH
uint8 phone_ip[4] = {0};
os_memcpy(phone_ip, (uint8*)pdata, 4);
os_printf("Phone ip: %d.%d.%d.%d\n",phone_ip[0],phone_ip[1],phone_ip[2],phone_ip[3]);
} else {
//SC_TYPE_AIRKISS - support airkiss v2.0
airkiss_start_discover();
}
smartconfig_stop();
break;
}
}
}在代码中status = SC_STATUS_GETTING_SSID_PSWD时,参数 void *pdata为sc_type *类型的指针变量,表示此次配置是AirKiss还是ESP-TOUCH;当status=SC_STATUS_LINK时,参数void*pdata为struct station_config类型的指针变量;当status = SC_STATUS_LINK_OVER时,参数void *pdata是移动的IP地址的指针,4个字节。(仅支持在ESP-TOUCH方式下,其他方式则为NULL).当status为其他状态时,参数void*pdata为NULL.uint8 log=1,表示UART打印连接过程。否则:UART仅打印连接结果。在status= SC_STATUS_LINK,我们进行wifi参数设置。wifi_station_set_config(sta_conf)表示.之后要先断开wifi连接。再进行连接。注意:wifi_station_set_config(sta_conf)是设置并保存至flash里。也就是说wifi账号和密码已经保存至flash了。
在主函数中,代码如下:
uart_reattach为初始化uart,设置uart0用户使用的,uart1表示esp8266打印接口。在此不再讲解。keys_init为刚刚的按键初始化模块。wifi_status_led_install功能为注册一个wifi状态led灯。wifi没有连接上时,一直闪烁。wifi连接上后,led灯常亮。user_wifi_station_config为初始化wifi模式。(需要判断是否有wifi账号和密码在flash里,flash里的密码为通过airkiss功能保存的)。
二.开机时,wifi的初始化。此时我们看一下user_wifi_station_config函数。
wifi_set_opmode(STATION_MODE)为设置wifi模式。wifi_set_event_handler_cb(wifi_handle_event_cb)为注册wifi事件。后面会展开讲解。wifi_station_get_config_default(&sta_conf)此函数是读取flash里上次通过airkiss设置的wifi账号和密码。如果读取成功,返回true.否则返回false.返回false表示flash里没有wifi的参数。在返回true后,我们调用wifi_station_set_config(&sta_conf)设置wifi参数,在连接wifi之前记得先断开连接。现在我们来讲解一下注册的wifi事件wifi_handle_event_cb.代码如下:
/******************************************************************************
* FunctionName : wifi_handle_event_cb
* Description : wifi event callback
* Parameters : evt,事件
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
wifi_handle_event_cb(System_Event_t *evt)
{
os_printf("event %x\n", evt->event);
switch (evt->event) {
case EVENT_STAMODE_CONNECTED:
os_printf("connect to ssid %s, channel %d\n",
evt->event_info.connected.ssid,
evt->event_info.connected.channel);
break;
case EVENT_STAMODE_DISCONNECTED:
os_printf("disconnect from ssid %s, reason %d\n",
evt->event_info.disconnected.ssid,
evt->event_info.disconnected.reason);
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
os_printf("mode: %d -> %d\n",
evt->event_info.auth_change.old_mode,
evt->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP:
os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR,
IP2STR(&evt->event_info.got_ip.ip),
IP2STR(&evt->event_info.got_ip.mask),
IP2STR(&evt->event_info.got_ip.gw));
os_printf("\n");
user_udp_init();
os_printf("\r\nUDP start\r\n");
user_tcpserver_init(SERVER_LOCAL_PORT);
break;
case EVENT_SOFTAPMODE_STACONNECTED:
os_printf("station: " MACSTR "join, AID = %d\n",
MAC2STR(evt->event_info.sta_connected.mac),
evt->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED:
os_printf("