1. 程式人生 > >微控制器使用HTTP POST方式傳送資料

微控制器使用HTTP POST方式傳送資料

HTTP請求是依賴TCP的,也就是在微控制器上面,我們一樣可以使用,無非就是先發送一個http請求頭,再發送正文,比如我最近就使用了http post方式傳送資料到伺服器,伺服器端使用的是WEB API,微控制器使用的STM32 與SIM800C,SIM800C使用GPRS連線伺服器,採用透傳方式,TCP連線,在這裡就不講述TCP連線方式了,假設你已經會使用TCP方式連線伺服器,併發送數了。

以下程式碼只會教會你怎麼發起http請求,具體的傳送介面底層這裡不做說明,以及json打包等操作也不做說明,json打包就是不停的使用sprintf即可。

#define POST_VER							"1.00"						//此處必須是浮點或整數
#define POST_REAL_DATA_STRING				"RealData"					//實時資料上報定義
#define POST_API_URL						"/api/RTU_DataInterface"	//介面地址

//POST請求的http頭資訊,引數1:API地址,引數2:伺服器IP,引數3:後續資料長度
static const char *const HTTP_POST_HEAD = 	
{
"POST %s HTTP/1.1\r\n\
Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n\
X-Requested-With: XMLHttpRequest\r\n\
Host: %s\r\n\
Content-Length: %d\r\n\
Expect: 100-continue\r\n\
Connection: Keep-Alive\r\n" //最後面必須空一行
}

//傳送http post請求

