1. 程式人生 > >STM32F4加ESP8266完成HTTP的POST方式請求

STM32F4加ESP8266完成HTTP的POST方式請求

    最近開發的一個工程中需要用到雲上傳功能,我是用來上傳音訊到雲端進行識別的,目前開放的語音識別平臺有很多家,科大訊飛、百度語音、阿里雲等,但是這些商家對於安卓應用端和linux嵌入式開發的支援都是不錯的,我的工程暫時用不到linux系統,所以先嚐試用裸板進行音訊上傳識別,百度語音和阿里雲都是支援restful的http請求進行識別的,那麼裸板能夠完成POST請求的就只能加ESP8266了,所以這裡採用這個模組。平臺我這裡用的是百度語音,因為百度的技術文件支援寫的還是比較詳細的,所以研究一段時間也就差不多能夠勉強使用了,但是受限於ESP8266這個模組的傳輸速度,這個識別過程不是很穩定,一旦網路不好很容易失敗,而且這個識別過程很慢很慢。下面記錄一下這個開發過程。

    首先ESP8266這個模組基本上就相當於一個無線網絡卡,既可以作為熱點,也可以通過路由器連線網際網路,用的比較多的是用這個模組與手機進行無線連線然後用手機對程式做一些控制或者進行資訊互動。這次拓展一下,直接用這個模組的STA模式連線網際網路,然後與網際網路進行資料互動。模組與微控制器使用串列埠進行通訊,模組集成了一些命令可以很方便的對其進行控制。其中用到的一些命令會在程式中進行介紹。

    稍微介紹一下百度語音識別的過程,首先必須要有百度賬號,然後到語音識別平臺去註冊一個應用,註冊好之後會提供一個祕鑰,之後會在程式中通過祕鑰去獲取一個token,只有在傳送音訊時加上這個token才能被識別。也就是說我們的識別過程分為兩步,第一步是獲取token,第二步是打包音訊資料上傳,當然其實還有第三步就是將返回的結果(json格式)進行解析,其實返回的token也是需要解析出來的。具體的細節性的內容請參看以下網址http://ai.baidu.com/docs#/ASR-API/top

點選開啟連結

    初始化就不多說了,直接用原子家的初始化就好,然後設定為STA模式,命令是AT+CWMODE=1,這個命令之後需要重啟一下模組,命令是AT+RST。之後第一步要先連線路由器,這裡的命令是AT+CWJAP="wifista_ssid",wifista_password"。接下來設定為單鏈接模式:AT+CIPMUX=0。接下來就要開始進行聯網上傳資料了,第一步是要連線到目標伺服器(這個是獲取token的伺服器):

sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s","openapi.baidu.com","80");
atk_8266_send_cmd(p,"OK",200);

然後設定為透傳模式,也就是說下面這一條命令執行完之後,之後所有用串列埠發出的東西都不再認為是命令,而是直接轉發到剛剛連線到的伺服器上:

atk_8266_send_cmd("AT+CIPMODE=1","OK",200);

之後涉及到的就是如何進行一個POST的請求了,這個稍微上網學一下就行,主要知道格式就成,這裡有一篇不錯的誒帖子可以進行了解:https://www.cnblogs.com/ranyonsue/p/5984001.html點選開啟連結

下面是我的進行POST請求的程式段:

u3_printf("POST https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=xxxxxxxxxxxx&client_secret=xxxxxxxxxxx& HTTP/1.1\r\n");
u3_printf("Host: openapi.baidu.com\r\n");
u3_printf("Content-Length: 0\r\n");
u3_printf("Connection: close\r\n");
u3_printf("\r\n");
u3_printf("0\r\n");

這個命令其實沒有傳送資料,只是要接收資料,但作為一個POST請求後面總覺得應該有點東西,所以我在空行之後直接傳送了一個0字元。然後就可以檢測是否接收到資料了。是否接收到資料同樣直接看串列埠接收標誌是否置位即可。然後最重要的就是一定要記得退出透傳模式再進行其他操作!退出就是串列埠接收到連續的三個+就會退出,但是這個退出在這個程式中有時候會失敗。

之後同樣的操作之後連線到語音上傳的伺服器:

sprintf((char*)p,"AT+CIPSTART=\"TCP\",\"%s\",%s","vop.baidu.com","80"); 
atk_8266_send_cmd(p,"OK",200)

之後進入透傳模式後如下發送語音資料:

u3_printf("POST http://vop.baidu.com/server_api?dev_pid=1537&cuid=C89CDCE7B0F4&token=%s HTTP/1.1\r\n",access_token);
u3_printf("Content-Type: audio/wav;rate=16000\r\n");
u3_printf("Host: vop.baidu.com\r\n");
u3_printf("Content-Length: %lu\r\n",file_byte);
u3_printf("Connection: Keep Alive\r\n");
u3_printf("\r\n");
fillnum=wav_buffill(USART3_TX_BUF,USART3_MAX_SEND_LEN);
第一行都是一些配置引數,在之前發的那個百度的技術文件中有描述,最後在空行之後我是直接將資料分批讀出然後用串列埠傳送出去,我覺得傳送過程伺服器認為傳送完成有兩種可能,一種是上面傳送的資料長度,另外一種是傳送的間隔,間隔超過某一閾值就認為傳送完成,總之無論怎樣,我的這種傳送方式都是可以完成音訊的上傳的。這樣基本就完成了資料的上傳,這個過程中還有一個非常重要的事就是檢測到返回資料後一定要對資料進行解析,返回的資料時json格式的,要把自己需要用的東西分離出來,另外最後識別到的結果是UTF-8格式的,如果要顯示的話注意文字格式轉換的問題。