1. 程式人生 > >ESP8266例程解析②PostAndGet

ESP8266例程解析②PostAndGet

函式邏輯
設定串列埠速率
設定wifi模式
設定連線WiFi資訊
連線路由器
啟動定時器函式
檢測狀態
解析HTTP網址

返回資料
每隔一段時間啟動定時器 更新資料
執行呼叫函式時須關閉定時器

user_main.c

#include "driver/uart.h"
#include "user_main.h"

os_timer_t checkTimer_wifistate;

void Check_WifiState(void) {
	uint8 getState;
	getState = wifi_station_get_connect_status();

	//如果狀態正確,證明已經成功連線到路由器
	if (getState == STATION_GOT_IP) {
		os_printf("WIFI連線成功!");
		os_timer_disarm(&checkTimer_wifistate); //取消定時器定時
		os_timer_disarm(&connect_timer);

		uint8 status = wifi_station_get_connect_status();
		if (status == STATION_GOT_IP) {
			uart0_sendStr("WIFI連線成功!");
			startHttpQuestByGET(
					"https://api.seniverse.com/v3/weather/now.json?key=your_api_key&location=beijing&language=zh-Hans&unit=c");
			return;
		}
	}

}
void user_init() {

	uart_init(57600, 57600);
	wifi_set_opmode(0x01); //設定為STATION模式
	struct station_config stationConf;
	os_strcpy(stationConf.ssid, "IAmYourFather");	  //改成你自己的   路由器的使用者名稱
	os_strcpy(stationConf.password, "666666666"); //改成你自己的   路由器的密碼
	wifi_station_set_config(&stationConf); //設定WiFi station介面配置,並儲存到 flash
	wifi_station_connect(); //連線路由器

	os_timer_disarm(&checkTimer_wifistate); //取消定時器定時
	os_timer_setfn(&checkTimer_wifistate, (os_timer_func_t *) Check_WifiState,
	NULL); //設定定時器回撥函式
	os_timer_arm(&checkTimer_wifistate, 500, true); //啟動定時器,單位:毫秒
	os_printf("57600 end... \n\r");
}
void user_rf_pre_init() 
{
}

在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
示例:

void ICACHE_FLASH_ATTR

user_set_station_config(void)

{

    char ssid[32] = SSID; 
    
    char password[64] = PASSWORD; 
    
    struct station_config stationConf; 
    
    stationConf.bssid_set = 0; //need not check MAC address of AP
    
    os_memcpy(&stationConf.ssid, ssid, 32); 
    
    os_memcpy(&stationConf.password, password, 64); 
    
    wifi_station_set_config(&stationConf);
}
void user_init(void)

{

    wifi_set_opmode(STATIONAP_MODE); //Set softAP + station mode
    user_set_station_config();
}

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

my_http.c

#include "my_http.h"
#include "c_types.h"
#include "client.h"
    
//剖析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)){
		uart0_sendStr("\r\n ----- URL return -----  \r\n");
		return;
	}

	PA = URL;

	if (!strncmp(PA, "http://", strlen("http://")))  //字串比較函式 1 2 比較3的位數  如果相等 執行
	 {
		PA = URL + strlen("http://");
	} 
	else if (!strncmp(PA, "https://", strlen("https://"))) 
   {
		PA = URL + strlen("https://");
	}

	PB = strchr(PA, '/');  //字串1為一個字串的指標,字元2為一個待查詢字元 該函式返回在字串 str 中第一次出現字元2 的位置,如果未找到該字元則返回 NULL。

	if (PB)
	 {
		uart0_sendStr("\r\n ----- PB=true -----  \r\n");
		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;

		uart0_sendStr(host,strlen(host));

	} 
	else
	 {
		uart0_sendStr("\r\n ----- PB=false -----  \r\n");
		memcpy(host, PA, strlen(PA));
		host[strlen(PA)] = 0;
		uart0_sendStr(host,strlen(host));
	}

	PA = strchr(host, ':');

	if (PA)
	{
		*port = atoi(PA + 1);
	}
   else
   {
		*port = 80;
	}
}

//尋找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);
	my_station_init(ipaddr, &info.ip, port);
}

