【ESP8266】NONOS SDK开发,发送HTTP请求
網絡方面不是很懂,可能描述有一點不準確。
主要是通過ESP8266,在NONOS-SDK環境下,用URL地址,發出HTTP請求,接收并處理信息。
假設已經大致了解廠家提供的SDK,以及Eclipse開發環境如何使用,現在大致要做的是以下幾步:
1、連上WiFi(連上網絡)
2、與URL地址的服務器建立TCP連接
3、發出HTTP請求
4、接收并處理信息
現在就開始一步步地講:
一、連上WiFi
連上WiFi這里我采用比較笨的方式,就是固定的WiFi和密碼,直接連上就是了
需要用到幾個函數:
| 1234567891011 | bool wifi_set_opmode (uint8 opmode); //設置ESP8266模式,選擇station模式wifi_station_set_config(&stationConf); //設置連接WiFi的參數//有結構體:struct station_config {uint8 ssid[32]; //ssiduint8 password[64]; //密碼uint8 bssid_set;uint8 bssid[6];};bool wifi_station_connect (void); //連接WiFiuint8 wifi_station_get_connect_status (void); //獲取連接狀態 |
?來自CODE的代碼片 wifi_func
1)設置ESP8266 的工作模式;
2)設置好WiFi的SSID和密碼;
3)開始連接WiFi;
4)檢查WiFi連接狀態,若為5則連接成功。
| 1234567891011121314151617181920212223242526272829303132333435363738394041 | 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} |
?來自CODE的代碼片 init_collectwifi.c
在開始初始化的時候應該還要有一句?wifi_set_opmode(STATION_MODE);
二、建立TCP連接
這里又分為幾步:
1)解析URL,獲取域名
要建立TCP連接,首先應該獲取服務器的域名。
舉個例子:https://code.csdn.net/snippets_manage
那么域名就應該是code.csdn.net,我們要建立連接也是與這個服務器建立連接,所以我們需要把URL地址拆開
| 123456789101112131415161718192021222324252627282930 | 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;} |
?來自CODE的代碼片 http_parse_request_url.c
2)解析域名,轉換成IP地址
這里,當它找到對應的IP地址后,會有調用回調函數,我們可以在回調函數中進行TCP連接
我是這樣調用這個函數的:espconn_gethostbyname(&user_tcp_conn,host, &addr,user_esp_dns_found);
3)TCP連接
| 123456 | //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);} |
?來自CODE的代碼片 dns_cb.c
獲得了IP地址后就可以連接了
| 12345678910111213141516171819202122232425262728293031 | /** 函數名: 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 DEBUGos_printf("\r\ncall iot_station_init\n");#endifuser_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 DEBUGos_printf("espconn_connect\n");#endifespconn_connect(&user_tcp_conn);return true;} |
?來自CODE的代碼片 iot_station_init
三、發送HTTP請求
在(二)中的函數應該是在要發出命令時一氣呵成的,所以這里我們應該封裝好一個接口函數,
只要用戶給出URL和發送的命令時,系統就能自動完成功能。
| 123456789101112131415161718 | void ICACHE_FLASH_ATTR HttpReadFile(char *URL,char *method,char *postdata){struct ip_addr addr;memset(buffer,0,1024);#ifdef DEBUGos_printf("\r\nThe URL request:\n%s\n", URL);#endifhttp_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);} |
?來自CODE的代碼片 HttpReadFile
這里有包含頭文件 my_client.h ,里面定義了GET和POST的格式
| 12345678910111213141516171819202122 | #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_ */ |
?來自CODE的代碼片 my_client.h
四、接收信息
在之前一直沒有講,在建立了TCP連接后有四個很重要的回調函數要聲明。
就是上面my_client.h中的四個回調函數
| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 | /** 函數名: user_tcp_sent_cb* 描述: tcp發送成功后的回調函數* 輸入: arg:tcp連接句柄* 返回: 無* 調用: 無*/void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg){#ifdef DEBUGos_printf("\r\nsend success!");#endif}/** 函數名: user_tcp_discon_cb* 描述: tcp連接斷開后的回調函數* 輸入: arg:tcp連接句柄* 返回: 無* 調用: 無*/void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg){#ifdef DEBUGos_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 DEBUGos_printf("connect err,errno:%d\r\n",err);#endifespconn_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 DEBUGos_printf("\r\nconnect success!");#endif } |
?來自CODE的代碼片 tcp_cb
收到信號后的處理,我們就寫在recv_cb里面就可以了
但是有一點要注意的是:我們使用的這個NONOS_SDK,它是有看門狗的,當回調函數執行時間過長是會導致重啟的!
參考資料: HTTP和URL介紹?http://www.cnblogs.com/LDSmallCat/p/4942039.html ESP8266 SDK 編程手冊.pdf 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的【ESP8266】NONOS SDK开发,发送HTTP请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【ESP8266】ESP8266_NON
- 下一篇: 【ESP8266】NONOS SDK开发