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 stageos_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_ESPTOUCHuint8 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.0airkiss_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("station: " MACSTR "leave, AID = %d\n",MAC2STR(evt->event_info.sta_disconnected.mac),evt->event_info.sta_disconnected.aid);break;default:break;}
}
这个函数是由事件驱动的,非常有用。比其它用定时器定时器扫描wifi的状态好太用了EVENT_STAMODE_CONNECTED,表示wifi已经连接上了路由器,并打印出路由器的ssid,channel.EVENT_STAMODE_DISCONNECTED,wifi断开时事件类型。而EVENT_STAMODE_AUTHMODE_CHANGE,表示wifi切换信道的了,并打印出新旧信道,EVENT_STAMODE_GOT_IP,在wifi连接至路由器后回调的。可以知道路由器的ip,mask,gw.这个非常有用。因为所有的业务都必须在wifi连接上后才能开始。我们的TCP服务器和UDP绑定端口就是在此调用的。在后文详细讲解。
三.UDP端口绑定和组播绑定。在wifi回调事件中,我们在状态EVENT_STAMODE_GOT_IP中,调用了UDP初始化.如下代码片段。
 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;
我们来看看user_udp_init函数吧。代码如下:
/******************************************************************************* FunctionName : user_devicefind_init* Description  : create a udp listening* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_udp_init(void)
{sint8 ret = 0;ip_addr_t multicast_ip;struct ip_info host_info;multicast_ip.addr = ipaddr_addr(Multicast_Ip);os_printf("\r\nmulticast_ip:%d\r\n",multicast_ip.addr);wifi_get_ip_info(STATION_IF,&host_info);os_printf("host_ip:%d.%d.%d.%d\r\n",ip4_addr1(&(host_info.ip)),ip4_addr2(&(host_info.ip)),ip4_addr3(&(host_info.ip)),ip4_addr4(&(host_info.ip)));wifi_set_broadcast_if(STATION_MODE);espconn_igmp_join(&(host_info.ip),&multicast_ip);udpespconn.type = ESPCONN_UDP;//UDPudpespconn.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); //return memory spaceudpespconn.proto.udp->local_port = UDP_LOCAL_PORT;//local portespconn_regist_recvcb(&udpespconn,user_udp_recv_cb);//Resigister a callback function that it will be callback when udp receives datas from networkret = espconn_create(&udpespconn);os_printf("\r\nret=%d\r\n",ret);
}

在调用该函数之前,wifi已经连接至路由器了,所以本wifi station的IP地址是可以知道的。调用wifi_get_ip_info函数可以返回本模块被分配的IP地址。组播的地址是由自己定义。关于组播,大家可以百度搜。再经过ip的格式转换后,就可以绑定组播了。之后通过wifi_set_broadcast_if(STATION_MODE)绑定广播。之后建立UDP结构体块,绑定本地端口号,并注册udp接受回调函数。espconn_create,创建UDP连接。为什么要创建UDP,并绑定主播与广播呢?做这些工作是为了下面的TCP连接。在应用场景中,端设备是不知道服务器地址的。而没有服务器的IP就无法连接到服务器。所以可以通过组播。在服务器端,通过发送组播(内外网)或者广播(内网).而加入组播或者广播的设备可以收到服务器发送的组播或者广播。接受到组播或者广播命令时,也就可以知道服务器的IP地址等信息,也可以通过特定命令下发其他有用的信息。这样就可以通过IP地址连接至TCP服务器了。user_udp_recv_cb接受回调函数如下:

/******************************************************************************* FunctionName : user_udp_recv_cb* Description  : Processing the received udp packet* Parameters   : arg -- Additional argument to pass to the callback function*                pusrdata -- The received data (or NULL when the connection has been closed!)*                length -- The length of received data* Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_udp_recv_cb(void *arg,char *pusrdata,unsigned short length)
{os_printf("recv udp data:%s\n",pusrdata);struct espconn *pesp_conn = arg;remot_info *premot = NULL;sint8 value = ESPCONN_OK;if(espconn_get_connection_info(pesp_conn,&premot,0) == ESPCONN_OK){pesp_conn->proto.udp->remote_port = premot->remote_port;pesp_conn->proto.udp->remote_ip[0] = premot->remote_ip[0];pesp_conn->proto.udp->remote_ip[1] = premot->remote_ip[1];pesp_conn->proto.udp->remote_ip[2] = premot->remote_ip[2];pesp_conn->proto.udp->remote_ip[3] = premot->remote_ip[3];os_printf("remote_ip:%d.%d.%d.%d\r\n",pesp_conn->proto.udp->remote_ip[0],pesp_conn->proto.udp->remote_ip[1],pesp_conn->proto.udp->remote_ip[2],pesp_conn->proto.udp->remote_ip[3]);espconn_sendto(pesp_conn,pusrdata,os_strlen(pusrdata));}
}
请注意,回调函数中的espconn_get_connection_info函数的作用就是获取该UDP是哪个源IP,源端口发送的。这个非常有用。在接收信息后回复该设备命令场景很有用。切记不可用参量arg里面的remote_ip和remote_port.它指的是我们udp创建时绑定的远程ip和远程端口。而不是当前命令的远程ip和远程端口。如果创建UDP块时没有绑定远程ip和远程端口,则arg里的remote_ip和remote_port应该是0.
三.TCP服务器创建。终于将到了TCP服务器了。直接上代码吧。
/****************************************************************************** * FunctionName : user_tcpserver_init * Description : parameter initialize as a TCP server * Parameters : port --server port * Returns : none*******************************************************************************/void ICACHE_FLASH_ATTRuser_tcpserver_init(uint32 port){esp_conn.type = ESPCONN_TCP;//TCPesp_conn.state = ESPCONN_NONE;esp_conn.proto.tcp = &esptcp;esp_conn.proto.tcp->local_port = port;espconn_regist_connectcb(&esp_conn,tcp_server_listen);sint8 ret = espconn_accept(&esp_conn);os_printf("espconn_accept [%d]!!!\r\n",ret);
}TCP服务器初始化时,也只是绑定了本地端口。
注意,最好是UDP与TCP的端口后要不一样。respconn_regist_connectcb为注册监听回调函数tcp_server_listen.在此函数中,又注册了几个回调函数。如下:
/******************************************************************************* FunctionName : tcp_server_listen* Description  : TCP server listened a connection successfully* Parameters   : arg -- Addritional argument to pass to the callback function* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
tcp_server_listen(void *arg)
{struct espconn *pesp_conn = arg;os_printf("tcp_server_listen!!!\r\n");espconn_regist_recvcb(pesp_conn,tcp_server_recv_cb);//Register a callback function that successfully receives network dataespconn_regist_reconcb(pesp_conn,tcp_server_recon_cb);//Regiser callback function when TCP connections are abnormally disconnectedespconn_regist_disconcb(pesp_conn,tcp_server_discon_cb);//Register the callback function when the TCP connections are normally disconnectedespconn_regist_sentcb(pesp_conn,tcp_server_sent_cb);//Register the callback function when the network receives datas sucessfully
}
当服务器接受到tcp数据时,回掉tcp_server_recv_cb;当tcp异常掉线时,回掉tcp_server_reconn_cb函数;当tcp正常断开时回调tcp_server_discon_cb;当tcp发生数据成功后回调tcp_server_sent_cb.
总结:本文的功能是:通过按键长按出发airkiss配置wifi连接密码,并保持在flash里。在以后的每次上电都可以自动连接至路由器。为了可以根据人性后的连接tcp服务器,先建立了UDP并绑定了广播和组播。这样,服务器可以在不知道esp8266模块的ip地址的情况下发送组播(外网)或者广播(内网),与esp8266通信。在esp8266模块接受到组播或者广播后,分析接受到的数据可以知道服务器的ip和端口号,续而发起tcp连接。这样,esp8266就可以上次数据至服务器了。
最后,公布一下详细代码如下:
void ICACHE_FLASH_ATTR
keys_init(void)
{singlekey[0] = (struct single_key_param *)airkissfun_key();           //airkissfun keysinglekey[1] = (struct single_key_param *)start_test_key();            //start test keykey.key_num = PLUG_KEY_NUM;key.single_key = singlekey;key_init(&key);
}
void ICACHE_FLASH_ATTR
user_init(void)
{uart_reattach();//uart initializekeys_init(); // keys initializewifi_status_led_install(HUMITURE_WIFI_LED_IO_NUM, HUMITURE_WIFI_LED_IO_MUX, HUMITURE_WIFI_LED_IO_FUNC);//wifi led initializeuser_wifi_station_config();//config wifi station and connect wifi to AP
}
/** airkissfun.c**  Created on: 2018年5月25日*      Author: admin*/
#include "ets_sys.h"
#include "osapi.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"#include "user_interface.h"
#include "smartconfig.h"
#include "airkiss.h"
#include "driver/uart.h"
#include "driver/key.h"
#include "driver/airkissfun.h"#define DEVICE_TYPE         "gh_9e2cff3dfa51" //wechat public number
#define DEVICE_ID           "122475"        //model ID#define DEFAULT_LAN_PORT    12476#define AIRKISS_KEY_IO_MUX PERIPHS_IO_MUX_GPIO5_U   // airkiss key gpio's name
#define AIRKISS_KEY_IO_NUM GPIO_ID_PIN(5)          //airkiss key gpio's id
#define AIRKISS_KEY_IO_FUNC FUNC_GPIO5             //airkiss key gpio's funcLOCAL esp_udp ssdp_udp;
LOCAL struct espconn pssdpudpconn;
LOCAL os_timer_t ssdp_time_serv;uint8_t  lan_buf[200];
uint16_t lan_buf_len;
uint8    udp_sent_cnt = 0;const airkiss_config_t akconf =
{(airkiss_memset_fn)&memset,(airkiss_memcpy_fn)&memcpy,(airkiss_memcmp_fn)&memcmp,0,
};LOCAL void ICACHE_FLASH_ATTR
airkiss_wifilan_time_callback(void)
{uint16 i;airkiss_lan_ret_t ret;if ((udp_sent_cnt++) >30) {udp_sent_cnt = 0;os_timer_disarm(&ssdp_time_serv);//s//return;}ssdp_udp.remote_port = DEFAULT_LAN_PORT;ssdp_udp.remote_ip[0] = 255;ssdp_udp.remote_ip[1] = 255;ssdp_udp.remote_ip[2] = 255;ssdp_udp.remote_ip[3] = 255;lan_buf_len = sizeof(lan_buf);ret = airkiss_lan_pack(AIRKISS_LAN_SSDP_NOTIFY_CMD,DEVICE_TYPE, DEVICE_ID, 0, 0, lan_buf, &lan_buf_len, &akconf);if (ret != AIRKISS_LAN_PAKE_READY) {os_printf("Pack lan packet error!");return;}ret = espconn_sendto(&pssdpudpconn, lan_buf, lan_buf_len);if (ret != 0) {os_printf("UDP send error!");}os_printf("Finish send notify!\n");
}LOCAL void ICACHE_FLASH_ATTR
airkiss_wifilan_recv_callbk(void *arg, char *pdata, unsigned short len)
{uint16 i;remot_info* pcon_info = NULL;airkiss_lan_ret_t ret = airkiss_lan_recv(pdata, len, &akconf);airkiss_lan_ret_t packret;switch (ret){case AIRKISS_LAN_SSDP_REQ:espconn_get_connection_info(&pssdpudpconn, &pcon_info, 0);os_printf("remote ip: %d.%d.%d.%d \r\n",pcon_info->remote_ip[0],pcon_info->remote_ip[1],pcon_info->remote_ip[2],pcon_info->remote_ip[3]);os_printf("remote port: %d \r\n",pcon_info->remote_port);pssdpudpconn.proto.udp->remote_port = pcon_info->remote_port;os_memcpy(pssdpudpconn.proto.udp->remote_ip,pcon_info->remote_ip,4);ssdp_udp.remote_port = DEFAULT_LAN_PORT;lan_buf_len = sizeof(lan_buf);packret = airkiss_lan_pack(AIRKISS_LAN_SSDP_RESP_CMD,DEVICE_TYPE, DEVICE_ID, 0, 0, lan_buf, &lan_buf_len, &akconf);if (packret != AIRKISS_LAN_PAKE_READY) {os_printf("Pack lan packet error!");return;}os_printf("\r\n\r\n");for (i=0; i<lan_buf_len; i++)os_printf("%c",lan_buf[i]);os_printf("\r\n\r\n");packret = espconn_sendto(&pssdpudpconn, lan_buf, lan_buf_len);if (packret != 0) {os_printf("LAN UDP Send err!");}break;default:os_printf("Pack is not ssdq req!%d\r\n",ret);break;}
}void ICACHE_FLASH_ATTR
airkiss_start_discover(void)
{ssdp_udp.local_port = DEFAULT_LAN_PORT;pssdpudpconn.type = ESPCONN_UDP;pssdpudpconn.proto.udp = &(ssdp_udp);espconn_regist_recvcb(&pssdpudpconn, airkiss_wifilan_recv_callbk);espconn_create(&pssdpudpconn);os_timer_disarm(&ssdp_time_serv);os_timer_setfn(&ssdp_time_serv, (os_timer_func_t *)airkiss_wifilan_time_callback, NULL);os_timer_arm(&ssdp_time_serv, 1000, 1);//1s
}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 stageos_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_ESPTOUCHuint8 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.0airkiss_start_discover();}smartconfig_stop();break;}}/******************************************************************************* FunctionName : long_press_callback* Description  : When pressing the button frequently,clear the stored wifi information*                 and enter the airkiss function* Parameters   : NONE* Returns      : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
smart_long_press_callback(void)
{//system_restore();    //restore data to spi//system_restart();    //restart machinesmartconfig_stop();smartconfig_set_type(SC_TYPE_ESPTOUCH_AIRKISS); //SC_TYPE_ESPTOUCH,SC_TYPE_AIRKISS,SC_TYPE_ESPTOUCH_AIRKISSwifi_set_opmode(STATION_MODE);smartconfig_start(smartconfig_done);
}LOCAL void ICACHE_FLASH_ATTR
smart_short_press_callback(void)
{}
/******************************************************************************* FunctionName : keyofconnect_init* Description  : Initializes the airkiss connection function module* Parameters   : NONE* Returns      : NONE
*******************************************************************************/struct single_key_param *ICACHE_FLASH_ATTR
airkissfun_key(void)
{struct single_key_param *smart_connect_key = key_init_single(AIRKISS_KEY_IO_NUM,AIRKISS_KEY_IO_MUX,\AIRKISS_KEY_IO_FUNC,smart_long_press_callback,smart_short_press_callback);return smart_connect_key;
}
/** tcp_msg.c**  Created on: 2018年5月28日*      Author: admin*/#include "ets_sys.h"
#include "osapi.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"#include "user_interface.h"
#include "driver/tcp_msg.h"
#include "driver/udp_msg.h"#define LINK_LED_IO_MUX     PERIPHS_IO_MUX_MTDI_U
#define LINK_LED_IO_NUM     12
#define LINK_LED_IO_FUNC    FUNC_GPIO12#define SERVER_LOCAL_PORT   9909LOCAL os_timer_t link_led_timer; //link led timer
LOCAL uint8 link_led_level = 0;     //link led current level
LOCAL struct espconn esp_conn;  //esp_conn parameter
LOCAL esp_tcp esptcp; //tcp struct parameter/******************************************************************************* FunctionName : link_led_init* Description  : link led init* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
link_led_init(void)
{PIN_FUNC_SELECT(LINK_LED_IO_MUX, LINK_LED_IO_FUNC);
}/******************************************************************************* FunctionName : link_led_output* Description  : output the link led* Parameters   : level=1,high level;level=0,low level* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
link_led_output(uint8 level)
{GPIO_OUTPUT_SET(GPIO_ID_PIN(LINK_LED_IO_NUM), level);
}/******************************************************************************* FunctionName : link_led_timer_cb* Description  : the callback function of the link_led_timer* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
link_led_timer_cb(void)
{link_led_level = (~link_led_level & 0x01);GPIO_OUTPUT_SET(GPIO_ID_PIN(LINK_LED_IO_NUM),link_led_level);
}/******************************************************************************* FunctionName : link_led_timer_init* Description  : The timer of link led is initalized* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
link_led_timer_init(void)
{os_timer_disarm(&link_led_timer);os_timer_setfn(&link_led_timer,(os_timer_func_t *)link_led_timer_cb,NULL);os_timer_arm(&link_led_timer,50,1);
}/******************************************************************************* FunctionName : link_led_timer_done* Description  : close the link led timer and link led* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
link_led_timer_done(void)
{os_timer_disarm(&link_led_timer);GPIO_OUTPUT_SET(GPIO_ID_PIN(LINK_LED_IO_NUM), 0);
}LOCAL void ICACHE_FLASH_ATTR
tcp_server_sent_cb(void *arg)
{//data sent successfullyos_printf("tcp sent successed  \r\n");
}/******************************************************************************* FunctionName : tcp_server_recv_cb* Description  : receive callback.* Parameters   : arg -- Addritional argument to pass to the callback function* Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
tcp_server_recv_cb(void *arg,char *pusrdata,unsigned short length)
{//received some data from tcp connectionstruct espconn *pespconn = arg;espconn_send(pespconn,pusrdata,length);
}/******************************************************************************* FunctionName : tcp_server_discon_cb* Description  : disconnect callback* Parameters   : arg -- Addritional argument to pass to the callback function* Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
tcp_server_discon_cb(void *arg)
{//tcp disconnect sucesssfullyos_printf("tcp disconnect successed!!!\r\n");
}/******************************************************************************* FunctionName : tcp_server_recon_cb* Description  : reconnect callback,error occured in TCP connection* Parameters   : arg -- Addritional argument to pass to the callback function* Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
tcp_server_recon_cb(void *arg,sint8 err)
{//error occured,tcp connection broke.os_printf("reconnect callback,error code %d!!! \r\n",err);
}/******************************************************************************* FunctionName : tcp_server_listen* Description  : TCP server listened a connection successfully* Parameters   : arg -- Addritional argument to pass to the callback function* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
tcp_server_listen(void *arg)
{struct espconn *pesp_conn = arg;os_printf("tcp_server_listen!!!\r\n");espconn_regist_recvcb(pesp_conn,tcp_server_recv_cb);//Register a callback function that successfully receives network dataespconn_regist_reconcb(pesp_conn,tcp_server_recon_cb);//Regiser callback function when TCP connections are abnormally disconnectedespconn_regist_disconcb(pesp_conn,tcp_server_discon_cb);//Register the callback function when the TCP connections are normally disconnectedespconn_regist_sentcb(pesp_conn,tcp_server_sent_cb);//Register the callback function when the network receives datas sucessfully
}/******************************************************************************* FunctionName : user_tcpserver_init* Description  : parameter initialize as a TCP server* Parameters   : port --server port* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_tcpserver_init(uint32 port)
{esp_conn.type = ESPCONN_TCP;//TCPesp_conn.state = ESPCONN_NONE;esp_conn.proto.tcp = &esptcp;esp_conn.proto.tcp->local_port = port;espconn_regist_connectcb(&esp_conn,tcp_server_listen);sint8 ret = espconn_accept(&esp_conn);os_printf("espconn_accept [%d]!!!\r\n",ret);
}/******************************************************************************* 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("station: " MACSTR "leave, AID = %d\n",MAC2STR(evt->event_info.sta_disconnected.mac),evt->event_info.sta_disconnected.aid);break;default:break;}
}/******************************************************************************* FunctionName : user_wifi_station_config* Description  : wifi station config* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_wifi_station_config(void)
{struct station_config sta_conf,sta[5];bool result = false;wifi_set_opmode(STATION_MODE);//Set the wifi mode as station modewifi_set_event_handler_cb(wifi_handle_event_cb);//when wifi is connected,will callback wifi_handle_event_cbresult = wifi_station_get_config_default(&sta_conf);//get the wifi station paramter from flashif(result){os_printf("get wifi station parameter sucessed!\r\n");wifi_station_set_config(&sta_conf);wifi_station_disconnect();wifi_station_connect();}else{os_printf("get wifi station parameter failed!\r\n");}
}
/** udp_msg.c**  Created on: 2018年5月30日*      Author: admin*/#include "ets_sys.h"
#include "osapi.h"
#include "ip_addr.h"
#include "espconn.h"
#include "mem.h"#include "user_interface.h"
#include "driver/udp_msg.h"#define UDP_LOCAL_PORT     9666
#define MULTICAST_IP    "224.0.1.99"LOCAL struct espconn udpespconn; //udp struct parameterconst char *Multicast_Ip = MULTICAST_IP;/******************************************************************************* FunctionName : user_udp_recv_cb* Description  : Processing the received udp packet* Parameters   : arg -- Additional argument to pass to the callback function*                pusrdata -- The received data (or NULL when the connection has been closed!)*                length -- The length of received data* Returns      : none
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
user_udp_recv_cb(void *arg,char *pusrdata,unsigned short length)
{os_printf("recv udp data:%s\n",pusrdata);struct espconn *pesp_conn = arg;remot_info *premot = NULL;sint8 value = ESPCONN_OK;if(espconn_get_connection_info(pesp_conn,&premot,0) == ESPCONN_OK){pesp_conn->proto.udp->remote_port = premot->remote_port;pesp_conn->proto.udp->remote_ip[0] = premot->remote_ip[0];pesp_conn->proto.udp->remote_ip[1] = premot->remote_ip[1];pesp_conn->proto.udp->remote_ip[2] = premot->remote_ip[2];pesp_conn->proto.udp->remote_ip[3] = premot->remote_ip[3];os_printf("remote_ip:%d.%d.%d.%d\r\n",pesp_conn->proto.udp->remote_ip[0],pesp_conn->proto.udp->remote_ip[1],pesp_conn->proto.udp->remote_ip[2],pesp_conn->proto.udp->remote_ip[3]);espconn_sendto(pesp_conn,pusrdata,os_strlen(pusrdata));}
}
/******************************************************************************* FunctionName : user_devicefind_init* Description  : create a udp listening* Parameters   : none* Returns      : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_udp_init(void)
{sint8 ret = 0;ip_addr_t multicast_ip;struct ip_info host_info;multicast_ip.addr = ipaddr_addr(Multicast_Ip);os_printf("\r\nmulticast_ip:%d\r\n",multicast_ip.addr);wifi_get_ip_info(STATION_IF,&host_info);os_printf("host_ip:%d.%d.%d.%d\r\n",ip4_addr1(&(host_info.ip)),ip4_addr2(&(host_info.ip)),ip4_addr3(&(host_info.ip)),ip4_addr4(&(host_info.ip)));wifi_set_broadcast_if(STATION_MODE);espconn_igmp_join(&(host_info.ip),&multicast_ip);udpespconn.type = ESPCONN_UDP;//UDPudpespconn.proto.udp = (esp_udp *)os_zalloc(sizeof(esp_udp)); //return memory spaceudpespconn.proto.udp->local_port = UDP_LOCAL_PORT;//local portespconn_regist_recvcb(&udpespconn,user_udp_recv_cb);//Resigister a callback function that it will be callback when udp receives datas from networkret = espconn_create(&udpespconn);os_printf("\r\nret=%d\r\n",ret);
}

esp8266 airkiss联网进行TCP,UDP通信服务相关推荐

  1. 高性能 TCP UDP 通信框架 HP-Socket v3.2.3

    HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Del ...

  2. 21天学会Java之(Java SE第十三篇):网络编程、TCP/UDP通信

    如今,计算机已经成为人们学习.工作.生活必不可少的工具.人们利用计算机可以和亲朋好友在网上聊天,玩网游或发邮件等,这些功能的实现都离不开计算机网络.计算机网络实现了不同计算机之间的通信,而这些必须依靠 ...

  3. QT TCP/UDP通信

    参考:43黑马QT笔记之Qt下Tcp/Udp通信过程_Mango酱的博客-CSDN博客 HTTP与TCP的区别和联系_satellite13的博客-CSDN博客 TCP和UDP的区别: UDP通信 服 ...

  4. OSI七层模型以及TCP/UDP客户端/服务端程序实例

    OSI七层模型以及TCP/UDP客户端/服务端程序实例 一.前言 二.OSI简介 2.1 OSI概念 2.2 划分原则 2.3 OSI七层模型 2.4 模型举例 三.Linux下TCP/UDP程序开发 ...

  5. 【.NET类库】通过SharpSocket进行TCP/UDP通信数据传输

    类库作用: 用于基于TCP/UDP协议的数据通信,调用简单,高效. 封装了和业务无关的底层细节,让开发人员可以专注于做业务 完善的示例代码: 针对类库的几种用法,都提供了较为详细的示例代码 一.TCP ...

  6. php实现tcp连接esp8266,【零知ESP8266教程】WIFI TCP协议通信 TCP客户端示例

    本帖最后由 lz-esp-link 于 2019-9-25 09:56 编辑 本帖主要讲解ESP8266 WIFI功能关于TCP协议网络传输的应用,这里演示了ESP8266作为TCP客户端的示例: 1 ...

  7. Android开发使用ServerSocket ServerSocketChannel DatagramSocket进行TCP UDP通信 实现服务器与APP消息推送

    前言 在日常开发中采用Http协议进行数据传输的情况非常多,但这都是APP主动请求服务端,将数据传到服务器或者从服务器下载数据:那么如果我们想服务器主动联系我们或者我们频繁的上报消息给服务器,怎么弄呢 ...

  8. 黑马程序员_Java学习日记第八天--TCP/UDP通信、正则表达式

    ------- android培训. java培训.期待与您交流! ---------- UDP/TCP 如何实现通信: 1,找到对方IP 2,数据要发送到对方指定的应用程序上.为了标识这些应用程序, ...

  9. java安卓模拟器和电脑通信_PC电脑和Android模拟器访问及模拟器之间tcp/udp通信

    Android系统默认只能通过IP(10.0.2.2)单向访问PC电脑,而PC电脑不能通过IP来直接访问Android模拟器系统.要想实现PC电脑和Android模拟器系统以及Android模拟器之间 ...

最新文章

  1. 如何降低QPS(错峰、限流、削峰)
  2. java group类_浅析Java中线程组(ThreadGroup类)
  3. Waymo首次公开自动驾驶技术:让AI学会「危机想象力」
  4. socket编程 (PHP实现)
  5. Genome Research封面文章|张勇课题组开发方法绘制胚胎发育早期转录因子结合位点图谱...
  6. php人才招聘网可二开
  7. 《OpenACC并行程序设计:性能优化实践指南》一 3.1 性能分析技术和术语
  8. 如何进行 JVM 调优
  9. 永磁同步电机模型之坐标变换
  10. ajax请求数据 ztree_ztree通过ajax获取json并勾选checkbook
  11. 手游服务器账号,手游服务器登录流程
  12. ESP8266-Arduino编程实例-MQ3酒精传感器驱动
  13. 无法打开虚拟磁盘服务器,win2008R2 修改了带有快照的父虚拟磁盘;导致启动不了...
  14. C语言之自定义函数的实现
  15. java des解密乱码_des解密不完整,前面几位是乱码的解决办法
  16. 【倡议】表达哀思,博客更换为素装
  17. 超简单的混合开发入门 JS实现安卓Listview
  18. Fcitx──小企鹅输入法
  19. 使用windows默认工具快速修改图片尺寸
  20. python绘图房子_matplotlib画房子

热门文章

  1. P1000刷机知识+获取ROOT+HDVS_ROM快速刷机教程 by fox
  2. 软件提交到国外的下载站的几点操作和想法
  3. python图像运算、图像融合
  4. 密码学 | 维吉尼亚密码(Vigener)
  5. EXCEL生成随机密码函数
  6. C语言——生命小游戏
  7. 中控系统一键关机--读取串口数据并判断
  8. 我用Python隐藏了MacBook Pro 14的大刘海
  9. Mysql 修改密码 (亲测)
  10. 产品范围与项目范围的联系与区别