Error[8]: Undefined offset: 2048, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

1、准备开发板

开发板功能区分布图

开发板俯视图

2、HTTP协议介绍 HTTP协议简介

    HTTP(HyperText Transfer Protocol)协议,即超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 协议是基于 TCP/IP 协议的网络应用层协议。
    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。服务器接收到请求之后,通过接收到的信息判断响应方式,并且给予客户端相应的响应,完成整个 HTTP 数据交互流程。

HTTP 工作原理
HTTP 请求/响应的步骤
1. 客户端连接到Web服务器一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
2. 发送HTTP请求通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和数据包4部分组成。
3. 服务器接受请求并返回HTTP响应Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
HTTP协议请求头Request Headers

客户端发送一个HTTP请求到服务器的请求头主要包括:请求行、请求头部、空行、数据包
如下图是一个 POST 请求的信息:

HTTP 协议响应信息 Response

HTTP 协议状态码
状态代码类别原因短语
1xxInfomational(信息性状态码)接收的请求正在处理
2xxSuccess(成功状态码)请求正常处理完毕
3xxRedirection(重定向状态码)需要进行附加 *** 作以完成请求
4xxClient Error(客户端错误状态码)服务器无法处理请求
5xxServer Error(服务器错误状态码)服务器处理请求出错
3、在MDK中编写代码
WebClient客户端代码
web_strdup将字符串复制到新开辟的内存空间
webclient_session_create创建webclient客户端
webclient_header_fields_add将请求句柄封装到客户端缓存区
webclient_header_fields_get解析响应数据的单一消息报头
webclient_header_length_response获取请求头的长度
webclient_handle_response获取服务器响应的状态码
webclient_data_analysis获取服务器返回的数据包
HTTP请求方法
webclient_get_method客户端GET请求方法
webclient_post_method客户端POST请求方法

修改ESP8266.c代码中的NET_DEVICE_LinkServer_Init函数(代码在上一章)

