【ESP8266】NONOS SDK开发,发送HTTP请求

网络方面不是很懂,可能描述有一点不准确。

主要是通过ESP8266,在NONOS-SDK环境下,用URL地址,发出HTTP请求,接收并处理信息。


假设已经大致了解厂家提供的SDK,以及Eclipse开发环境如何使用,现在大致要做的是以下几步:

1、连上WiFi(连上网络)

2、与URL地址的服务器建立TCP连接

3、发出HTTP请求

4、接收并处理信息


现在就开始一步步地讲:

一、连上WiFi

连上WiFi这里我采用比较笨的方式,就是固定的WiFi和密码,直接连上就是了

需要用到几个函数:

bool wifi_set_opmode (uint8 opmode);    //设置ESP8266模式,选择station模式
wifi_station_set_config(&stationConf);    //设置连接WiFi的参数
//有结构体:
struct station_config {
uint8 ssid[32];		//ssid
uint8 password[64];	//密码
uint8 bssid_set;
uint8 bssid[6];
};
bool wifi_station_connect (void);	//连接WiFi
uint8 wifi_station_get_connect_status (void);	//获取连接状态

1)设置ESP8266 的工作模式;

2)设置好WiFi的SSID和密码;

3)开始连接WiFi;

4)检查WiFi连接状态,若为5则连接成功。

void init_CollectWifi()
{
	uint8 wifistatus;
	struct station_config stationConf;



	os_memcpy(&stationConf.ssid,WIFI_SSID,32);        //输入路由器账号
	os_memcpy(&stationConf.password,WIFI_PWD,64);     //输入路由器密码
	//stationConf.bssid_set = 0;
	wifi_station_set_config(&stationConf);//设置wifi_station的接口,并保存到flash。

#ifdef DEBUG
	os_printf("\r\n call connect_wifi\n");
	os_printf("wifi name: %s\n",stationConf.ssid);
	os_printf("wifi pw:%s\n",stationConf.password);
	os_printf("wifi connecting..\n");
#endif

	if (wifi_station_connect())
	{
#ifdef DEBUG
		os_printf("wifi_station_connect = true\n");
#endif
	}
	else
	{
#ifdef DEBUG
		os_printf("wifi_station_connect = flase\n");
#endif
	}
	//os_delay_us(2000000);

	wifistatus = wifi_station_get_connect_status();

#ifdef DEBUG
	os_printf("wifi connect status = %d\n",wifistatus);
	os_printf("wifi status = %s\n", Word_Status[wifistatus]);
#endif

}

在开始初始化的时候应该还要有一句 wifi_set_opmode(STATION_MODE);


二、建立TCP连接

这里又分为几步:

1)解析URL,获取域名

要建立TCP连接,首先应该获取服务器的域名。

举个例子:https://code.csdn.net/snippets_manage

那么域名就应该是code.csdn.net,我们要建立连接也是与这个服务器建立连接,所以我们需要把URL地址拆开

void ICACHE_FLASH_ATTR http_parse_request_url(char *URL,char *host,char *filename,unsigned short *port){
	char *PA;
	char *PB;
	memset(host,0,sizeof(host));
	memset(filename,0,sizeof(filename));
	*port=0;
	if(!(*URL)) return;
	PA=URL;
	if(!strncmp(PA,"http://",strlen("http://")))
		PA=URL+strlen("http://");
	if(!strncmp(PA,"https://",strlen("https://")))
		PA=URL+strlen("https://");
	PB=strchr(PA,'/');
	if(PB){
		memcpy(host,PA,strlen(PA)-strlen(PB));
		if(PB+1){
			memcpy(filename,PB+1,strlen(PB-1));
			filename[strlen(PB)-1]=0;
		}
		host[strlen(PA)-strlen(PB)]=0;
	}else{
		memcpy(host,PA,strlen(PA));
		host[strlen(PA)]=0;
	}
	PA=strchr(host,':');
	if(PA)
		*port=atoi(PA+1);
	else
		*port=80;
}

2)解析域名,转换成IP地址

【ESP8266】NONOS SDK开发,发送HTTP请求_第1张图片


这里,当它找到对应的IP地址后,会有调用回调函数,我们可以在回调函数中进行TCP连接

我是这样调用这个函数的:espconn_gethostbyname(&user_tcp_conn,host, &addr,user_esp_dns_found);


3)TCP连接

//DNS回调函数
void ICACHE_FLASH_ATTR user_esp_dns_found(const char *name, ip_addr_t *ipaddr, void *arg){
	struct ip_info info;
	wifi_get_ip_info(STATION_IF,&info);
	iot_station_init(ipaddr,&info.ip,port);
}


获得了IP地址后就可以连接了

/*
 * 函数名:	iot_station_init
 * 描述:		以ESP8266为客户端,建立tcp连接
 * 输入:		remote_ip:服务器IP
 * 			local_ip:本地IP
 * 			remote_port:服务器端口
 * 返回:		true:成功
 * 调用:		无
 */
