本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
coreMQTT 連線共用示範
重要
這是 FreeRTOS 使用者指南的封存版本,適用於 FreeRTOS 版本 202012.00。如需本文件的最新版本,請參閱 FreeRTOS 使用者指南。
簡介
coreMQTT 連線共用示範專案說明如何使用多執行緒應用程式,使用 TLS 建立與 AWS MQTT 代理程式的連線,並在用戶端和伺服器之間進行相互身分驗證。此示範使用 mbedTLS 型傳輸介面實作來建立伺服器和用戶端驗證的 TLS 連線,並示範 MQTT 在 QoS 1
注意
若要設定和執行 FreeRTOS 示範,請遵循中的步驟FreeRTOS 入門。
此示範使用執行緒安全佇列來保留命令,以與 MQTT API 互動。此示範中需要注意四個任務。
-
命令 (主要) 任務會從命令佇列取得命令並處理它們。其他任務會將命令放置在此佇列中,以進行處理。此任務會進入迴圈,在此期間處理命令。如果收到終止命令,則此任務會中斷迴圈。
-
同步發佈者任務會建立一系列發佈操作,並將其推送至命令佇列。然後,命令任務會執行這些操作。此任務使用同步發佈,這表示此任務會等待每個發佈操作完成,然後再排程下一個發佈操作。
-
非同步發佈者任務會建立一系列發佈操作,並將其推送至命令佇列。然後,命令任務會執行這些操作。此任務和上一個任務之間的差異在於,在排程下一個任務之前,不會等待發佈操作完成。它會在所有發佈操作新增至佇列後檢查每個發佈操作的狀態。請注意,同步和非同步發佈之間的差異僅在這些任務的行為中。實際發佈命令沒有差異。
-
訂閱者任務會建立與兩個發佈者任務發佈之所有訊息主題相符的主題篩選條件的 MQTT 訂閱。此任務進入迴圈,並等待接收其他任務發佈的訊息。
任務可以有佇列來保留收到的訊息。命令任務會將傳入訊息推送到訂閱傳入主題之任何任務的佇列。
此示範使用具有相互身分驗證的 TLS 連線來連線 AWS。如果網路在示範期間意外中斷連線,則用戶端會嘗試使用指數退避邏輯重新連線。如果用戶端成功重新連線,但代理程式無法繼續先前的工作階段,則用戶端會重新訂閱與先前工作階段相同的主題。
單一執行緒與多執行緒
有兩種 coreMQTT 用量模型:單一執行緒和多執行緒 (多任務)。此示範會示範如何建立自己的多執行緒方案。還有另一個多執行緒範例,會在代理程式 (或協助程式) 任務的背景中執行 MQTT 通訊協定。如需詳細資訊,請參閱使用 coreMQTT 的 MWTT 代理程式和示範MQTT_ProcessLoop
函數。此外,如果您使用代理程式任務,多個應用程式任務可以共用單一 MQTT 連線,而不需要同步基本概念,例如 Mutex。
來源碼
示範來源檔案已命名mqtt_demo_connection_sharing.c
,可在
目錄和 GitHubfreertos
/demos/coreMQTT/
功能
此示範總共會建立四個任務:三個請求 MQTT API 呼叫,另一個處理這些請求,這是主要任務。在此示範中,主要任務會進入迴圈,以建立三個子任務、呼叫處理迴圈,並在之後清除。主要任務會建立單一的 MQTT 連線,連接到子任務之間共用的代理程式。其中兩個子任務會將訊息發佈至代理程式,而第三個任務會使用 MQTT 訂閱,將訊息傳回至符合所發佈訊息所有主題的主題篩選條件。
Typedefs
示範會定義下列結構、列舉和函數指標。
- 命令
-
這些任務使用
Command_t
結構來建立命令,指示主要任務為其呼叫適當的 API 操作,而不是直接進行 MQTT API 呼叫。命令具有下列類型:-
PROCESSLOOP
-
PUBLISH
-
SUBSCRIBE
-
UNSUBSCRIBE
-
PING
-
DISCONNECT
-
RECONNECT
-
TERMINATE
TERMINATE
命令沒有對應的 MQTT API 操作。它用於示範,指示主要任務停止處理命令並開始清除操作。由於某些 MQTT 命令需要一些額外資訊,例如發佈或訂閱資訊,例如MQTT_Publish
、MQTT_Subscribe
和MQTT_Unsubscribe
,因此我們會使用CommandContext_t
欄位。這三個命令需要此欄位,其他命令則為選用。由於這些命令需要此內容,因此在命令放入佇列後,請勿變更此值,直到命令完成為止。當命令完成時,可以叫用選用的回呼。在此示範中,我們使用建立任務通知的回呼,通知呼叫任務命令已完成。對於需要確認的 MQTT 操作 (訂閱、取消訂閱和發佈 QoS 大於 0),在收到確認後,命令即視為已完成。否則,一旦傳回對應的 MQTT API 呼叫,命令就會完成。
您可以在
mqtt_demo_connection_sharing.c
檔案中找到下列定義:-
Command_t
結構 -
CommandCallback_t
函數指標
-
- 致謝
-
由於某些 MQTT 操作需要確認,因此它們會使用 AckInfo_t
陣列,其中包含預期確認的封包識別符,以及預期的原始命令,以便叫用其完成回呼。 - 訂閱
-
此示範可以追蹤每個任務的訂閱。若要這樣做,請求訂閱的每個任務都必須提供訊息佇列,以便接收已發佈的訊息 (SubscriptionElement_t
)。多個任務可以訂閱相同的主題篩選條件,因為它們需要使用單獨的回應佇列。 - 收到已發佈的訊息
-
由於任務與主要任務平行執行,因此主要任務必須等待每個訂閱的任務讀取收到的已發佈訊息,會很困難且耗時。因此,收到的每則訊息都會複製到訂閱已發佈訊息主題 (PublishElement_t
) 之任何任務的回應佇列。由於從 MQTT 用戶端收到的發佈封包包含用戶端網路緩衝區的指標,傳入訊息的承載和主題名稱會複製到單獨的緩衝區,再插入回應佇列。如此一來,訂閱的任務仍然可以在 MQTT 用戶端清除其網路緩衝區後讀取收到的資訊。
主要任務
主要應用程式任務 RunCoreMQTTConnectionSharingDemoclean session
旗標集連接到代理程式,然後中斷連線,並與 旗標取消設定重新連線。處理迴圈終止後,它會中斷與代理程式的連線,並再次從進行網路重新連線的時間點開始迴圈。
成功完成示範後,會產生類似下列影像的輸出。

- 命令迴圈
-
命令迴圈 prvCommandLoop
會等待命令放置在命令佇列中,然後呼叫適當的 MQTT API。除了 DISCONNECT
和TERMINATE
之外,所有命令也會MQTT_ProcessLoop
被呼叫。此示範會設定通訊端喚醒回呼,以在通訊端上提供資料時,將PROCESSLOOP
命令新增至佇列。不過,在那時,佇列中可能會有多個命令。為了確保我們在處理其他命令時不會忽略傳入資料,MQTT_ProcessLoop
會在每個命令之後呼叫 進行單一反覆運算。 - 處理命令
-
請參閱 prvProcessCommand
函數。
同步發佈者任務
同步發佈者任務 prvSyncPublishTaskPUBLISH
操作,並等待每個操作完成,然後再排程下一個操作。此示範使用 QoS 1 來發佈訊息,這表示在收到發佈確認封包之前,這些操作不會被視為已完成。
非同步發佈者任務
非同步發佈者任務 prvAsyncPublishTask
訂閱者任務
訂閱者任務 prvSubscribeTaskTERMINATE
操作,以發出結束命令迴圈的主要任務訊號。