//定義Get請求的實現
void ICACHE_FLASH_ATTR startHttpQuestByGET(char *URL)
{
	struct ip_addr addr;
	memset(buffer,0,1024);     //填充值  記憶體塊指標 填充值 填充大小
	http_parse_request_url(URL,host,filename,&port); //HTTP解析
	os_sprintf(buffer,GET,filename,host);//註釋見後面
	espconn_gethostbyname(&user_tcp_conn,host, &addr,
	user_esp_dns_found);//註釋見後面
}


//定義Post請求的實現
void ICACHE_FLASH_ATTR startHttpQuestByPOST(char *URL,char *method,char *postdata)
{
	struct ip_addr addr;
	memset(buffer,0,1024);
	http_parse_request_url(URL,host,filename,&port);
	os_sprintf(buffer,POST,filename,strlen(postdata),host,postdata);
	espconn_gethostbyname(&user_tcp_conn,host, &addr,
	user_esp_dns_found);
}

原型
os_sprintf( char *buffer, const char *format, [ argument] … );
引數列表
buffer:char型指標,指向將要寫入的字串的緩衝區。
format:格式化字串。
[argument]…:可選引數,可以是任何型別的資料。
返回值
返回寫入buffer 的字元數,出錯則返回-1. 如果 buffer 或 format 是空指標,且不出錯而繼續,函式將返回-1,並且 errno 會被設定為 EINVAL。
sprintf 返回以format為格式argument為內容組成的結果被寫入buffer 的位元組數,結束字元‘\0’不計入內。即,如果“Hello”被寫入空間足夠大的buffer後,函式sprintf 返回5。 [1]
同時buffer的內容將被改變。

/****************************************************************************

*FunctionName:espconn_gethostbyname

*描述:將主機名(字串)解析為IP地址。

*引數:pespconn——espconn解析主機名

  • hostname——要查詢的主機名

  • addr——指向ip_addr_t的指標,如果

*它已經快取在dns_table中(僅在ESPCONN_OK時有效)。

*返回!)

*.找到.——成功或失敗時呼叫的回撥函式

*或超時(僅當返回ERR_INPROGRESS時!)

*返回:err_t返回程式碼

*.–如果主機名是有效的IP地址字串或主機,則ESPCONN_OK

*.name已經在本地名稱表中。

*.–ESPCONN_INPROGRESS對要傳送到DNS伺服器的請求進行排隊

*如果沒有出現錯誤,則進行解析。

*-ESPCONN_ARG:dns客戶端未初始化或主機名無效

*******************************************************************************/

err_t espconn_gethostbyname(struct espconnpespconn、const charhostname、ip_addr_t*addr、dns_find_callback.);

客戶端
client.c

#include "client.h"
#include "iconv.h"
#include "stdio.h"
#include "string.h"

//成功接收到伺服器返回資料函式
void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg, char *pdata,
		unsigned short len) {
	uart0_sendStr("\r\n ----- 開始接受資料----- \r\n ");
	uart0_tx_buffer(pdata, strlen(pdata));
	uart0_sendStr("\r\n -----結束接受資料-----  \r\n ");

}

//傳送資料到伺服器成功的回撥函式
void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg) {
	uart0_sendStr("傳送資料成功!\r\n ");
}

//斷開伺服器成功的回撥函式
void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg) {
	uart0_sendStr("斷開連線成功!\r\n ");
}

//連線失敗的回撥函式,err為錯誤程式碼
void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err) {
	uart0_sendStr("連線錯誤,錯誤程式碼為%d\r\n", err);
	espconn_connect((struct espconn *) arg);
}

//成功連線到伺服器的回撥函式
void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg) {
	struct espconn *pespconn = arg;
	espconn_regist_recvcb(pespconn, user_tcp_recv_cb);
	espconn_regist_sentcb(pespconn, user_tcp_sent_cb);
	espconn_regist_disconcb(pespconn, user_tcp_discon_cb);

	uart0_sendStr("\r\n ----- 請求資料開始----- \r\n");
	uart0_tx_buffer(buffer, strlen(buffer));
	uart0_sendStr("\r\n -----請求資料結束-----  \r\n");

	espconn_sent(pespconn, buffer, strlen(buffer));

}
void ICACHE_FLASH_ATTR my_station_init(struct ip_addr *remote_ip,
		struct ip_addr *local_ip, int remote_port) {
	//配置
	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);  //連線失敗的回撥函式,err為錯誤程式碼
	//連線伺服器
	espconn_connect(&user_tcp_conn);
}