bool ICACHE_FLASH_ATTR iot_station_init(struct ip_addr *remote_ip ,struct ip_addr *local_ip ,int remote_port )
{
#ifdef DEBUG
	os_printf("\r\ncall iot_station_init\n");
#endif
	user_tcp_conn.type = ESPCONN_TCP;
	user_tcp_conn.state = ESPCONN_NONE;
	user_tcp_conn.proto.tcp = (esp_tcp *)os_zalloc(sizeof(esp_tcp));
	os_memcpy(user_tcp_conn.proto.tcp->local_ip ,local_ip,4);
	os_memcpy(user_tcp_conn.proto.tcp->remote_ip ,remote_ip,4);
	user_tcp_conn.proto.tcp->local_port = espconn_port();
	user_tcp_conn.proto.tcp->remote_port = remote_port;

	espconn_regist_connectcb(&user_tcp_conn ,user_tcp_connect_cb);
    espconn_regist_reconcb(&user_tcp_conn ,user_tcp_recon_cb);
#ifdef DEBUG
	os_printf("espconn_connect\n");
#endif
	espconn_connect(&user_tcp_conn);

	return true;
}



三、发送HTTP请求

在(二)中的函数应该是在要发出命令时一气呵成的,所以这里我们应该封装好一个接口函数,

只要用户给出URL和发送的命令时,系统就能自动完成功能。

void ICACHE_FLASH_ATTR HttpReadFile(char *URL,char *method,char *postdata)
{
	struct ip_addr addr;
	memset(buffer,0,1024);
#ifdef DEBUG
	os_printf("\r\nThe URL request:\n%s\n", URL);
#endif
	http_parse_request_url(URL,host,filename,&port);
	if(strcmp(method,"GET")==0)
	{
		os_sprintf(buffer,GET,filename,host);
	}
	else
	{
		os_sprintf(buffer,POST,filename,strlen(postdata),host,postdata);
	}
	espconn_gethostbyname(&user_tcp_conn,host, &addr,user_esp_dns_found);
}

这里有包含头文件 my_client.h ,里面定义了GET和POST的格式

#ifndef APP_INCLUDE_MY_CLIENT_H_
#define APP_INCLUDE_MY_CLIENT_H_

#include "user_main.h"
#include "espconn.h"
#include "mem.h"
char buffer[1024];
#define GET "GET /%s HTTP/1.1\r\nAccept: */*\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n"
#define POST "POST /%s HTTP/1.1\r\nAccept: */*\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\nHost: %s\r\nConnection: Keep-Alive\r\n\r\n%s"
struct espconn user_tcp_conn;

//工作模式初始化,传三个参:远端IP,本地IP,远端端口。
bool iot_station_init(struct ip_addr *remote_ip ,struct ip_addr *local_ip ,int remote_port );

void user_tcp_connect_cb(void *arg);
void user_tcp_reconnect_cb(void *arg ,sint8 err);	//连接失败时会执行这个函数,可以在本回调函数中进行重连。

void user_tcp_recv_cb(void *arg ,char *pdata ,unsigned short len);	//注册成功接收网络数据的回调函数
void user_tcp_sent_cb(void *arg);		//注册网络数据发送成功的回调函数
void user_tcp_discon_cb(void *arg);		//注册 TCP 连接正常断开成功的回调函数

#endif /* APP_INCLUDE_MY_CLIENT_H_ */


四、接收信息

在之前一直没有讲,在建立了TCP连接后有四个很重要的回调函数要声明。

就是上面my_client.h中的四个回调函数

/*
 * 函数名:	user_tcp_sent_cb
 * 描述:		tcp发送成功后的回调函数
 * 输入:		arg:tcp连接句柄
 * 返回:		无
 * 调用:		无
 */
void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg)
{
#ifdef DEBUG
	os_printf("\r\nsend success!");
#endif
}


/*
 * 函数名:	user_tcp_discon_cb
 * 描述:		tcp连接断开后的回调函数
 * 输入:		arg:tcp连接句柄
 * 返回:		无
 * 调用:		无
 */
void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg)
{
#ifdef DEBUG
	os_printf("\r\ndisconnect success!");
#endif
}


/*
 * 函数名:	user_tcp_recv_cb
 * 描述:		tcp接收成功后的回调函数
 * 输入:		arg:tcp连接句柄
 * 			pdata:收到数据
 * 			len:收到数据长度
 * 返回:		无
 * 调用:		无
 */
void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg, char *pdata, unsigned short len)
{
	
}


/*
 * 函数名:	user_tcp_recon_cb
 * 描述:		tcp重连成功后的回调函数
 * 输入:		arg:tcp连接句柄
 * 			err:错误码
 * 返回:		无
 * 调用:		无
 */
void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err)
{
#ifdef DEBUG
	os_printf("connect err,errno:%d\r\n",err);
#endif
	espconn_connect((struct espconn *)arg);
}


/*
 * 函数名:	user_tcp_connect_cb
 * 描述:		tcp连接成功后的回调函数,需要再注册一些回调函数
 * 输入:		arg:tcp连接句柄
 * 返回:		无
 * 调用:		无
 */
void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg)
{
	struct espconn *pespconn=arg;
#ifdef DEBUG
	os_printf("\r\nconnect success!");
#endif
	
}

收到信号后的处理,我们就写在recv_cb里面就可以了

但是有一点要注意的是:我们使用的这个NONOS_SDK,它是 有看门狗的,当回调函数执行时间过长是会导致重启的!

参考资料:
HTTP和URL介绍 http://www.cnblogs.com/LDSmallCat/p/4942039.html
ESP8266 SDK 编程手册.pdf

你可能感兴趣的:(嵌入式)