[鄭文波]
4G cat1 IoT模塊廣泛應用在物聯網行業,如遠程抄表、遠程監控、公網無線對講機等等。
在實際的應用中多采用MCU+IoT模塊的方式來實現數據傳輸,MCU 通過與其連接的傳感器實現數據的采集,然后通過AT 命令控制IoT模塊實現數據端到端或端到云的數據傳輸。
IoT模塊一般都有完整的AT 命令集。MCU 可以通過命令集中的數據傳輸子集,實現數據的傳輸,包括數據的接收和發送。由于數據傳輸子集中的AT 命令多數是異步執行的,這就帶來兩個問題。問題一是MCU 側的控制部分軟件編碼復雜,尤其是對很多應用中MCU 是功能簡單的單片機,程序是單任務的。問題二是無論數據的發送和接收,都是通過AT 命令一條一條的執行,兩個AT 命令之間必須有一定的時間間隔,這樣數據的傳輸的整體效率就不高。
為了克服MCU 數據傳輸部分的編程復雜和數據傳輸的整體效率不高這兩個缺點,同時又要保證IoT模塊的通用性。在保留原有的AT 命令集不變的情況下,增加了數據透傳功能。數據透傳功能可以有效的克服前面提到的兩個缺點,因此,受到無線數據傳輸行業應用開發者的普遍歡迎。
IoT模塊開機后默認是AT 命令模式,在這個模式下MCU 可以通過AT 命令和IoT模塊交互。
通過專用的數據透傳AT 命令AT+VTRANS,MCU可以命令IoT模塊進入數據透傳模式。在數據透傳模式下,模塊將暫時不能接收AT 命令,直到模塊退出數據透傳模式。
數據傳輸分為上行(如圖1 所示)和下行(如圖2 所示),上行指MCU 發送數據給IoT模塊,通過IoT模塊發送到網絡,下行指IoT模塊從網絡側接收數據,然后通過AT uart 口發送給MCU。buffer A 中的數據發送完后,buffer A 和buffer B 可以快速切換,接著把buffer B 中的數據發送到網絡側,同時,如果MCU 有數據發送給IoT 時,就可以緩存到buffer A 中。下行數據傳輸類似。

圖1 上行數據流

圖2 下行數據流
如果某些應用場合,MCU 和IoT 之間數據傳輸的數據特點是:小包、頻繁。那么可以進一步優化buffer的設計,增加buffer的數量,這些buffer 按順序輪換,同時提高了MCU 與IoT模塊之間數據傳輸和IoT模塊與網絡側之間數據傳輸的效率,進而提高了整體的上行數據傳輸效率。如此設計buffer,下行數據傳輸也一樣可以提高效率。
在數據傳輸時,某些情況下會出現吞吐率A 和吞吐率B 嚴重不匹配的情況,比如上行當AT uart 吞吐率持續大于IoT模塊發送到網絡的吞吐率時,即使有buffer 緩存數據,buffer 也存在溢出的風險,數據一旦有溢出,那么就意味著數據中傳輸的過程中發生了部分丟失,即數據傳輸變得不可靠,這在實際應用中是不可接受的。
為了避免由于數據buffer 溢出而導致的數據丟失,必須進行數據流控。當數據buffer 中的數據量達到流控閥值上限時,啟動流控,通知數據發送方暫停數據的發送,直到buffer 中的數據量下降到流控閥值下限。
MCU 和IoT模塊之間通過AT uart 傳輸數據的速率,我們這里姑且稱為吞吐率A,與IoT模塊和網絡之間的數據傳輸速率,我們姑且稱為吞吐率B。理想的結果是吞吐率A 和吞吐率B 在任何情況下都是匹配的。上行發送數據時,MCU 通過AT uart 丟給IoT模塊的數據,IoT模塊馬上通過網絡發送出去。下行接收網絡側的數據是,IoT模塊接收到數據,馬上通過AT uart 丟給MCU。
實際的情況是吞吐率A 和吞吐率B 經常不匹配,導致數據傳輸時出現丟失數據的現場。我們采用增加數據buffer的方式來解決這個問題,即通過適當的數據緩存,來達到減少數據丟失的概率,增加上行和下行數據傳輸的效率。
為了進一步提高數據傳輸的效率,減少因為數據buffer 被占用,而導致數據傳輸效率受影響的情況發生,我們采用了乒乓buffer 來緩存數據。上行傳輸數據時,即使buffer A 中的數據正在上傳到網絡側,那么buffer B還可以用于接收緩存MCU 發送給IoT模塊的數據。當
在數據透傳建立的過程中,可能會由于基站、終端受到干擾等原因,導致數據連接建立的過程中,出現異常。在數據建立連接后,在數據傳輸過程中或者在等待數據傳輸時,連接也可能出現異常,導致SOCKET 關閉,數據連接斷開。
當出現連接異常時,要根據異常的不同情況,采取不同的處理方法,去嘗試恢復連接,目的是維持持續的數據連接。
IP 資源是有限的,運營商為了基于有限的IP 資源,為盡可能多的無線數據終端提供數據服務,會定時清理長時間處于無數據收發狀態(稱為idle 狀態)的終端。
當數據終端處于idle 狀態持續時間超過運營商設定的時間(電信數據服務器的這個時間參數設置為6 分鐘),運營商的數據服務器就會強制釋放連接,并收回終端占用的IP。
有些應用中需要持續的數據連接,那么就要通過發送心跳包的方法,避免終端處于idle 狀態持續時間超過運營商允許的最長時間。
建立數據連接的過程分為兩步,如圖3 所示,第一步是PPP 撥號,第二步是創建SOCKET。

