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);
}