关于ESP8266,网上的程序控制例程也很多,这里就不详细写出来。这节我们来写写怎么编写一个应用程序,打包HTTP格式的数据并传递到HTTP服务器,定义格式如下:
HTTP POST请求,格式为from-data,也就是表单格式:
主要包括date、text1、place三个字段,分别代表日期和时间,序号,位置。
有了以上这三个字段,我们很容易就可以用C语言封装出两个字符串数组,一个用来表示HTTP请求头、一个用来表示HTTP请求数据包。
//请求头部 char upload_head[] = "POST /api/upload/messages HTTP/1.1\r\n" "Host: %s:%d\r\n" "content-type: multipart/form-data; boundary=--------------------------359443142220480708322079\r\n" "content-length: %d\r\n\r\n";
其中,Host对应后面的%s:%d表示HTTP服务器的地址以及端口号,这是需要通过用户写入的。content-length后的%d也是需要用户自行填写,表示请求数据的长度,这个也需要用户去计算,因为上传的数据大小会随着表单数据大小而改变。
接下来看以下请求数据:
//请求数据 char upload_data[] = { "----------------------------359443142220480708322079\r\n" "Content-Disposition: form-data; name=\"date\"\r\n\r\n" "%s" "\r\n----------------------------359443142220480708322079\r\n" "Content-Disposition: form-data; name=\"text1\"\r\n\r\n" "%s" "\r\n----------------------------359443142220480708322079\r\n" "Content-Disposition: form-data; name=\"place\"\r\n\r\n" "%s" "\r\n----------------------------359443142220480708322079--\r\n" };
这里的三个%s分别代表日期和时间、序号、位置,需要用户自行填写。
接下来分别写一个函数用来打包HTTP头以及HTTP数据,打包HTTP头:
//打包HTTP头 int Head_Package(const char *server_ip,int port_num,int ContentLength,char *out_data) { int len = 0 ; char *up_head = NULL ; if(NULL == server_ip || NULL == out_data) return -1 ; if(ContentLength < 0 || port_num < 0) return -2 ; up_head = MALLOC(DATE_LEN); if(NULL != up_head) snprintf(up_head,DATE_LEN,upload_head,server_ip,port_num,ContentLength); if(NULL != out_data) sprintf(out_data,"%s",up_head); else return -3 ; len = strlen(up_head); FREE(up_head); return len; }
打包HTTP数据包:
//打包HTTP数据 int Data_Package(const char *date,const char *text1,const char *place,char *out_data) { int len = 0 ; char *up_data = NULL ; if(NULL == date || NULL == text1 || NULL == place || NULL == out_data) return -1 ; up_data = MALLOC(DATE_LEN); if(NULL != up_data) snprintf(up_data,DATE_LEN,upload_data,date,text1,place); if(NULL != out_data) sprintf(out_data,"%s",up_data); else return -2 ; len = strlen(up_data); FREE(up_data); return len; }
其中MALLOC、FREE、DATE_LEN分别为以下宏定义:
#define MALLOC(x) malloc(x) #define FREE(x) free(x) #define TOTAL_DATA_LEN 1500 #define MAX_DATA_LEN 2048 #define DATE_LEN 512
将HTTP头和数据封装成一个函数:
//HTTP数据上传 int Http_Data_Upload(char *server_ip,int port_num,char *time,char *text1,char *place,char *out_buffer) { int ContentLength = 0 ; char *http_head = NULL ; char *http_data = NULL ; char *upload_http_data = NULL ; http_head = MALLOC(DATE_LEN); if(NULL == http_head) return -1 ; http_data = MALLOC(DATE_LEN); if(NULL == http_data) return -2 ; upload_http_data = MALLOC(TOTAL_DATA_LEN); if(NULL == upload_http_data) return -3 ; ContentLength = Data_Package(time,text1,place,http_data); Head_Package(server_ip,port_num,ContentLength,http_head); sprintf(upload_http_data,"%s%s",http_head,http_data); sprintf(out_buffer,"%s",upload_http_data); FREE(http_head); FREE(http_data); FREE(upload_http_data); return 0 ; }
接下来编写一个简单的函数来进行测试:
void ESP8266_StaTcpClient_UnvarnishTest ( void ) { char *upload_http_data = NULL ; char *http_hex_data = NULL ; upload_http_data = malloc(TOTAL_DATA_LEN); if(NULL == upload_http_data) return ; http_hex_data = malloc(MAX_DATA_LEN); if(NULL == http_hex_data) return ; //给ESP8266上电 macESP8266_CH_ENABLE(); //测试模块是否已经启动 ESP8266_AT_Test (); //设置模式为STA ESP8266_Net_Mode_Choose ( STA ); //连接热点 while ( ! ESP8266_JoinAP ( macUser_ESP8266_ApSsid, macUser_ESP8266_ApPwd ) ); //关闭多连接 ESP8266_Enable_MultipleId ( DISABLE ); //连接服务器IP以及端口号 while ( ! ESP8266_Link_Server ( enumTCP, macUser_ESP8266_TcpServer_IP, macUser_ESP8266_TcpServer_Port, Single_ID_0 ) ); //开启透传模式 while ( ! ESP8266_UnvarnishSend () ); printf ( "\r\n配置 ESP8266 完毕\r\n" ); while ( 1 ) { memset(upload_http_data,0,strlen(upload_http_data)); //封装HTTP头以及数据 Http_Data_Upload(SERVER_IP,SERVER_PORT,"2017/08/15 12:20","12345678910","114.0925,225.3369",upload_http_data); //获得要上传的HTTP数据 Get_Hex_Http_Packet_Data(upload_http_data,http_hex_data); printf("%s\n",upload_http_data); //通过WIFI透传的形式将数据发送到服务器 ESP8266_SendString ( ENABLE, upload_http_data, 0, Single_ID_0 ); //发送http数据 Delay_ms (5000); } }
在主函数中调用它:
/** * @brief 主函数 * @param 无 * @retval 无 */ int main ( void ) { USARTx_Config (); //初始化串口1 SysTick_Init (); //配置 SysTick 为 1ms 中断一次 ESP8266_Init (); //初始化WiFi模块使用的接口和外设 ESP8266_StaTcpClient_UnvarnishTest (); while ( 1 ); }
最后在我的后台可以成功的看见我的数据成功上传:
当然,本文仅仅只是为了测试这个模块是否能够正常将数据上传,并没有做过多的考虑,仅供参考;真正应用需要根据实际产品需求以及业务需求去做设计。
优质嵌入式学习干货推荐:包括ARM裸机开发、Linux设备驱动程序、Linux应用程序开发、Android系统学习、Linux设备树等。