圖3 SOCKET 創建流程
本文所述的IOT模塊PPP撥號對應的AT命令格式為:
參數說明:

示例:AT+CGDATA=”PPP”,1
PPP 撥號成功后,接著需要為數據連接創建SOCKET。SOCKET 用于描述IP 地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。
創建SOCKET 前,需要選擇協議的類型。本文所述的IoT模塊支持TCP/IP UDP 兩種協議。MCU 可以在發給IoT模塊建立數據透傳的AT 命令中通過參數設置在兩種協議中選擇其一。
在IoT模塊和數據接收端之間,建立一個用于數據傳輸的SOCKET,并且維持該SOCKET 持續有效。在端到端或端到云之間建立一個數據傳輸的數據通道。數據通道一旦成功創建,MCU 就可以直接把數據發送給IoT模塊,而不需要每次發送數據前都要發送一堆的AT 命令來判斷網絡狀態和創建數據連接。這樣就實現了數據的透傳功能。
3.2.1 建立過程中的異常
(1)無網絡服務
建立數據透傳之前,先查詢一下終端有沒有注冊到網絡,如果已經注冊到網絡,就繼續查詢一下是否有基站的網絡服務,如果沒有注冊到網絡或者沒有網絡服務,就上報錯誤信息給MCU。MCU 可以一段時間后再重新嘗試連接。
(2)PPP 撥號失敗
出現PPP 撥號失敗時,如果重新嘗試數次后還是不成功,可能的原因有:運營商網絡原因,終端的SIM 卡欠費等。嘗試次數達到了設定的最大次數,就放棄PPP 撥號,同時通過AT uart 口上報給MCU。
(3)SOCKET 無法打開
PPP 撥號成功后,終端會或獲得有效的IP 地址。接著就可以嘗試打開SOCKET。如果打開失敗,可以再嘗試幾次。如果嘗試幾次后還是無法成功打開SOCKET,就要關閉PPP,重新打開PPP,然后再嘗試去打開SOCKET。如果這樣的操作循環嘗試數次后還是無法打開SOCKET,就通過AT uart 口上報給MCU。這種情況最可能的原因是目標服務器有異常。
3.2.2 長連接狀態下的異常
(1)SOCKET 異常關閉
導致SOCKET 異常關閉的常見原因有:目標服務器主動關閉、目標服務器異常、運營商網絡異常、由于信號不好等原因導致的終端接收靈敏度大幅下降等。
SOCKET 異常關閉后,可以重新嘗試打開SOCKET。如果嘗試次數達到最大限制次數,還是無法成功打開SOCKET,就關閉PPP,然后重新嘗試打開PPP 連接和SOCKET。如果嘗試次數達到最大限制次數,還是無法打開SOCKET,就放棄建立連接,把錯誤信息通過AT uart口上報給MCU。
(2)SOCKET 和PPP 同時斷開
如果SOCKET 和PPP 同時斷開,就按照打開PPP,打開SOCKET的順序重新建立連接,前面有闡述,就不再重復。
(3)SOCKET 未斷開,數據始終發送不成功
如果連續發生數次數據發送失敗時,就說明當前的連接出現了問題,這時候就要嘗試斷開當前的連接,然后重新建立數據透傳。為了避免建立的過程中MCU 繼續發送數據給IoT模塊,進而導致因buffer 溢出而丟失數據,IoT模塊發現有數據連續發送失敗時,要把錯誤信息通過AT uart 口上報給MCU,然后再開始嘗試重新建立連接。建立連接成功后,通過AT uart 口上報給MCU,MCU 就可以繼續發送數據給IoT模塊。
為了實現數據透傳功能,設計了一個數據結構體DataMngrT。


數據結構體的解析如表1 所示。

表1 數據結構解析
選相同型號的兩個IoT模塊,一個采用逐條AT 命令的方式,另外一個采用數據透傳的方式,在相同的網絡環境下做數據收發的對比測試,實測數據如表2 所示。

表2 數據收發實測
由實驗測試數據可以看到,在持續收發數據應用場景下,數據透傳模式有明顯的速率優勢。
支持數據透傳模式的IoT 軟件版本發布后,用戶使用一段時間之后,我們收到了用戶很好的反饋。總結一下主要有兩點:一是MCU 側收發數據的編程簡單了;二是收發數據速率明顯提高了。
版本經過一段時間的測試和實際產品使用驗證穩定后,我們在其他型號的IoT模塊中也移植了該功能。此后,數據透傳功能成為我司IoT模塊的標配功能。