/*************************************************************************************************************************
* 函式			:	bool POST_SendHttpHead(POST_HANDLE *pHandle, u16 DataLen)
* 功能			:	傳送http POST請求頭
* 引數			:	pHandle:控制代碼;AcqTime:觀測時間;pData:實時資料指標;SerialNumber:流水號;AlarmStatus:報警定義
* 返回			:	長度
* 依賴			:	無
* 作者			:	
[email protected]
* 時間 : 2018-02-04 * 最後修改時間 : 2018-02-04 * 說明 : 將報文打包寫入到了pPackDataBuff中 *************************************************************************************************************************/ bool POST_SendHttpHead(POST_HANDLE *pHandle, u16 DataLen) { int len; char IpBuff[16]; if(pHandle->pHttpHeadDataBuff == NULL) DEBUG("pHttpHeadDataBuff未初始化\r\n"); HTTP_POST_GetHost(IpBuff, pHandle->SendDataTelAttr.CentralIndex); //獲取伺服器ip len = sprintf((char *)pHandle->pHttpHeadDataBuff, HTTP_POST_HEAD, POST_API_URL, IpBuff, DataLen); //http請求頭打包 uart_printf("http頭(%dB):%s\r\n",len, (char*)pHandle->pHttpHeadDataBuff); return pHandle->pSendData(pHandle->pHttpHeadDataBuff, len); }
//獲取指定伺服器的IP地址
u8 HTTP_POST_GetHost(char *pIpBuff, u8 ServerIndex)
{
	u16 ip[4];
	
	if(ServerIndex > 3) 
	{
		return sprintf(pIpBuff, "localhost");
	}
	ip[0]=atoi(&g_SYS_Config.ServerIP[ServerIndex][0]);
	ip[1]=atoi(&g_SYS_Config.ServerIP[ServerIndex][4]);
	ip[2]=atoi(&g_SYS_Config.ServerIP[ServerIndex][8]);
	ip[3]=atoi(&g_SYS_Config.ServerIP[ServerIndex][12]);
	
	return sprintf(pIpBuff,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
}

//這裡面控制代碼什麼的,傳送介面什麼的忽略掉,你只要知道打包方式,這個報文長度什麼的非常重要。

/*************************************************************************************************************************
* 函式			:	u16 POST_RealDataPackage(POST_HANDLE *pHandle,  tm *pAcqTime,REAL_DATA *pData, u16 SerialNumber)
* 功能			:	實時資料打包(正文打包)
* 引數			:	pHandle:控制代碼;AcqTime:觀測時間;pData:實時資料指標;SerialNumber:流水號;AlarmStatus:報警定義
* 返回			:	長度
* 依賴			:	無
* 作者			:	[email protected]
* 時間			:	2018-02-04
* 最後修改時間	: 	2018-02-04
* 說明			: 	將報文打包寫入到了pPackDataBuff中,注意:一定要在最後面增加一個換行符,這樣每次傳送資料時伺服器才不會斷開連線
*************************************************************************************************************************/ 
u16 POST_RealDataPackage(POST_HANDLE *pHandle,tm *pAcqTime,REAL_DATA *pData, u16 SerialNumber)
{
	u16 len = 0;
	char *pTextBuff = (char *) pHandle->pPackDataBuff;
	
	
	//報文格式 flag=1&ver=1.00&type=RealData&SERIAL=1&ST=1510260128&UT=2018-02-04 15:24:32&data={"ST":"1510260128","TT":"2018-02-04 18:00:00","Z":1.234,"VT":12.56,"ZT":128}
	//http頭與後面資料分開發送的時候,要先發送一個換行,但是這個換行不算總長度
	len += sprintf(&pTextBuff[len],"\r\n");								//前面增加一個換行-不要弄掉了,掉了會出現各種問題
	len += sprintf(&pTextBuff[len],"flag=%d&",1);						//資料上傳識別符號1
	len += sprintf(&pTextBuff[len],"ver=%s&",POST_VER);					//通訊協議版本,用於後續升級的相容
	len += sprintf(&pTextBuff[len],"type=%s&",POST_REAL_DATA_STRING);	//報文型別:實時資料
	len += sprintf(&pTextBuff[len],"SERIAL=%d&",SerialNumber);			//流水號
	len += sprintf(&pTextBuff[len],"ST=%02X%02X%02X%02X%02X&",pHandle->SendDataTelAttr.TelNumber[0],pHandle->SendDataTelAttr.TelNumber[1],
		pHandle->SendDataTelAttr.TelNumber[2],pHandle->SendDataTelAttr.TelNumber[3],pHandle->SendDataTelAttr.TelNumber[4]);	//站點編號
	len += sprintf(&pTextBuff[len],"UT=%04d-%02d-%02d %02d:%02d:%02d&",timer.w_year, timer.w_month, timer.w_date, timer.hour, timer.min, timer.sec);//發報時間
	
	len += sprintf(&pTextBuff[len],"data={");							//報文正文
	//前面固定為ST 與 TT
	len += sprintf(&pTextBuff[len],"\"ST\":\"%02X%02X%02X%02X%02X\",",pHandle->SendDataTelAttr.TelNumber[0],pHandle->SendDataTelAttr.TelNumber[1],
		pHandle->SendDataTelAttr.TelNumber[2],pHandle->SendDataTelAttr.TelNumber[3],pHandle->SendDataTelAttr.TelNumber[4]);	//站點編號
	len += sprintf(&pTextBuff[len],"\"TT\":\"%04d-%02d-%02d %02d:%02d:%02d\",",pAcqTime->w_year, pAcqTime->w_month, pAcqTime->w_date, pAcqTime->hour, pAcqTime->min, 0);			//採集時間
	//打包所有要素資料
	len += JSON_RealDataPackage(&pTextBuff[len], pData, pAcqTime);		//實時資料打包為JSON(正文打包)

	len += sprintf(&pTextBuff[len],"}");
	
	return len;
}

//上面是正文資料打包,自己根據需要實現json就行。

//下面就是傳送了,先發送請求頭,裡面包含了報文正文的長度,請求頭與報文正文之間有個換行,但是不算總長度,這個非常重要,沒有控制好就會導致傳送完成後伺服器斷開了,或者是不能收到伺服器響應等各種情況

/*************************************************************************************************************************
* 函式			:	POST_COMM_ERROR POST_SendRealDataPackge(POST_HANDLE *pHandle, tm *pAcqTime,REAL_DATA *pData, u16 SerialNumber)
* 功能			:	傳送實時資料
* 引數			:	pHandle:協議棧控制代碼;pConnectData:POST連線結構指標;pAcqTime:發報時間;pData:實時資料指標;SerialNumber:流水號;
* 返回			:	RTU_ERROR
* 依賴			:	無
* 作者			:	[email protected]
* 時間			:	2018-02-01
* 最後修改時間	: 	2018-02-01
* 說明			: 	
*************************************************************************************************************************/ 
POST_COMM_ERROR POST_SendRealDataPackge(POST_HANDLE *pHandle, tm *pAcqTime,REAL_DATA *pData, u16 SerialNumber)
{
	u16 ByteNum = 0;
	u8 retry ;
	int len;
	u16 ReceiveDelay;
	u8 *pRxData;			//注意:接收資料的緩衝區與傳送的一般是共用的,為了節省記憶體
	
	if(SerialNumber == 0)	//需要自動流水號
	{
		SerialNumber = pHandle->SerialNumberAdd(pHandle->SendDataTelAttr.CentralIndex);	//流水號增加	
	}		
	
	for(retry = 0;retry < pHandle->SendRetry; retry ++)										//失敗重試
	{
		ByteNum = POST_RealDataPackage(pHandle, pAcqTime, pData, SerialNumber);				//資料正文打包
		
		if(ByteNum < 2) return POST_COMM_DATA_ERROR;
		
		POST_SendHttpHead(pHandle, ByteNum-2);												//傳送http POST請求頭-資料長度-2,去掉前面的2個換行符
		uart_printf("正文(%dB):%s\r\n",ByteNum, (char*)pHandle->pPackDataBuff);
		OSTimeDlyHMSM(0,0,0,500);															//傳送頭部資訊後延時500毫秒
		pHandle->pSendData(pHandle->pPackDataBuff, ByteNum);								//傳送後續正文資料
		
		//等待接收資料
		len = pHandle->pReadData(&pRxData, 20, pHandle->RxTimeOutMs, &ReceiveDelay);		//接收資料
		if(len < 0)
		{
			uart_printf("[POST ERROR]:伺服器異常的斷開了連線\r\n");
			return POST_COMM_LINGK_ERROR;
		}
		else if(len <= 3)
		{
			uart_printf("[POST ERROR]:等待伺服器返回資料超時\r\n");
			continue;
		}
		else 
		{
			
			pRxData[len] = 0;	//增加結束符
			uart_printf("[POST]:伺服器返回資料(%dms):\r\n%s\r\n", ReceiveDelay, pRxData);
			
			return POST_COMM_OK;
		}
	}
	
	uart_printf("[POST ERROR]:傳送超時\r\n");
	return POST_COMM_TIME_OUT;
}

//東西有點亂,只著重看請求頭打包以及請求頭髮送與正文傳送就行。

伺服器上webapi核心,接收資料後進行判斷,儲存,響應操作
 // POST api/rtu_datainterface
        public HttpResponseMessage Post([FromBody]UploadDataStruct data)
        {
            //資料解析
            try
            {
                if (data.flag != 1 || data.type == null || data.SERIAL == 0 || data.ST == null || data.ST.Length != 10 || data.UT == null)
                {
                    return null;    //資料無效
                }
                if (data.type == "RealData")  //上傳實時資料
                {
                    if (data.data != null)
                        SystemLog.Write(data.ST + " \t" + data.data);

                    //響應資料
                    return new HttpResponseMessage
                    {
                        Content = new StringContent(
                            StaticJson.DefaultResponseJsonStructPack(1, "1510260128", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")),
                            System.Text.Encoding.UTF8, "application/json")
                    };
                }
                else return null;

         
            }
            catch (Exception e)
            {
                return null;
            }

           
        }

//最後收到的資料

2018-03-18 07:57:34 	2018030301 	{"ST":"2018030301","TT":"2018-03-18 08:00:00","Z":3.098,"ZB":3.098,"SBL1":0.000,"SBL2":0.000,"VA":0.000,"VJ":0.000,"PD":0.0,"PJ":0.0,"PT":8.0,"PN01":0.0,"PN05":0.0,"PN10":0.0,"PN30":0.0,"P1":0.0,"DTEMP":15.4,"SIGNAL":40.0,"VT":12.19}
2018-03-18 08:07:37 	2018030301 	{"ST":"2018030301","TT":"2018-03-18 08:05:00","Z":3.098,"ZB":3.098,"SBL1":0.000,"SBL2":0.000,"VA":0.000,"VJ":0.000,"PJ":0.0,"PT":8.0,"PN01":0.0,"PN05":0.0,"DTEMP":15.5,"SIGNAL":62.0,"VT":12.21}
2018-03-18 08:07:39 	2018030301 	{"ST":"2018030301","TT":"2018-03-18 08:10:00","Z":3.099,"ZB":3.099,"SBL1":0.000,"SBL2":0.000,"VA":0.000,"VJ":0.000,"PJ":0.0,"PT":8.0,"PN01":0.0,"PN05":0.0,"PN10":0.0,"DTEMP":15.4,"SIGNAL":62.0,"VT":12.22}
2018-03-18 08:17:34 	2018030301 	{"ST":"2018030301","TT":"2018-03-18 08:15:00","Z":3.098,"ZB":3.098,"SBL1":0.000,"SBL2":0.000,"VA":0.000,"VJ":0.000,"PJ":0.0,"PT":8.0,"PN01":0.0,"PN05":0.0,"DTEMP":15.5,"SIGNAL":43.0,"VT":12.24}

相關推薦

微控制器使用HTTP POST方式傳送資料

HTTP請求是依賴TCP的,也就是在微控制器上面,我們一樣可以使用,無非就是先發送一個http請求頭,再發送正文,比如我最近就使用了http post方式傳送資料到伺服器,伺服器端使用的是WEB API,微控制器使用的STM32 與SIM800C,SIM800C使用GPRS連

Http使用post方式提交資料(使用java標準介面)

本文內容:使用java標準介面,實現http用post方式提交資料。 ------------------------------------------------------------------------------------------------------

Android傳統HTTP請求get----post方式提交資料(包含亂碼問題)

1.模仿登入頁面顯示(使用傳統方式是面向過程的) 使用Apache公司提供的HttpClient  API是面向物件的 (文章底部含有原始碼的連線,包含了使用async框架) (解決中文亂碼的問題,主要是對中文的資料進行URL編碼) android手機預設的編碼是UTF-

java post方式傳遞資料的兩種方式(http https)

採用哪種方式傳遞資料,主要取決於目標地址是否有ssl協議。即字首是http還是https 1.http方式 : 欄位解析: 1.url:表示要傳遞到的目標地址 String型別 2.byte[] parameter :表示要傳遞的資料

HttpClient通過Post方式傳送Json資料

伺服器用的是Springmvc,介面內容: @ResponseBody @RequestMapping(value="/order",method=RequestMethod.POST) public boolean order(HttpServletRequest

Network 【用 AFN 通過 POST 方式傳送JSON資料的兩種形式】

POST 傳送資料有兩種形式:1、傳送純文字的內容 2、傳送的 body 部分帶有檔案(圖片,音訊或者其他二進位制資料) 1、使用 POST 方式傳送純文字內容: [mgr POST:@"https://AAAAA" parameters:params success:^(AFHTTPRequestOpe

httpclient使用post方式傳送json資料,以及服務端的接收

步驟大致如下: 1、客戶端使用StringEntity封裝資料 2、服務端先從request.getInputStream();中獲取資料,再把位元組流轉為字元流 3、最後用response.getWriter().write(param);返回資料給客戶端 4、客戶端

Http使用post方式提交資料(使用apache標準介面)

本文:目的和前一篇一樣,唯一區別是本文用apache標準介面進行http的post提交資料,而前一篇是用 java標準介面實現。 ------------------------------------------------------------------------

nodejs的http.request使用post方式提交資料請求

https://www.cnblogs.com/sunwubin/archive/2013/11/09/3416246.html 直接上程式碼:http_post.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 1

HttpURLConnection 、HttpPost、Okhttp 等POST方式傳送JSON資料

一、HttpURLConnection Post方式傳送JSON資料 public class GetResult extends AsyncTask<String, String, String> { protected void onPreEx

C語言 如何用http post方式 上傳json資料

What :C語言 如何用post方式 上傳json資料. Piont:C語言Socket實現HTTP協議,json格式資料組包。 1,C語言Socket實現HTTP POST+json格式資料 按照HTTP協議傳送request。 http POST

C#帶cookie Post和Get方式傳送資料,保持cookie

在實際程式設計中,可能需要讀取特定網頁的資訊,但很多網站需要使用者登入後,才能夠獲取相關的頁面內容,這就需要程式設計者先臨時儲存當前的cookie,在C#中可以使用CookieContainer 物件來儲存登入後的Cookie資訊,這樣,在每次傳送資料的時候,附加上Cookie資訊,就可以了。       

python通過get方式,post方式傳送http請求和接收http響應-urllib urllib2

測試用CGI,名字為test.py,放在apache的cgi-bin目錄下: #!/usr/bin/python import cgi def main():     print "Content-type: text/html\n"     form = cgi.FieldStorage()     i

Post方式傳送http請求引數

 public boolean uploadPostMethod(String path, Map<String, String> params) throws IOException{ StringBuilder sb = new StringBuilde

C#通過GET/POST方式傳送Http請求

介紹http請求的兩種方式,get和post方式。並用C#語言實現,如何請求url並獲取返回的資料 兩者的區別: 引數 Get請求把提交的資料進行簡單編碼,同時將url的一部分發送到伺服器 比如url:Http://127.0.0.1/login.j

restclient使用get,post方式傳送http請求

火狐瀏覽器新增restclient元件 工具標籤裡面找到新增元件然後安裝restclient元件即可 1.get方式比較簡單 URL具體如下: http://192.168.1.123:8080/wfCloud-service/OrganizeController/byN

Android系列之網路(三)----使用HttpClient傳送HTTP請求(分別通過GET和POST方法傳送資料

 【正文】 在前兩篇文章中,我們學習到了和HTTP相關的基礎知識。文章連結如下: 一、GET和POST的對比: 在漫長的時間當中,其他的方法逐漸的退出了歷史舞臺,最常用的只剩下GET和POST方法。而之前已經講過了通過GET方法獲取資料,今天來學習一下如何分別通過

bootstrapTable post 方式請求資料 (注意POST大小寫)

$('#table').bootstrapTable({ url:'...', method: 'post', queryParams: function (params) { return param;

關於RS485通訊中使用STM32串列埠以DMA方式傳送資料丟失位元組的問題

1、開發平臺 計算機作業系統:WIN7 64位; 開發環境:Keil MDK 5.14; MCU:STM32F407ZET6; STM32F4xx韌體庫:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0; 串列埠除錯助手; 2、問題描述  &

Python以json方式傳送資料

今天在爬一個網站的時候遇到了這個問題,感謝老哥的解決方案 import urllib2 import json data = { 'a': 123, 'b': 456 } headers = {'Content-Type': 'app