STM32通過SIM800L向yeelink端上傳資料
忙了一個多月,終於完成了一套系統的開發,筆者參與完成了SIM800L向yeelink端上傳資料,以及Andriod客戶端的開發,視訊製作等。裝置演示視訊地址
為:
http://v.youku.com/v_show/id_XMTI2NTM5OTA2NA==.html
另外我們還做了一套更小的板子,因為外觀設計等問題,需要等待。好了,廢話不多說,來說一說SIM800L上傳資料到yeelink中的一些問題,和解決辦法,Andriod
客戶端的,技術含量不是很高,就不再提及。
這裡我們是通過TCP/IP的方式模擬HTTP進行傳送的json格式資料,對傳送HTTP要有所瞭解,不瞭解的可以windows下,IE 裡裝個httpwatch,Linux直接用wireshark,跟蹤一下
就能大致瞭解了。
這裡就以傳送柺杖跌倒標誌位來講述:
const char yeelink1[]="POST /v1.0/device/xxxxx/sensor/xxxxx/datapoint HTTP/1.1\r\n";
const char yeelink2[]="Host: api.yeelink.net\r\n";
const char yeelink3[]="Accept: */*\r\n";
const char yeelink4[]="U-ApiKey:d0fdba9069356c7dc282df3515xxxxxx\r\n";
const char yeelink5[]="Content-Length:13\r\n";
const char yeelink6[]="Content-Type: application/x-www-form-urlencoded\r\n";
const char yeelink7[]="Connection: close\r\n\r\n";
char yeelink8[]="{\"value\":0}\r\n";
const char yeelink9[]="\r\n";
const char yeelink10[]="\x1A\r\n";
這些就是我們要POST的內容(xxx就不公佈了)。
要上傳這些資料到yeelink,我們首先當然是控制SIM800L上網,GSM聯網我們需要:開啟任務,啟用場景等,依次我們用
AT+CSTT
AT+CIICR
AT+CIFSR
AT+CIPSTART="TCP","42.96.164.52","80"
AT+CIPSEND
然後就可以傳送資料了,這些操作倒是沒有什麼,很正常,在上位機除錯也沒有什麼問題,可放到STM32上面,問題來了
(不是挖掘機技術哪家強的問題),有時候資料傳送成功,有時候傳送失敗,還有時候呢不僅僅沒有成功,反而在執行完
指令時,進行AT+CIPSHUT關閉也不成功。首先和大家想到的一樣,那就是延遲的問題,沒錯,確實是延遲的問題,我們
確定一組延遲以後,是可以進行傳送的,可訊號不好的時候又出現傳送不一定成功的時候,而且還會伴隨上面的問題,怎樣
做呢,剛開始是試著去尋找一組都可以用的延遲,自然是越久越穩定,可啟用場景這一步,手冊上說最大達到85s,
這個問題考慮了很久,決定放棄這種方法,決定曲線救國吧,這裡先說明一點,這裡在STM32上除錯GSM是有回顯的
我們怎樣判斷每次輸入的指令成功執行了呢?
第一,先確定輸入指令GSM有應答訊號
這裡採取的方法是迴圈等待,直到連線GSM的串列埠有應答資訊,有的需要一次,有的需要兩次迴圈等待,看具體指令。
試驗中發現,串列埠有時連續傳送兩次,中間有短暫間隔。這裡我們借用微控制器按鍵去抖的經驗,短暫延時後再次判斷
串列埠中資料長度是否變化來解決。
看到有的人是判斷GSM執行指令後,串列埠緩衝區裡面回顯的是否正確來判斷命令是否成功。這裡我不推薦,因為事實上,
比如你的GSM如果已經處於IP GPRSACT狀態了,你再執行AT+CIICR返回錯誤,你卻可以進行下一步的操作。
這裡推薦的方法是執行命令前,先查詢IP所處的狀態,使用命令為:AT+CIPSTATUS,這樣可以在任意狀態下進行。
這裡貼出部分程式碼,這裡沒有使用結構體偏移,源於對STM32編譯器不瞭解,程式粗糙了點
void open_ip(void)
{
u8 flag=1;
while(flag)
{
if(getipstatus("TCP CONNECTING")||getipstatus("IP CONFIG"))
{
delay_ms(1000);
}else
if(getipstatus("CONNECT OK"))
{
flag=0;
}else
if(getipstatus("TCP CLOSED"))
{
usart3_send_str(atcipshut);
wait_for_answer();
wait_for_answer();
}else
if(getipstatus("IP STATUS"))
{
usart3_send_str(atcipstart);
wait_for_answer();
}else
if(getipstatus("IP GPRSACT"))
{
usart3_send_str(atcifsr);
wait_for_answer();
}else
if(getipstatus("IP START"))
{
usart3_send_str(atciicr);
wait_for_answer();
wait_for_answer();
}else
if(getipstatus("IP INITIAL"))
{
usart3_send_str(atcstt);
wait_for_answer();
}
else{
usart3_send_str(atcipshut);
wait_for_answer();
}
}
}
筆者實驗發現,都很成功