ESP8266_RETTYPE NET_DEVICE_LinkServer_Init(void)
{
	
	unsigned char errCount = 0, errType = 0;
	char cfgBuffer[70];
	
	switch(netDeviceInfo.initStep)
	{
		case 0:
			if(ESP8266_Net_Mode_Choose(STA) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 1:
			if(ESP8266_Enable_MultipleId(DISABLE) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 2:
			if(ESP8266_JoinAP(netDeviceInfo.staName,netDeviceInfo.staPass) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 3:
			//注释掉这一行,因为请求的网址不同
//			if(ESP8266_Link_Server(enumTCP,netDeviceInfo.staIPAddress,netDeviceInfo.staPort,Single_ID_0) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		default:
			 netDeviceInfo.netWork = 1;
			 errType = 3;
			break;
	}
	
	
		return errType;
	
}

在webclient.h中编写以下代码

#ifndef __WEBCLIENT_H_
#define __WEBCLIENT_H_
#include "sys.h"


#ifndef WEBCLIENT_OK
#define WEBCLIENT_OK 0
#endif

#ifndef WEBCLIENT_NOK
#define WEBCLIENT_NOK 1
#endif

typedef struct __webclient_header
{
    char* buffer;

    unsigned int length;                      /* content header buffer size */

    unsigned int size;                        /* maximum support header size */
}webclient_header;

typedef struct __webclient_session
{	
	webclient_header* header;    /* webclient response header information */
	
	int resp_status;
	int content_length;
}webclient_session;


void webclient_get_method(void);
void webclient_post_method(void);

#endif

在webclient.c中编写以下代码

#include "webclient.h"
#include "ESP8266.h"
#include "usart.h"
#include "StringUtil.h"


//将字符串复制到新开辟的内存空间
char* web_strdup(const char* s)
{
	uint16_t len = strlen(s) + 1;
	char* tmp = (char*)malloc(len);

	if (!tmp)
			return NULL;

	memcpy(tmp, s, len);

	return tmp;
}

//创建webclient客户端
webclient_session* webclient_session_create(uint16_t header_sz)
{
	webclient_session* session;
	/* create session */
	session = (webclient_session*)calloc(1, sizeof(webclient_session));
	if (session == NULL)
	{
			printf("webclient create failed, no memory for webclient session!");
			return NULL;
	}
	/* initialize the socket of session */
	session->content_length = -1;
	session->header = (webclient_header*)calloc(1, sizeof(webclient_header));
	if (session->header == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	session->header->size = header_sz;
	session->header->buffer = (char*)calloc(1, header_sz);
	if (session->header->buffer == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	return session;
}

//将请求句柄封装到客户端缓存区
unsigned char webclient_header_fields_add(webclient_session* session, const char* fmt, ...)
{
	int length;
	va_list args;
	va_start(args, fmt);
	length = vsnprintf(session->header->buffer + session->header->length, session->header->size - session->header->length, fmt, args);
	if (length < 0)
	{
			printf("add fields header data failed, return length(%d) error.", length);
			return WEBCLIENT_NOK;
	}
	va_end(args);
	session->header->length += length;
	if (session->header->length >= session->header->size)
	{
			printf("not enough header buffer size(%d)!", session->header->size);
			return WEBCLIENT_NOK;
	}

	return WEBCLIENT_OK;
}



//解析响应数据的单一消息报头
const char* webclient_header_fields_get(webclient_session* session, const char* fields)
{
	char* resp_buf = NULL;
	size_t resp_buf_len = 0;
	char* dataPtr;
	char* mime_ptr = NULL;

	resp_buf = session->header->buffer;

	dataPtr = strstr(resp_buf,fields);
	if(dataPtr != NULL)
	{
		mime_ptr = strstr(dataPtr,":");
		if(mime_ptr != NULL)
		{
				mime_ptr += 1;
				while (*mime_ptr && (*mime_ptr == ' ' || *mime_ptr == '\t'))
					mime_ptr++;
				return mime_ptr;
		}
	}
	
	return NULL;
}

//获取请求头的长度
unsigned int webclient_header_length_response(webclient_session* session)
{
	return (strlen(session->header->buffer) - session->content_length - 4);
}

//获取服务器响应的状态码
unsigned char webclient_handle_response(webclient_session* session)
{
	int rc = 0;
	char* mime_buffer = NULL;
	char* mime_ptr = NULL;
	const char* transfer_encoding;
	int i;

	if(webclient_header_fields_get(session, "Content-Length") != NULL)
	{
		session->content_length = atoi(webclient_header_fields_get(session, "Content-Length"));
	}
	
	session->header->length = webclient_header_length_response(session);

	/* get HTTP status code */
	mime_ptr = web_strdup(session->header->buffer);
	if (strstr(mime_ptr, "HTTP/1."))
	{
		char* ptr = mime_ptr;

		ptr += strlen("HTTP/1.x");

		printf("ptr: %s\r\n", ptr);

		while (*ptr && (*ptr == ' ' || *ptr == '\t'))
				ptr++;

		/* Terminate string after status code */
		for (i = 0; ((ptr[i] != ' ') && (ptr[i] != '\t')); i++);
		ptr[i] = ';'=

		session->resp_status ( int)strtol(,ptrNULL ,10 );}

	if
	( )mime_ptrfree
	{
			()mime_ptr;}
	return
	
	; session->resp_status}
//获取服务器返回的数据包

uint8_t
*webclient_data_analysis (*webclient_session) sessionchar
{
	*; dataptrchar
	*= mime_ptr ; session->header->buffer=
	
	//printf("session->header->buffer:%s\r\n",session->header->buffer);
	
	dataptr strstr (,mime_ptr"\r\n\r\n");if
	(!=dataptr NULL )+=
	{
		dataptr 4 ;return
		( uint8_t*);dataptr}
	return
	
	NULL ;}
//客户端GET请求方法



void
webclient_get_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=en&unit=c HTTP/1.1\r\n");webclient_header_fields_add
	(,session"Host:www.baidu.com\r\n");webclient_header_fields_add
	(,session"\r\n");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接,	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.seniverse.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
//客户端POST请求方法

void
webclient_post_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"POST /devices/583402349/datapoints HTTP/1.1\r\n");webclient_header_fields_add
	(,session"api-key:rBIh6FFxeyW=kVJyybB2FzD5QAQ=\r\n");webclient_header_fields_add
	(,session"Host: api.heclouds.com\r\n");webclient_header_fields_add
	(,session"Content-Length:66\r\n");webclient_header_fields_add
	(,session"\r\n");webclient_header_fields_add
	(,session"{\"datastreams\":[{\"id\":\"test_stream\",\"datapoints\":[{\"value\":30}]}]}");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.heclouds.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
#

在StringUtil.h中编写以下代码

ifndef__STRING_UTIL_h #
define__STRING_UTIL_h #
include"string.h" #
include# 
include# 
include"usart.h" int

find_end (char* , usart_bufferint ) number;int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcRes;void
smart_array (unsignedchar *, addrunsignedchar * )ip;void
Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLen;unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) right;#
endif#

在StringUtil.c中编写以下代码

include"StringUtil.h" /**
*@brief	 	ip网络地址转换
*@param		adr:地址 ip:ip
*@return	无
*/


void
smart_array (unsignedchar *, addrunsignedchar * )ipint
{
    ; ichar
    [ taddr30];char
    * ; nexttokchar
    ; numstrcpy
    (,taddr(char* ))addr;=
    nexttok ; taddrfor
    (=i 0 ;< i 4 ; ++ i)=
    {
        nexttok strtok (,nexttok".");//		if(nexttok[0] == '0' && nexttok[1] == 'x') num = atoi16(nexttok+2,0x10);
//		else num = atoi16(nexttok,10);
[
        ip]i= ; num=
        nexttok NULL ;}
    }
/***********************************************************
  函数名称:Find_string(char *pcBuf,char*left,char*right, char *pcRes)
  函数功能:寻找特定字符串
  入口参数:
           char *pcBuf 为传入的字符串
           char*left   为搜索字符的左边标识符  例如:"["
           char*right  为搜索字符的右边标识符  例如:"]"
		   char *pcRes 为输出转存的字符串数组
  返回值:用来校验是否成功,无所谓的。
  备注: left字符需要唯一,right字符从left后面开始唯一即可
 服务器下发命令举例:+MQTTPUBLISH: 0,0,0,0,/device/NB/zx99999999999999_back,6,[reastrobot]
 此函数会 *** 作内存空间  强烈建议 提前清空buf   memset(Find_token,0x00,sizeof(Find_token));
***********************************************************/
int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcReschar
{
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=
    pcBegin strstr (,pcBuf) left;//找到第一次出现的位置               =
    pcEnd strstr (+pcBeginstrlen()left,) right;//找到右边标识第一次出现位置 if
    (==pcBegin NULL || == pcEnd NULL || ) pcBegin > pcEndprintf
    {
        ("string name not found!\n");return
        0 ;}
    else
    +=
    {
        pcBegin strlen ()left;memcpy
        (,pcRes, pcBegin- pcEnd)pcBegin;return
        1 ;}
    }
//+IPD, 268:hello world\r\n

//过滤left和right之间的字符串,返回过滤之后的字符串
unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) rightchar
{
    *; ptrIPD=

    ptrIPD strstr ((char*),pcBuf) left;//搜索“left”头				if
    ( ==ptrIPD NULL )//						UsartPrintf(USART_DEBUG, "\"left\" not found\r\n");										
    {
        }
    else
    =
    {
        ptrIPD strstr (,ptrIPD) right;//找到'right'							if
        ( !=ptrIPD NULL )+=
        {
            ptrIPDstrlen()right;return
            ( unsignedchar *)()ptrIPD;}
        else
        return
            NULL ;}
    }
//int Smart_array(char *pcBuf,char *fu)


//memcpy(&citc_server_ip[0],back_ip,strstr(back_ip,".")-back_ip);
//{
//  char *pcBegin = NULL;
//	int8_t len =0;
//	pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	memcpy(&pcRes[i], pcBuf,pcBegin-pcBuf);
//	}
//	 len= strlen(pcBuf);
//	 pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	 memcpy(&pcRes[0], pcBuf,pcBegin-pcBuf);
//}
//寻找字符后面最近的结束符

//  int i;
//int find_end(char * usart_buffer, int number) {
//      return number + i+2 ;   //如果有换行符  需要加4
//  for (i = 0; i < 100; i++) {
//    if ((usart_buffer[number + i] == '/') && (usart_buffer[number + i + 1] == '>')) {
//    }
//  }
//}
//智能查找和匹配字符串

int8_t
Find_AttributeStringAll (char* ,pcBufchar * ,pcRestuint16_t, rowuint8_t, colchar * ,leftchar * ,rightuint8_t* )Numchar
{
    [ pcFind20]= 0 {};char
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=

    pcEnd  ; pcBufwhile
    (1)memset
    {
        (,pcFind0,20);=
        pcBegin strstr (+pcEnd1,) left;if
        ((==pcBegin NULL )|| ( strcmp(,pcBegin"}")== 0 ))printf
        {
            ("找到指定字符 !\n");return
            1 ;}
        else
        =
        {
            pcEnd strstr (+pcBeginstrlen()left,) right;if
            ( (==pcEnd NULL )|| ( )pcBegin > pcEnd)printf
            {
                ("Mail name not found!\n");return
                - 1;}
            else
            if
            {
                (*)Num>rowreturn
                {
                    1 ;}
                else
                +=
                {
                    pcBegin strlen ()left;memcpy
                    (,pcFind, pcBegin- pcEnd ) pcBegin;memset
                    (+pcRest**Num,col0,)col;memcpy
                    (+pcRest**Num,col,pcFindsizeof()pcFind);(
                    *)Num++ ;}
                }
            }
        }
    }
void

Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLenchar
{
    ,    ddl;ddhint
    ; ifor

    ( =i0;< i;nLen++ i)=
    {
        ddh 48 + [ pbSrc]i/ 16 ;=
        ddl 48 + [ pbSrc]i% 16 ;if
        ( 57ddh > )= ddh + ddh 7 ;if
        ( 57ddl > )= ddl + ddl 7 ;[
        pbDest*i2]= ; ddh[
        pbDest*i2+1]= ; ddl}
    [

    pbDest*nLen2]= ';' }void
Str2Hex

( char*,char str* )const hexchar
{

    * ="0123456789ABCDEF" cHex ; int=
    0 i;for(
    int=0 j ;<strlen j ( );str++) junsignedint
    {
        = ( a unsigned  int) [] str;j[++
        hex]i=[ ( cHex&0xf0a ) 4] >> ;[++
        hex]i=[ ( cHex&0x0fa ) ];}[
    ]
    hex=i';' } /* USER CODE BEGIN 0 */#
define

在main.c中编写以下代码

REQUEST_METHOD

0//0:GET请求,1:POST请求 /* USER CODE END 0 */ 	int	main
(

void )/* USER CODE BEGIN 1 */unsignedchar
{
  *
	= NULL; dataPtr uint32_t =0
	; request_time uint32_t =0
	; netErr_time = ;uint32_t
	ESP8266_RETTYPE uwRet = ESP8266_NOK0
	; total_len/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init

  (

  )
  ;/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */

  SystemClock_Config

  (

  )
  ;/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */

  MX_GPIO_Init

  (

  )
  ;MX_DMA_Init()
  ;MX_LPUART1_UART_Init()
  ;MX_USART1_UART_Init()
  ;MX_TIM2_Init()
  ;/* USER CODE BEGIN 2 */TIM_Interupt_Enable(
  )
	
	;//使能串口中断USART_Interupt_Enable( )
	
	;//使能定时器中断/* USER CODE END 2 *//* Infinite loop */ /* USER CODE BEGIN WHILE */

	
  while

  (
  1
  ) /* USER CODE END WHILE *//* USER CODE BEGIN 3 */if
  {
    (

    !
		
		.)//如果网络未连接netDeviceInfoifnetWork(	NET_DEVICE_Init
		{
			()==)printf ( ESP8266_OK"初始化成功\r\n"	
			{
				);}}if
			(
		-
		
		10000)time2Count //(1ms * 2000)相当于延时2秒钟 request_time >= if(		.
		{
			)//如果网络连接成功netDeviceInfo#netWorkifREQUEST_METHOD
			{
webclient_get_method( )
					;#elsewebclient_post_method	
()
					;#endif}
}}
		
			/* USER CODE END 3 */
		}
	
  实现的功能
  1、上电自动连接WIFI
2、如果是POST请求,则请求POST接口(我这里用的是ONENET的POST接口)


4、实验现象 [+++][+++][+++]
3、如果是GET请求,则请求GET接口(我这里用的是心知天气的GET接口)

POST请求(Onenet物联网平台)

GET请求(心知天气)

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 2049, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

1、准备开发板

开发板功能区分布图

开发板俯视图

2、HTTP协议介绍 HTTP协议简介

    HTTP(HyperText Transfer Protocol)协议,即超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 协议是基于 TCP/IP 协议的网络应用层协议。
    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。服务器接收到请求之后,通过接收到的信息判断响应方式,并且给予客户端相应的响应,完成整个 HTTP 数据交互流程。

HTTP 工作原理
HTTP 请求/响应的步骤
1. 客户端连接到Web服务器一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
2. 发送HTTP请求通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和数据包4部分组成。
3. 服务器接受请求并返回HTTP响应Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
HTTP协议请求头Request Headers

客户端发送一个HTTP请求到服务器的请求头主要包括:请求行、请求头部、空行、数据包
如下图是一个 POST 请求的信息:

HTTP 协议响应信息 Response

HTTP 协议状态码
状态代码类别原因短语
1xxInfomational(信息性状态码)接收的请求正在处理
2xxSuccess(成功状态码)请求正常处理完毕
3xxRedirection(重定向状态码)需要进行附加 *** 作以完成请求
4xxClient Error(客户端错误状态码)服务器无法处理请求
5xxServer Error(服务器错误状态码)服务器处理请求出错
3、在MDK中编写代码
WebClient客户端代码
web_strdup将字符串复制到新开辟的内存空间
webclient_session_create创建webclient客户端
webclient_header_fields_add将请求句柄封装到客户端缓存区
webclient_header_fields_get解析响应数据的单一消息报头
webclient_header_length_response获取请求头的长度
webclient_handle_response获取服务器响应的状态码
webclient_data_analysis获取服务器返回的数据包
HTTP请求方法
webclient_get_method客户端GET请求方法
webclient_post_method客户端POST请求方法

修改ESP8266.c代码中的NET_DEVICE_LinkServer_Init函数(代码在上一章)

ESP8266_RETTYPE NET_DEVICE_LinkServer_Init(void)
{
	
	unsigned char errCount = 0, errType = 0;
	char cfgBuffer[70];
	
	switch(netDeviceInfo.initStep)
	{
		case 0:
			if(ESP8266_Net_Mode_Choose(STA) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 1:
			if(ESP8266_Enable_MultipleId(DISABLE) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 2:
			if(ESP8266_JoinAP(netDeviceInfo.staName,netDeviceInfo.staPass) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 3:
			//注释掉这一行,因为请求的网址不同
//			if(ESP8266_Link_Server(enumTCP,netDeviceInfo.staIPAddress,netDeviceInfo.staPort,Single_ID_0) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		default:
			 netDeviceInfo.netWork = 1;
			 errType = 3;
			break;
	}
	
	
		return errType;
	
}

在webclient.h中编写以下代码

#ifndef __WEBCLIENT_H_
#define __WEBCLIENT_H_
#include "sys.h"


#ifndef WEBCLIENT_OK
#define WEBCLIENT_OK 0
#endif

#ifndef WEBCLIENT_NOK
#define WEBCLIENT_NOK 1
#endif

typedef struct __webclient_header
{
    char* buffer;

    unsigned int length;                      /* content header buffer size */

    unsigned int size;                        /* maximum support header size */
}webclient_header;

typedef struct __webclient_session
{	
	webclient_header* header;    /* webclient response header information */
	
	int resp_status;
	int content_length;
}webclient_session;


void webclient_get_method(void);
void webclient_post_method(void);

#endif

在webclient.c中编写以下代码

#include "webclient.h"
#include "ESP8266.h"
#include "usart.h"
#include "StringUtil.h"


//将字符串复制到新开辟的内存空间
char* web_strdup(const char* s)
{
	uint16_t len = strlen(s) + 1;
	char* tmp = (char*)malloc(len);

	if (!tmp)
			return NULL;

	memcpy(tmp, s, len);

	return tmp;
}

//创建webclient客户端
webclient_session* webclient_session_create(uint16_t header_sz)
{
	webclient_session* session;
	/* create session */
	session = (webclient_session*)calloc(1, sizeof(webclient_session));
	if (session == NULL)
	{
			printf("webclient create failed, no memory for webclient session!");
			return NULL;
	}
	/* initialize the socket of session */
	session->content_length = -1;
	session->header = (webclient_header*)calloc(1, sizeof(webclient_header));
	if (session->header == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	session->header->size = header_sz;
	session->header->buffer = (char*)calloc(1, header_sz);
	if (session->header->buffer == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	return session;
}

//将请求句柄封装到客户端缓存区
unsigned char webclient_header_fields_add(webclient_session* session, const char* fmt, ...)
{
	int length;
	va_list args;
	va_start(args, fmt);
	length = vsnprintf(session->header->buffer + session->header->length, session->header->size - session->header->length, fmt, args);
	if (length < 0)
	{
			printf("add fields header data failed, return length(%d) error.", length);
			return WEBCLIENT_NOK;
	}
	va_end(args);
	session->header->length += length;
	if (session->header->length >= session->header->size)
	{
			printf("not enough header buffer size(%d)!", session->header->size);
			return WEBCLIENT_NOK;
	}

	return WEBCLIENT_OK;
}



//解析响应数据的单一消息报头
const char* webclient_header_fields_get(webclient_session* session, const char* fields)
{
	char* resp_buf = NULL;
	size_t resp_buf_len = 0;
	char* dataPtr;
	char* mime_ptr = NULL;

	resp_buf = session->header->buffer;

	dataPtr = strstr(resp_buf,fields);
	if(dataPtr != NULL)
	{
		mime_ptr = strstr(dataPtr,":");
		if(mime_ptr != NULL)
		{
				mime_ptr += 1;
				while (*mime_ptr && (*mime_ptr == ' ' || *mime_ptr == '\t'))
					mime_ptr++;
				return mime_ptr;
		}
	}
	
	return NULL;
}

//获取请求头的长度
unsigned int webclient_header_length_response(webclient_session* session)
{
	return (strlen(session->header->buffer) - session->content_length - 4);
}

//获取服务器响应的状态码
unsigned char webclient_handle_response(webclient_session* session)
{
	int rc = 0;
	char* mime_buffer = NULL;
	char* mime_ptr = NULL;
	const char* transfer_encoding;
	int i;

	if(webclient_header_fields_get(session, "Content-Length") != NULL)
	{
		session->content_length = atoi(webclient_header_fields_get(session, "Content-Length"));
	}
	
	session->header->length = webclient_header_length_response(session);

	/* get HTTP status code */
	mime_ptr = web_strdup(session->header->buffer);
	if (strstr(mime_ptr, "HTTP/1."))
	{
		char* ptr = mime_ptr;

		ptr += strlen("HTTP/1.x");

		printf("ptr: %s\r\n", ptr);

		while (*ptr && (*ptr == ' ' || *ptr == '\t'))
				ptr++;

		/* Terminate string after status code */
		for (i = 0; ((ptr[i] != ' ') && (ptr[i] != '\t')); i++);
		ptr[i] = ';'=

		session->resp_status ( int)strtol(,ptrNULL ,10 );}

	if
	( )mime_ptrfree
	{
			()mime_ptr;}
	return
	
	; session->resp_status}
//获取服务器返回的数据包

uint8_t
*webclient_data_analysis (*webclient_session) sessionchar
{
	*; dataptrchar
	*= mime_ptr ; session->header->buffer=
	
	//printf("session->header->buffer:%s\r\n",session->header->buffer);
	
	dataptr strstr (,mime_ptr"\r\n\r\n");if
	(!=dataptr NULL )+=
	{
		dataptr 4 ;return
		( uint8_t*);dataptr}
	return
	
	NULL ;}
//客户端GET请求方法



void
webclient_get_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=en&unit=c HTTP/1.1\r\n");webclient_header_fields_add
	(,session"Host:www.baidu.com\r\n");webclient_header_fields_add
	(,session"\r\n");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接,	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.seniverse.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
//客户端POST请求方法

void
webclient_post_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"POST /devices/583402349/datapoints HTTP/1.1\r\n");webclient_header_fields_add
	(,session"api-key:rBIh6FFxeyW=kVJyybB2FzD5QAQ=\r\n");webclient_header_fields_add
	(,session"Host: api.heclouds.com\r\n");webclient_header_fields_add
	(,session"Content-Length:66\r\n");webclient_header_fields_add
	(,session"\r\n");webclient_header_fields_add
	(,session"{\"datastreams\":[{\"id\":\"test_stream\",\"datapoints\":[{\"value\":30}]}]}");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.heclouds.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
#

在StringUtil.h中编写以下代码

ifndef__STRING_UTIL_h #
define__STRING_UTIL_h #
include"string.h" #
include# 
include# 
include"usart.h" int

find_end (char* , usart_bufferint ) number;int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcRes;void
smart_array (unsignedchar *, addrunsignedchar * )ip;void
Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLen;unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) right;#
endif#

在StringUtil.c中编写以下代码

include"StringUtil.h" /**
*@brief	 	ip网络地址转换
*@param		adr:地址 ip:ip
*@return	无
*/


void
smart_array (unsignedchar *, addrunsignedchar * )ipint
{
    ; ichar
    [ taddr30];char
    * ; nexttokchar
    ; numstrcpy
    (,taddr(char* ))addr;=
    nexttok ; taddrfor
    (=i 0 ;< i 4 ; ++ i)=
    {
        nexttok strtok (,nexttok".");//		if(nexttok[0] == '0' && nexttok[1] == 'x') num = atoi16(nexttok+2,0x10);
//		else num = atoi16(nexttok,10);
[
        ip]i= ; num=
        nexttok NULL ;}
    }
/***********************************************************
  函数名称:Find_string(char *pcBuf,char*left,char*right, char *pcRes)
  函数功能:寻找特定字符串
  入口参数:
           char *pcBuf 为传入的字符串
           char*left   为搜索字符的左边标识符  例如:"["
           char*right  为搜索字符的右边标识符  例如:"]"
		   char *pcRes 为输出转存的字符串数组
  返回值:用来校验是否成功,无所谓的。
  备注: left字符需要唯一,right字符从left后面开始唯一即可
 服务器下发命令举例:+MQTTPUBLISH: 0,0,0,0,/device/NB/zx99999999999999_back,6,[reastrobot]
 此函数会 *** 作内存空间  强烈建议 提前清空buf   memset(Find_token,0x00,sizeof(Find_token));
***********************************************************/
int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcReschar
{
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=
    pcBegin strstr (,pcBuf) left;//找到第一次出现的位置               =
    pcEnd strstr (+pcBeginstrlen()left,) right;//找到右边标识第一次出现位置 if
    (==pcBegin NULL || == pcEnd NULL || ) pcBegin > pcEndprintf
    {
        ("string name not found!\n");return
        0 ;}
    else
    +=
    {
        pcBegin strlen ()left;memcpy
        (,pcRes, pcBegin- pcEnd)pcBegin;return
        1 ;}
    }
//+IPD, 268:hello world\r\n

//过滤left和right之间的字符串,返回过滤之后的字符串
unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) rightchar
{
    *; ptrIPD=

    ptrIPD strstr ((char*),pcBuf) left;//搜索“left”头				if
    ( ==ptrIPD NULL )//						UsartPrintf(USART_DEBUG, "\"left\" not found\r\n");										
    {
        }
    else
    =
    {
        ptrIPD strstr (,ptrIPD) right;//找到'right'							if
        ( !=ptrIPD NULL )+=
        {
            ptrIPDstrlen()right;return
            ( unsignedchar *)()ptrIPD;}
        else
        return
            NULL ;}
    }
//int Smart_array(char *pcBuf,char *fu)


//memcpy(&citc_server_ip[0],back_ip,strstr(back_ip,".")-back_ip);
//{
//  char *pcBegin = NULL;
//	int8_t len =0;
//	pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	memcpy(&pcRes[i], pcBuf,pcBegin-pcBuf);
//	}
//	 len= strlen(pcBuf);
//	 pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	 memcpy(&pcRes[0], pcBuf,pcBegin-pcBuf);
//}
//寻找字符后面最近的结束符

//  int i;
//int find_end(char * usart_buffer, int number) {
//      return number + i+2 ;   //如果有换行符  需要加4
//  for (i = 0; i < 100; i++) {
//    if ((usart_buffer[number + i] == '/') && (usart_buffer[number + i + 1] == '>')) {
//    }
//  }
//}
//智能查找和匹配字符串

int8_t
Find_AttributeStringAll (char* ,pcBufchar * ,pcRestuint16_t, rowuint8_t, colchar * ,leftchar * ,rightuint8_t* )Numchar
{
    [ pcFind20]= 0 {};char
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=

    pcEnd  ; pcBufwhile
    (1)memset
    {
        (,pcFind0,20);=
        pcBegin strstr (+pcEnd1,) left;if
        ((==pcBegin NULL )|| ( strcmp(,pcBegin"}")== 0 ))printf
        {
            ("找到指定字符 !\n");return
            1 ;}
        else
        =
        {
            pcEnd strstr (+pcBeginstrlen()left,) right;if
            ( (==pcEnd NULL )|| ( )pcBegin > pcEnd)printf
            {
                ("Mail name not found!\n");return
                - 1;}
            else
            if
            {
                (*)Num>rowreturn
                {
                    1 ;}
                else
                +=
                {
                    pcBegin strlen ()left;memcpy
                    (,pcFind, pcBegin- pcEnd ) pcBegin;memset
                    (+pcRest**Num,col0,)col;memcpy
                    (+pcRest**Num,col,pcFindsizeof()pcFind);(
                    *)Num++ ;}
                }
            }
        }
    }
void

Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLenchar
{
    ,    ddl;ddhint
    ; ifor

    ( =i0;< i;nLen++ i)=
    {
        ddh 48 + [ pbSrc]i/ 16 ;=
        ddl 48 + [ pbSrc]i% 16 ;if
        ( 57ddh > )= ddh + ddh 7 ;if
        ( 57ddl > )= ddl + ddl 7 ;[
        pbDest*i2]= ; ddh[
        pbDest*i2+1]= ; ddl}
    [

    pbDest*nLen2]= ';' }void
Str2Hex

( char*,char str* )const hexchar
{

    * ="0123456789ABCDEF" cHex ; int=
    0 i;for(
    int=0 j ;<strlen j ( );str++) junsignedint
    {
        = ( a unsigned  int) [] str;j[++
        hex]i=[ ( cHex&0xf0a ) 4] >> ;[++
        hex]i=[ ( cHex&0x0fa ) ];}[
    ]
    hex=i';' } /* USER CODE BEGIN 0 */#
define

在main.c中编写以下代码

REQUEST_METHOD

0//0:GET请求,1:POST请求 /* USER CODE END 0 */ 	int	main
(

void )/* USER CODE BEGIN 1 */unsignedchar
{
  *
	= NULL; dataPtr uint32_t =0
	; request_time uint32_t =0
	; netErr_time = ;uint32_t
	ESP8266_RETTYPE uwRet = ESP8266_NOK0
	; total_len/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init

  (

  )
  ;/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */

  SystemClock_Config

  (

  )
  ;/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */

  MX_GPIO_Init

  (

  )
  ;MX_DMA_Init()
  ;MX_LPUART1_UART_Init()
  ;MX_USART1_UART_Init()
  ;MX_TIM2_Init()
  ;/* USER CODE BEGIN 2 */TIM_Interupt_Enable(
  )
	
	;//使能串口中断USART_Interupt_Enable( )
	
	;//使能定时器中断/* USER CODE END 2 *//* Infinite loop */ /* USER CODE BEGIN WHILE */

	
  while

  (
  1
  ) /* USER CODE END WHILE *//* USER CODE BEGIN 3 */if
  {
    (

    !
		
		.)//如果网络未连接netDeviceInfoifnetWork(	NET_DEVICE_Init
		{
			()==)printf ( ESP8266_OK"初始化成功\r\n"	
			{
				);}}if
			(
		-
		
		10000)time2Count //(1ms * 2000)相当于延时2秒钟 request_time >= if(		.
		{
			)//如果网络连接成功netDeviceInfo#netWorkifREQUEST_METHOD
			{
webclient_get_method( )
					;#elsewebclient_post_method	
()
					;#endif}
}}
		
			/* USER CODE END 3 */
		}
	
  实现的功能
  1、上电自动连接WIFI
2、如果是POST请求,则请求POST接口(我这里用的是ONENET的POST接口)


4、实验现象 [+++][+++]
3、如果是GET请求,则请求GET接口(我这里用的是心知天气的GET接口)

POST请求(Onenet物联网平台)

GET请求(心知天气)

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 2050, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

1、准备开发板

开发板功能区分布图

开发板俯视图

2、HTTP协议介绍 HTTP协议简介

    HTTP(HyperText Transfer Protocol)协议,即超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 协议是基于 TCP/IP 协议的网络应用层协议。
    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。服务器接收到请求之后,通过接收到的信息判断响应方式,并且给予客户端相应的响应,完成整个 HTTP 数据交互流程。

HTTP 工作原理
HTTP 请求/响应的步骤
1. 客户端连接到Web服务器一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
2. 发送HTTP请求通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和数据包4部分组成。
3. 服务器接受请求并返回HTTP响应Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
HTTP协议请求头Request Headers

客户端发送一个HTTP请求到服务器的请求头主要包括:请求行、请求头部、空行、数据包
如下图是一个 POST 请求的信息:

HTTP 协议响应信息 Response

HTTP 协议状态码
状态代码类别原因短语
1xxInfomational(信息性状态码)接收的请求正在处理
2xxSuccess(成功状态码)请求正常处理完毕
3xxRedirection(重定向状态码)需要进行附加 *** 作以完成请求
4xxClient Error(客户端错误状态码)服务器无法处理请求
5xxServer Error(服务器错误状态码)服务器处理请求出错
3、在MDK中编写代码
WebClient客户端代码
web_strdup将字符串复制到新开辟的内存空间
webclient_session_create创建webclient客户端
webclient_header_fields_add将请求句柄封装到客户端缓存区
webclient_header_fields_get解析响应数据的单一消息报头
webclient_header_length_response获取请求头的长度
webclient_handle_response获取服务器响应的状态码
webclient_data_analysis获取服务器返回的数据包
HTTP请求方法
webclient_get_method客户端GET请求方法
webclient_post_method客户端POST请求方法

修改ESP8266.c代码中的NET_DEVICE_LinkServer_Init函数(代码在上一章)

ESP8266_RETTYPE NET_DEVICE_LinkServer_Init(void)
{
	
	unsigned char errCount = 0, errType = 0;
	char cfgBuffer[70];
	
	switch(netDeviceInfo.initStep)
	{
		case 0:
			if(ESP8266_Net_Mode_Choose(STA) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 1:
			if(ESP8266_Enable_MultipleId(DISABLE) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 2:
			if(ESP8266_JoinAP(netDeviceInfo.staName,netDeviceInfo.staPass) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 3:
			//注释掉这一行,因为请求的网址不同
//			if(ESP8266_Link_Server(enumTCP,netDeviceInfo.staIPAddress,netDeviceInfo.staPort,Single_ID_0) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		default:
			 netDeviceInfo.netWork = 1;
			 errType = 3;
			break;
	}
	
	
		return errType;
	
}

在webclient.h中编写以下代码

#ifndef __WEBCLIENT_H_
#define __WEBCLIENT_H_
#include "sys.h"


#ifndef WEBCLIENT_OK
#define WEBCLIENT_OK 0
#endif

#ifndef WEBCLIENT_NOK
#define WEBCLIENT_NOK 1
#endif

typedef struct __webclient_header
{
    char* buffer;

    unsigned int length;                      /* content header buffer size */

    unsigned int size;                        /* maximum support header size */
}webclient_header;

typedef struct __webclient_session
{	
	webclient_header* header;    /* webclient response header information */
	
	int resp_status;
	int content_length;
}webclient_session;


void webclient_get_method(void);
void webclient_post_method(void);

#endif

在webclient.c中编写以下代码

#include "webclient.h"
#include "ESP8266.h"
#include "usart.h"
#include "StringUtil.h"


//将字符串复制到新开辟的内存空间
char* web_strdup(const char* s)
{
	uint16_t len = strlen(s) + 1;
	char* tmp = (char*)malloc(len);

	if (!tmp)
			return NULL;

	memcpy(tmp, s, len);

	return tmp;
}

//创建webclient客户端
webclient_session* webclient_session_create(uint16_t header_sz)
{
	webclient_session* session;
	/* create session */
	session = (webclient_session*)calloc(1, sizeof(webclient_session));
	if (session == NULL)
	{
			printf("webclient create failed, no memory for webclient session!");
			return NULL;
	}
	/* initialize the socket of session */
	session->content_length = -1;
	session->header = (webclient_header*)calloc(1, sizeof(webclient_header));
	if (session->header == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	session->header->size = header_sz;
	session->header->buffer = (char*)calloc(1, header_sz);
	if (session->header->buffer == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	return session;
}

//将请求句柄封装到客户端缓存区
unsigned char webclient_header_fields_add(webclient_session* session, const char* fmt, ...)
{
	int length;
	va_list args;
	va_start(args, fmt);
	length = vsnprintf(session->header->buffer + session->header->length, session->header->size - session->header->length, fmt, args);
	if (length < 0)
	{
			printf("add fields header data failed, return length(%d) error.", length);
			return WEBCLIENT_NOK;
	}
	va_end(args);
	session->header->length += length;
	if (session->header->length >= session->header->size)
	{
			printf("not enough header buffer size(%d)!", session->header->size);
			return WEBCLIENT_NOK;
	}

	return WEBCLIENT_OK;
}



//解析响应数据的单一消息报头
const char* webclient_header_fields_get(webclient_session* session, const char* fields)
{
	char* resp_buf = NULL;
	size_t resp_buf_len = 0;
	char* dataPtr;
	char* mime_ptr = NULL;

	resp_buf = session->header->buffer;

	dataPtr = strstr(resp_buf,fields);
	if(dataPtr != NULL)
	{
		mime_ptr = strstr(dataPtr,":");
		if(mime_ptr != NULL)
		{
				mime_ptr += 1;
				while (*mime_ptr && (*mime_ptr == ' ' || *mime_ptr == '\t'))
					mime_ptr++;
				return mime_ptr;
		}
	}
	
	return NULL;
}

//获取请求头的长度
unsigned int webclient_header_length_response(webclient_session* session)
{
	return (strlen(session->header->buffer) - session->content_length - 4);
}

//获取服务器响应的状态码
unsigned char webclient_handle_response(webclient_session* session)
{
	int rc = 0;
	char* mime_buffer = NULL;
	char* mime_ptr = NULL;
	const char* transfer_encoding;
	int i;

	if(webclient_header_fields_get(session, "Content-Length") != NULL)
	{
		session->content_length = atoi(webclient_header_fields_get(session, "Content-Length"));
	}
	
	session->header->length = webclient_header_length_response(session);

	/* get HTTP status code */
	mime_ptr = web_strdup(session->header->buffer);
	if (strstr(mime_ptr, "HTTP/1."))
	{
		char* ptr = mime_ptr;

		ptr += strlen("HTTP/1.x");

		printf("ptr: %s\r\n", ptr);

		while (*ptr && (*ptr == ' ' || *ptr == '\t'))
				ptr++;

		/* Terminate string after status code */
		for (i = 0; ((ptr[i] != ' ') && (ptr[i] != '\t')); i++);
		ptr[i] = ';'=

		session->resp_status ( int)strtol(,ptrNULL ,10 );}

	if
	( )mime_ptrfree
	{
			()mime_ptr;}
	return
	
	; session->resp_status}
//获取服务器返回的数据包

uint8_t
*webclient_data_analysis (*webclient_session) sessionchar
{
	*; dataptrchar
	*= mime_ptr ; session->header->buffer=
	
	//printf("session->header->buffer:%s\r\n",session->header->buffer);
	
	dataptr strstr (,mime_ptr"\r\n\r\n");if
	(!=dataptr NULL )+=
	{
		dataptr 4 ;return
		( uint8_t*);dataptr}
	return
	
	NULL ;}
//客户端GET请求方法



void
webclient_get_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=en&unit=c HTTP/1.1\r\n");webclient_header_fields_add
	(,session"Host:www.baidu.com\r\n");webclient_header_fields_add
	(,session"\r\n");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接,	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.seniverse.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
//客户端POST请求方法

void
webclient_post_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"POST /devices/583402349/datapoints HTTP/1.1\r\n");webclient_header_fields_add
	(,session"api-key:rBIh6FFxeyW=kVJyybB2FzD5QAQ=\r\n");webclient_header_fields_add
	(,session"Host: api.heclouds.com\r\n");webclient_header_fields_add
	(,session"Content-Length:66\r\n");webclient_header_fields_add
	(,session"\r\n");webclient_header_fields_add
	(,session"{\"datastreams\":[{\"id\":\"test_stream\",\"datapoints\":[{\"value\":30}]}]}");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.heclouds.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
#

在StringUtil.h中编写以下代码

ifndef__STRING_UTIL_h #
define__STRING_UTIL_h #
include"string.h" #
include# 
include# 
include"usart.h" int

find_end (char* , usart_bufferint ) number;int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcRes;void
smart_array (unsignedchar *, addrunsignedchar * )ip;void
Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLen;unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) right;#
endif#

在StringUtil.c中编写以下代码

include"StringUtil.h" /**
*@brief	 	ip网络地址转换
*@param		adr:地址 ip:ip
*@return	无
*/


void
smart_array (unsignedchar *, addrunsignedchar * )ipint
{
    ; ichar
    [ taddr30];char
    * ; nexttokchar
    ; numstrcpy
    (,taddr(char* ))addr;=
    nexttok ; taddrfor
    (=i 0 ;< i 4 ; ++ i)=
    {
        nexttok strtok (,nexttok".");//		if(nexttok[0] == '0' && nexttok[1] == 'x') num = atoi16(nexttok+2,0x10);
//		else num = atoi16(nexttok,10);
[
        ip]i= ; num=
        nexttok NULL ;}
    }
/***********************************************************
  函数名称:Find_string(char *pcBuf,char*left,char*right, char *pcRes)
  函数功能:寻找特定字符串
  入口参数:
           char *pcBuf 为传入的字符串
           char*left   为搜索字符的左边标识符  例如:"["
           char*right  为搜索字符的右边标识符  例如:"]"
		   char *pcRes 为输出转存的字符串数组
  返回值:用来校验是否成功,无所谓的。
  备注: left字符需要唯一,right字符从left后面开始唯一即可
 服务器下发命令举例:+MQTTPUBLISH: 0,0,0,0,/device/NB/zx99999999999999_back,6,[reastrobot]
 此函数会 *** 作内存空间  强烈建议 提前清空buf   memset(Find_token,0x00,sizeof(Find_token));
***********************************************************/
int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcReschar
{
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=
    pcBegin strstr (,pcBuf) left;//找到第一次出现的位置               =
    pcEnd strstr (+pcBeginstrlen()left,) right;//找到右边标识第一次出现位置 if
    (==pcBegin NULL || == pcEnd NULL || ) pcBegin > pcEndprintf
    {
        ("string name not found!\n");return
        0 ;}
    else
    +=
    {
        pcBegin strlen ()left;memcpy
        (,pcRes, pcBegin- pcEnd)pcBegin;return
        1 ;}
    }
//+IPD, 268:hello world\r\n

//过滤left和right之间的字符串,返回过滤之后的字符串
unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) rightchar
{
    *; ptrIPD=

    ptrIPD strstr ((char*),pcBuf) left;//搜索“left”头				if
    ( ==ptrIPD NULL )//						UsartPrintf(USART_DEBUG, "\"left\" not found\r\n");										
    {
        }
    else
    =
    {
        ptrIPD strstr (,ptrIPD) right;//找到'right'							if
        ( !=ptrIPD NULL )+=
        {
            ptrIPDstrlen()right;return
            ( unsignedchar *)()ptrIPD;}
        else
        return
            NULL ;}
    }
//int Smart_array(char *pcBuf,char *fu)


//memcpy(&citc_server_ip[0],back_ip,strstr(back_ip,".")-back_ip);
//{
//  char *pcBegin = NULL;
//	int8_t len =0;
//	pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	memcpy(&pcRes[i], pcBuf,pcBegin-pcBuf);
//	}
//	 len= strlen(pcBuf);
//	 pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	 memcpy(&pcRes[0], pcBuf,pcBegin-pcBuf);
//}
//寻找字符后面最近的结束符

//  int i;
//int find_end(char * usart_buffer, int number) {
//      return number + i+2 ;   //如果有换行符  需要加4
//  for (i = 0; i < 100; i++) {
//    if ((usart_buffer[number + i] == '/') && (usart_buffer[number + i + 1] == '>')) {
//    }
//  }
//}
//智能查找和匹配字符串

int8_t
Find_AttributeStringAll (char* ,pcBufchar * ,pcRestuint16_t, rowuint8_t, colchar * ,leftchar * ,rightuint8_t* )Numchar
{
    [ pcFind20]= 0 {};char
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=

    pcEnd  ; pcBufwhile
    (1)memset
    {
        (,pcFind0,20);=
        pcBegin strstr (+pcEnd1,) left;if
        ((==pcBegin NULL )|| ( strcmp(,pcBegin"}")== 0 ))printf
        {
            ("找到指定字符 !\n");return
            1 ;}
        else
        =
        {
            pcEnd strstr (+pcBeginstrlen()left,) right;if
            ( (==pcEnd NULL )|| ( )pcBegin > pcEnd)printf
            {
                ("Mail name not found!\n");return
                - 1;}
            else
            if
            {
                (*)Num>rowreturn
                {
                    1 ;}
                else
                +=
                {
                    pcBegin strlen ()left;memcpy
                    (,pcFind, pcBegin- pcEnd ) pcBegin;memset
                    (+pcRest**Num,col0,)col;memcpy
                    (+pcRest**Num,col,pcFindsizeof()pcFind);(
                    *)Num++ ;}
                }
            }
        }
    }
void

Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLenchar
{
    ,    ddl;ddhint
    ; ifor

    ( =i0;< i;nLen++ i)=
    {
        ddh 48 + [ pbSrc]i/ 16 ;=
        ddl 48 + [ pbSrc]i% 16 ;if
        ( 57ddh > )= ddh + ddh 7 ;if
        ( 57ddl > )= ddl + ddl 7 ;[
        pbDest*i2]= ; ddh[
        pbDest*i2+1]= ; ddl}
    [

    pbDest*nLen2]= ';' }void
Str2Hex

( char*,char str* )const hexchar
{

    * ="0123456789ABCDEF" cHex ; int=
    0 i;for(
    int=0 j ;<strlen j ( );str++) junsignedint
    {
        = ( a unsigned  int) [] str;j[++
        hex]i=[ ( cHex&0xf0a ) 4] >> ;[++
        hex]i=[ ( cHex&0x0fa ) ];}[
    ]
    hex=i';' } /* USER CODE BEGIN 0 */#
define

在main.c中编写以下代码

REQUEST_METHOD

0//0:GET请求,1:POST请求 /* USER CODE END 0 */ 	int	main
(

void )/* USER CODE BEGIN 1 */unsignedchar
{
  *
	= NULL; dataPtr uint32_t =0
	; request_time uint32_t =0
	; netErr_time = ;uint32_t
	ESP8266_RETTYPE uwRet = ESP8266_NOK0
	; total_len/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init

  (

  )
  ;/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */

  SystemClock_Config

  (

  )
  ;/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */

  MX_GPIO_Init

  (

  )
  ;MX_DMA_Init()
  ;MX_LPUART1_UART_Init()
  ;MX_USART1_UART_Init()
  ;MX_TIM2_Init()
  ;/* USER CODE BEGIN 2 */TIM_Interupt_Enable(
  )
	
	;//使能串口中断USART_Interupt_Enable( )
	
	;//使能定时器中断/* USER CODE END 2 *//* Infinite loop */ /* USER CODE BEGIN WHILE */

	
  while

  (
  1
  ) /* USER CODE END WHILE *//* USER CODE BEGIN 3 */if
  {
    (

    !
		
		.)//如果网络未连接netDeviceInfoifnetWork(	NET_DEVICE_Init
		{
			()==)printf ( ESP8266_OK"初始化成功\r\n"	
			{
				);}}if
			(
		-
		
		10000)time2Count //(1ms * 2000)相当于延时2秒钟 request_time >= if(		.
		{
			)//如果网络连接成功netDeviceInfo#netWorkifREQUEST_METHOD
			{
webclient_get_method( )
					;#elsewebclient_post_method	
()
					;#endif}
}}
		
			/* USER CODE END 3 */
		}
	
  实现的功能
  1、上电自动连接WIFI
2、如果是POST请求,则请求POST接口(我这里用的是ONENET的POST接口)


4、实验现象 [+++]
3、如果是GET请求,则请求GET接口(我这里用的是心知天气的GET接口)

POST请求(Onenet物联网平台)

GET请求(心知天气)

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
STM32玩转物联网实战篇:3.1.ESP8266 WIFI模块WEBClient通信示例详解GET、POST(心知天气、Onenet)_app_内存溢出

STM32玩转物联网实战篇:3.1.ESP8266 WIFI模块WEBClient通信示例详解GET、POST(心知天气、Onenet)

STM32玩转物联网实战篇:3.1.ESP8266 WIFI模块WEBClient通信示例详解GET、POST(心知天气、Onenet),第1张

1、准备开发板

开发板功能区分布图

开发板俯视图

2、HTTP协议介绍 HTTP协议简介

    HTTP(HyperText Transfer Protocol)协议,即超文本传输协议,是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 协议是基于 TCP/IP 协议的网络应用层协议。
    HTTP是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。通过使用网页浏览器、网络爬虫或者其它的工具,客户端发起一个HTTP请求到服务器上指定端口(默认端口为80)。服务器接收到请求之后,通过接收到的信息判断响应方式,并且给予客户端相应的响应,完成整个 HTTP 数据交互流程。

HTTP 工作原理
HTTP 请求/响应的步骤
1. 客户端连接到Web服务器一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。
2. 发送HTTP请求通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和数据包4部分组成。
3. 服务器接受请求并返回HTTP响应Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
HTTP协议请求头Request Headers

客户端发送一个HTTP请求到服务器的请求头主要包括:请求行、请求头部、空行、数据包
如下图是一个 POST 请求的信息:

HTTP 协议响应信息 Response

HTTP 协议状态码
状态代码类别原因短语
1xxInfomational(信息性状态码)接收的请求正在处理
2xxSuccess(成功状态码)请求正常处理完毕
3xxRedirection(重定向状态码)需要进行附加 *** 作以完成请求
4xxClient Error(客户端错误状态码)服务器无法处理请求
5xxServer Error(服务器错误状态码)服务器处理请求出错
3、在MDK中编写代码
WebClient客户端代码
web_strdup将字符串复制到新开辟的内存空间
webclient_session_create创建webclient客户端
webclient_header_fields_add将请求句柄封装到客户端缓存区
webclient_header_fields_get解析响应数据的单一消息报头
webclient_header_length_response获取请求头的长度
webclient_handle_response获取服务器响应的状态码
webclient_data_analysis获取服务器返回的数据包
HTTP请求方法
webclient_get_method客户端GET请求方法
webclient_post_method客户端POST请求方法

修改ESP8266.c代码中的NET_DEVICE_LinkServer_Init函数(代码在上一章)

ESP8266_RETTYPE NET_DEVICE_LinkServer_Init(void)
{
	
	unsigned char errCount = 0, errType = 0;
	char cfgBuffer[70];
	
	switch(netDeviceInfo.initStep)
	{
		case 0:
			if(ESP8266_Net_Mode_Choose(STA) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 1:
			if(ESP8266_Enable_MultipleId(DISABLE) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 2:
			if(ESP8266_JoinAP(netDeviceInfo.staName,netDeviceInfo.staPass) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		case 3:
			//注释掉这一行,因为请求的网址不同
//			if(ESP8266_Link_Server(enumTCP,netDeviceInfo.staIPAddress,netDeviceInfo.staPort,Single_ID_0) == ESP8266_OK)
				netDeviceInfo.initStep++;
			break;
		default:
			 netDeviceInfo.netWork = 1;
			 errType = 3;
			break;
	}
	
	
		return errType;
	
}

在webclient.h中编写以下代码

#ifndef __WEBCLIENT_H_
#define __WEBCLIENT_H_
#include "sys.h"


#ifndef WEBCLIENT_OK
#define WEBCLIENT_OK 0
#endif

#ifndef WEBCLIENT_NOK
#define WEBCLIENT_NOK 1
#endif

typedef struct __webclient_header
{
    char* buffer;

    unsigned int length;                      /* content header buffer size */

    unsigned int size;                        /* maximum support header size */
}webclient_header;

typedef struct __webclient_session
{	
	webclient_header* header;    /* webclient response header information */
	
	int resp_status;
	int content_length;
}webclient_session;


void webclient_get_method(void);
void webclient_post_method(void);

#endif

在webclient.c中编写以下代码

#include "webclient.h"
#include "ESP8266.h"
#include "usart.h"
#include "StringUtil.h"


//将字符串复制到新开辟的内存空间
char* web_strdup(const char* s)
{
	uint16_t len = strlen(s) + 1;
	char* tmp = (char*)malloc(len);

	if (!tmp)
			return NULL;

	memcpy(tmp, s, len);

	return tmp;
}

//创建webclient客户端
webclient_session* webclient_session_create(uint16_t header_sz)
{
	webclient_session* session;
	/* create session */
	session = (webclient_session*)calloc(1, sizeof(webclient_session));
	if (session == NULL)
	{
			printf("webclient create failed, no memory for webclient session!");
			return NULL;
	}
	/* initialize the socket of session */
	session->content_length = -1;
	session->header = (webclient_header*)calloc(1, sizeof(webclient_header));
	if (session->header == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	session->header->size = header_sz;
	session->header->buffer = (char*)calloc(1, header_sz);
	if (session->header->buffer == NULL)
	{
			printf("webclient create failed, no memory for session header buffer!");
			free(session->header);
			free(session);
			session = NULL;
			return NULL;
	}

	return session;
}

//将请求句柄封装到客户端缓存区
unsigned char webclient_header_fields_add(webclient_session* session, const char* fmt, ...)
{
	int length;
	va_list args;
	va_start(args, fmt);
	length = vsnprintf(session->header->buffer + session->header->length, session->header->size - session->header->length, fmt, args);
	if (length < 0)
	{
			printf("add fields header data failed, return length(%d) error.", length);
			return WEBCLIENT_NOK;
	}
	va_end(args);
	session->header->length += length;
	if (session->header->length >= session->header->size)
	{
			printf("not enough header buffer size(%d)!", session->header->size);
			return WEBCLIENT_NOK;
	}

	return WEBCLIENT_OK;
}



//解析响应数据的单一消息报头
const char* webclient_header_fields_get(webclient_session* session, const char* fields)
{
	char* resp_buf = NULL;
	size_t resp_buf_len = 0;
	char* dataPtr;
	char* mime_ptr = NULL;

	resp_buf = session->header->buffer;

	dataPtr = strstr(resp_buf,fields);
	if(dataPtr != NULL)
	{
		mime_ptr = strstr(dataPtr,":");
		if(mime_ptr != NULL)
		{
				mime_ptr += 1;
				while (*mime_ptr && (*mime_ptr == ' ' || *mime_ptr == '\t'))
					mime_ptr++;
				return mime_ptr;
		}
	}
	
	return NULL;
}

//获取请求头的长度
unsigned int webclient_header_length_response(webclient_session* session)
{
	return (strlen(session->header->buffer) - session->content_length - 4);
}

//获取服务器响应的状态码
unsigned char webclient_handle_response(webclient_session* session)
{
	int rc = 0;
	char* mime_buffer = NULL;
	char* mime_ptr = NULL;
	const char* transfer_encoding;
	int i;

	if(webclient_header_fields_get(session, "Content-Length") != NULL)
	{
		session->content_length = atoi(webclient_header_fields_get(session, "Content-Length"));
	}
	
	session->header->length = webclient_header_length_response(session);

	/* get HTTP status code */
	mime_ptr = web_strdup(session->header->buffer);
	if (strstr(mime_ptr, "HTTP/1."))
	{
		char* ptr = mime_ptr;

		ptr += strlen("HTTP/1.x");

		printf("ptr: %s\r\n", ptr);

		while (*ptr && (*ptr == ' ' || *ptr == '\t'))
				ptr++;

		/* Terminate string after status code */
		for (i = 0; ((ptr[i] != ' ') && (ptr[i] != '\t')); i++);
		ptr[i] = ';'=

		session->resp_status ( int)strtol(,ptrNULL ,10 );}

	if
	( )mime_ptrfree
	{
			()mime_ptr;}
	return
	
	; session->resp_status}
//获取服务器返回的数据包

uint8_t
*webclient_data_analysis (*webclient_session) sessionchar
{
	*; dataptrchar
	*= mime_ptr ; session->header->buffer=
	
	//printf("session->header->buffer:%s\r\n",session->header->buffer);
	
	dataptr strstr (,mime_ptr"\r\n\r\n");if
	(!=dataptr NULL )+=
	{
		dataptr 4 ;return
		( uint8_t*);dataptr}
	return
	
	NULL ;}
//客户端GET请求方法



void
webclient_get_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=en&unit=c HTTP/1.1\r\n");webclient_header_fields_add
	(,session"Host:www.baidu.com\r\n");webclient_header_fields_add
	(,session"\r\n");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接,	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.seniverse.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
//客户端POST请求方法

void
webclient_post_method (void)*
{
	webclient_session; sessionuint8_t
	= uwRet ; WEBCLIENT_NOKuint8_t
	* ;dataPtr=
	
	session webclient_session_create ()RX_BUF_MAX_LEN;if
	(==session NULL )printf
	{
		("创建客户端失败\r\n");goto
		; __exit}
	//	webclient_header_fields_add(session,"GET http://%s:%s/getBinFile?IMEI=868626044941824 HTTP/1.1\r\n",netDeviceInfo.staIPAddress,netDeviceInfo.staPort);
	
//	webclient_header_fields_add(session,"\r\n");
//	GET https://api.seniverse.com/v3/weather/now.json?key=smtq3n0ixdggurox&location=nanning&language=zh-Hans&unit=c HTTP/1.1\r\n	
webclient_header_fields_add

	(,session"POST /devices/583402349/datapoints HTTP/1.1\r\n");webclient_header_fields_add
	(,session"api-key:rBIh6FFxeyW=kVJyybB2FzD5QAQ=\r\n");webclient_header_fields_add
	(,session"Host: api.heclouds.com\r\n");webclient_header_fields_add
	(,session"Content-Length:66\r\n");webclient_header_fields_add
	(,session"\r\n");webclient_header_fields_add
	(,session"{\"datastreams\":[{\"id\":\"test_stream\",\"datapoints\":[{\"value\":30}]}]}");if
	
	(ESP8266_DisconnectServer(0)!= ) ESP8266_OK//断开服务器连接	goto
		; __exitif
	
	(ESP8266_Link_Server(,enumTCP"api.heclouds.com","80",)Single_ID_0== ) ESP8266_OK//连接服务器	=
	{
	
		uwRet ESP8266_SendData (,DISABLE(uint8_t*),session->header->buffer,session->header->length)Single_ID_0;//发送数据	if
		
		(==uwRet ) WEBCLIENT_OK//发送成功	=
		{
			dataPtr ESP8266_GetIPD (,DISABLE2000);//解析服务器返回的数据	if
			(!=dataPtr NULL )memset
			{

				(,session->header->buffer0,)session->header->size;=
				session->header->length 0 ;memcpy
				
				(,session->header->buffer,dataPtr)session->header->size;if
				
				(webclient_handle_response()session== 200 )//解析服务器返回的状态码	printf
				{
				
					(,"strlen(session->header->buffer):%d\r\n"strlen()session->header->buffer);printf
					(,"session->header->length:%d\r\n")session->header->length;=

					dataPtr webclient_data_analysis ()session;//获取服务器返回的数据		if
					(!=dataPtr NULL )if
					{
						(strstr((char*),dataPtr"+IPD,"))//查找是否有IPD头		=
						{
							dataPtr Filter_string ((char*),dataPtr(char*)"+IPD,",(char*)":");//过滤IPD头	if
							(!=dataPtrNULL)printf
							{
								("dataPtr:%s\r\n",)dataPtr;}
								//printf("session->content_length:%d\r\n",session->content_length);
							}
						else
						printf
						{
								("dataPtr:%s\r\n",)dataPtr;}
						}
					}
					
				}
			}
		}
	:

__exitif
	(!=session->header->buffer NULL )free
	{
		()session->header->buffer;=
		session->header->bufferNULL;}
	if
	(!=session NULL )free
	{
		()session;=
		session NULL ;}
	}
#

在StringUtil.h中编写以下代码

ifndef__STRING_UTIL_h #
define__STRING_UTIL_h #
include"string.h" #
include# 
include# 
include"usart.h" int

find_end (char* , usart_bufferint ) number;int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcRes;void
smart_array (unsignedchar *, addrunsignedchar * )ip;void
Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLen;unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) right;#
endif#

在StringUtil.c中编写以下代码

include"StringUtil.h" /**
*@brief	 	ip网络地址转换
*@param		adr:地址 ip:ip
*@return	无
*/


void
smart_array (unsignedchar *, addrunsignedchar * )ipint
{
    ; ichar
    [ taddr30];char
    * ; nexttokchar
    ; numstrcpy
    (,taddr(char* ))addr;=
    nexttok ; taddrfor
    (=i 0 ;< i 4 ; ++ i)=
    {
        nexttok strtok (,nexttok".");//		if(nexttok[0] == '0' && nexttok[1] == 'x') num = atoi16(nexttok+2,0x10);
//		else num = atoi16(nexttok,10);
[
        ip]i= ; num=
        nexttok NULL ;}
    }
/***********************************************************
  函数名称:Find_string(char *pcBuf,char*left,char*right, char *pcRes)
  函数功能:寻找特定字符串
  入口参数:
           char *pcBuf 为传入的字符串
           char*left   为搜索字符的左边标识符  例如:"["
           char*right  为搜索字符的右边标识符  例如:"]"
		   char *pcRes 为输出转存的字符串数组
  返回值:用来校验是否成功,无所谓的。
  备注: left字符需要唯一,right字符从left后面开始唯一即可
 服务器下发命令举例:+MQTTPUBLISH: 0,0,0,0,/device/NB/zx99999999999999_back,6,[reastrobot]
 此函数会 *** 作内存空间  强烈建议 提前清空buf   memset(Find_token,0x00,sizeof(Find_token));
***********************************************************/
int
Find_string (char* ,pcBufchar* ,leftchar* ,rightchar * )pcReschar
{
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=
    pcBegin strstr (,pcBuf) left;//找到第一次出现的位置               =
    pcEnd strstr (+pcBeginstrlen()left,) right;//找到右边标识第一次出现位置 if
    (==pcBegin NULL || == pcEnd NULL || ) pcBegin > pcEndprintf
    {
        ("string name not found!\n");return
        0 ;}
    else
    +=
    {
        pcBegin strlen ()left;memcpy
        (,pcRes, pcBegin- pcEnd)pcBegin;return
        1 ;}
    }
//+IPD, 268:hello world\r\n

//过滤left和right之间的字符串,返回过滤之后的字符串
unsigned
char *Filter_string (char*, pcBufchar *, leftchar *) rightchar
{
    *; ptrIPD=

    ptrIPD strstr ((char*),pcBuf) left;//搜索“left”头				if
    ( ==ptrIPD NULL )//						UsartPrintf(USART_DEBUG, "\"left\" not found\r\n");										
    {
        }
    else
    =
    {
        ptrIPD strstr (,ptrIPD) right;//找到'right'							if
        ( !=ptrIPD NULL )+=
        {
            ptrIPDstrlen()right;return
            ( unsignedchar *)()ptrIPD;}
        else
        return
            NULL ;}
    }
//int Smart_array(char *pcBuf,char *fu)


//memcpy(&citc_server_ip[0],back_ip,strstr(back_ip,".")-back_ip);
//{
//  char *pcBegin = NULL;
//	int8_t len =0;
//	pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	memcpy(&pcRes[i], pcBuf,pcBegin-pcBuf);
//	}
//	 len= strlen(pcBuf);
//	 pcBegin = strstr(pcBuf, fu);//找到第一次出现的位置
//	 memcpy(&pcRes[0], pcBuf,pcBegin-pcBuf);
//}
//寻找字符后面最近的结束符

//  int i;
//int find_end(char * usart_buffer, int number) {
//      return number + i+2 ;   //如果有换行符  需要加4
//  for (i = 0; i < 100; i++) {
//    if ((usart_buffer[number + i] == '/') && (usart_buffer[number + i + 1] == '>')) {
//    }
//  }
//}
//智能查找和匹配字符串

int8_t
Find_AttributeStringAll (char* ,pcBufchar * ,pcRestuint16_t, rowuint8_t, colchar * ,leftchar * ,rightuint8_t* )Numchar
{
    [ pcFind20]= 0 {};char
    * =pcBegin NULL ;char
    * =pcEnd NULL ;=

    pcEnd  ; pcBufwhile
    (1)memset
    {
        (,pcFind0,20);=
        pcBegin strstr (+pcEnd1,) left;if
        ((==pcBegin NULL )|| ( strcmp(,pcBegin"}")== 0 ))printf
        {
            ("找到指定字符 !\n");return
            1 ;}
        else
        =
        {
            pcEnd strstr (+pcBeginstrlen()left,) right;if
            ( (==pcEnd NULL )|| ( )pcBegin > pcEnd)printf
            {
                ("Mail name not found!\n");return
                - 1;}
            else
            if
            {
                (*)Num>rowreturn
                {
                    1 ;}
                else
                +=
                {
                    pcBegin strlen ()left;memcpy
                    (,pcFind, pcBegin- pcEnd ) pcBegin;memset
                    (+pcRest**Num,col0,)col;memcpy
                    (+pcRest**Num,col,pcFindsizeof()pcFind);(
                    *)Num++ ;}
                }
            }
        }
    }
void

Hex2Str (char* ,pbDestchar * ,pbSrcint ) nLenchar
{
    ,    ddl;ddhint
    ; ifor

    ( =i0;< i;nLen++ i)=
    {
        ddh 48 + [ pbSrc]i/ 16 ;=
        ddl 48 + [ pbSrc]i% 16 ;if
        ( 57ddh > )= ddh + ddh 7 ;if
        ( 57ddl > )= ddl + ddl 7 ;[
        pbDest*i2]= ; ddh[
        pbDest*i2+1]= ; ddl}
    [

    pbDest*nLen2]= ';' }void
Str2Hex

( char*,char str* )const hexchar
{

    * ="0123456789ABCDEF" cHex ; int=
    0 i;for(
    int=0 j ;<strlen j ( );str++) junsignedint
    {
        = ( a unsigned  int) [] str;j[++
        hex]i=[ ( cHex&0xf0a ) 4] >> ;[++
        hex]i=[ ( cHex&0x0fa ) ];}[
    ]
    hex=i';' } /* USER CODE BEGIN 0 */#
define

在main.c中编写以下代码

REQUEST_METHOD

0//0:GET请求,1:POST请求 /* USER CODE END 0 */ 	int	main
(

void )/* USER CODE BEGIN 1 */unsignedchar
{
  *
	= NULL; dataPtr uint32_t =0
	; request_time uint32_t =0
	; netErr_time = ;uint32_t
	ESP8266_RETTYPE uwRet = ESP8266_NOK0
	; total_len/* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init

  (

  )
  ;/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */

  SystemClock_Config

  (

  )
  ;/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */

  MX_GPIO_Init

  (

  )
  ;MX_DMA_Init()
  ;MX_LPUART1_UART_Init()
  ;MX_USART1_UART_Init()
  ;MX_TIM2_Init()
  ;/* USER CODE BEGIN 2 */TIM_Interupt_Enable(
  )
	
	;//使能串口中断USART_Interupt_Enable( )
	
	;//使能定时器中断/* USER CODE END 2 *//* Infinite loop */ /* USER CODE BEGIN WHILE */

	
  while

  (
  1
  ) /* USER CODE END WHILE *//* USER CODE BEGIN 3 */if
  {
    (

    !
		
		.)//如果网络未连接netDeviceInfoifnetWork(	NET_DEVICE_Init
		{
			()==)printf ( ESP8266_OK"初始化成功\r\n"	
			{
				);}}if
			(
		-
		
		10000)time2Count //(1ms * 2000)相当于延时2秒钟 request_time >= if(		.
		{
			)//如果网络连接成功netDeviceInfo#netWorkifREQUEST_METHOD
			{
webclient_get_method( )
					;#elsewebclient_post_method	
()
					;#endif}
}}
		
			/* USER CODE END 3 */
		}
	
  实现的功能
  1、上电自动连接WIFI
2、如果是POST请求,则请求POST接口(我这里用的是ONENET的POST接口)


4、实验现象
3、如果是GET请求,则请求GET接口(我这里用的是心知天气的GET接口)

POST请求(Onenet物联网平台)

GET请求(心知天气)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1295018.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存