前言
統信uos使用到mqtt開發,需要重新編譯mqtt,本篇描述統信uos20上的mqtt源碼編譯和環境搭建。
這裏下載的mqtt版本與其他幾篇文章的不同,這裏是使用QMQTT::CLIENT來操作的,這裏筆者已知Qt的版本分爲兩個:一個是QMQTT::QMQTTCLIENT,一個是QTMQTT:CLIENT,對應不同的類和方式,請根據需求選擇)
《Mqtt開發筆記:Mqtt服務器搭建》
《Qt開發技術:mqtt介紹、QtMqtt編譯和開發環境搭建]》
《Mqtt開發筆記:windows下C++ ActiveMQ客戶端介紹、編譯和使用》
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發佈/訂閱(publish/subscribe)模式的"輕量級"通訊協議,該協議構建於TCP/IP協議上,由IBM在1999年發佈。MQTT最大優點在於,可以以極少的代碼和有限的帶寬,爲連接遠程設備提供實時可靠的消息服務。作爲一種低開銷、低帶寬佔用的即時通訊協議,使其在物聯網、小型設備、移動應用等方面有較廣泛的應用。
- 精簡,不添加可有可無的功能;
- 發佈/訂閱(Pub/Sub)模式,方便消息在傳感器之間傳遞;
- 允許用戶動態創建主題,零運維成本;
- 把傳輸量降到最低以提高傳輸效率;
- 把低帶寬、高延遲、不穩定的網絡等因素考慮在內;
- 支持連續的會話控制;
- 理解客戶端計算能力可能很低;
- 提供服務質量管理;
- 假設數據不可知,不強求傳輸數據的類型與格式,保持靈活性。
這一點很類似於XMPP,但是MQTT的信息冗餘遠小於XMPP,,因爲XMPP使用XML格式文本來傳遞數據。
主流的MQTT是基於TCP連接進行數據推送的,但是同樣有基於UDP的版本,叫做MQTT-SN。這兩種版本由於基於不同的連接方式,優缺點自然也就各有不同了。
- “至多一次”,消息發佈完全依賴底層TCP/IP網絡。會發生消息丟失或重複。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因爲不久後還會有第二次發送。這一種方式主要普通APP的推送,倘若你的智能設備在消息推送時未聯網,推送過去沒收到,再次聯網也就收不到了。
- “至少一次”,確保消息到達,但消息重複可能會發生。
- “只有一次”,確保消息到達一次。在一些要求比較嚴格的計費系統中,可以使用此級別。在計費系統中,消息重複或丟失會導致不正確的結果。這種最高質量的消息發佈服務還可以用於即時通訊類的APP的推送,確保用戶收到且只會收到一次。
(固定長度的頭部是2字節),協議交換最小化,以降低網絡流量。非常適合"在物聯網領域,傳感器與服務器的通信,信息的收集",嵌入式設備的運算能力和帶寬都相對薄弱,使用這種協議來傳遞消息再適合不過了。
- Last Will:即遺言機制,用於通知同一主題下的其他設備發送遺言的設備已經斷開了連接。
- Testament:遺囑機制,功能類似於Last Will。
MQTT是一個基於客戶端-服務器的消息發佈/訂閱傳輸協議。MQTT協議是輕量、簡單、開放和易於實現的,這些特點使它適用範圍非常廣泛。在很多情況下,包括受限的環境中,如:機器與機器(M2M)通信和物聯網(IoT)。其在,通過衛星鏈路通信傳感器、偶爾撥號的醫療設備、智能家居、及一些小型化設備中已廣泛使用。
從圖上MQTT有三種角色的存在:
- Broker代理:很多人理解爲中間件,當然可以這樣子認爲。他就是一箇中間件。用於處理信息併發送到相應的訂閱者。
- 發佈者:用於發佈信息到代理上面。注意:發佈者也可以是訂閱者。
- 訂閱者:就是用於接受信息的客戶端。
MQTT服務器以稱爲"消息代理"(Broker),可以是一個應用程序或一臺設備。它是位於消息發佈者和訂閱者之間,它可以:
- 接受來自客戶的網絡連接;
- 接受客戶發佈的應用信息;
- 處理來自客戶端的訂閱和退訂請求;
- 向訂閱的客戶轉發應用程序消息。
MQTT協議中定義了一些方法(也被稱爲動作),來於表示對確定資源所進行操作。這個資源可以代表預先存在的數據或動態生成數據,這取決於服務器的實現。通常來說,資源指服務器上的文件或輸出。主要方法有:
- Connect:等待與服務器建立連接
- Disconnect:等待MQTT客戶端完成所作的工作,並於服務器斷開TCP/IP會話
- Subscribe:等待完成訂閱
- UnSubscribe:等待服務器取消客戶端的一個活多個和topics訂閱
- Publish:MQTT客戶端發送消息請求,發送完成後返回應用程序線程
系統版本:
Qt在5,10版本開始支持mqtt,但是也沒有集成到安裝包裏面,需要自己下載編譯。(也使用Qt5.9.3可以運行mqtt)
Qt提供的qtmqtt庫不支持queue方式(點對點),只支持訂閱/發佈者模式。
git clone "https://codereview.qt-project.org/qt/qtmqtt"
(PS:當前時間爲2023年6月16日,此時下下來的qtmqtt已經更新爲使用CMakeList去配置編譯的版本了,博主同類其他博客的qtmqtt版本是.pro版本的)
這裏查看“入坑一”,我們是qt5版本,所以git下載的無用,現在切換到qt的源碼下載,去下載對應版本的mqtt模塊。
這裏因爲要下載對應版本的qtmqtt,還得挑版本了。
不好下,github找了個版本:https://github.com/emqx/qmqtt
這個既支持pro也支持cmake,下下來,放過去解壓:
調整爲release,這個錯誤跟我們之前其他版本博客在此處編譯得結果錯誤是一致得,所以下載新的試錯了,證明是一樣的。
清空後,單獨構建mqtt庫,也是一樣:
經研究,發現問題是沒有創建文件 Qt5Mqtt。當在…/qtmqtt/src/mqtt/.pch路徑上手動創建Qt5Mqtt文件時,則解決了。
然後,輕而易舉的就成功了:
然後把debug也編譯了,進行模塊化。
此處有三種方式,第一種是直接將源碼代入工程,第二種是以模塊的形式直接將其部署到qt的安裝目錄中去,第三種是直接添加庫和頭文件使用,我們使用將第一種方式,將其添加到Qt安裝庫的安裝目錄中去,至於第二種方式可以查看《Qt開發技術:mqtt介紹、QtMqtt編譯和開發環境搭建》。
前面可以編譯成庫,那麼代碼就是可以直接融入源碼的:
提取qtmqtt源碼中的一個,將其當作一個普通的代碼模塊加入新工程的modules,引入其qmqtt.pri文件:
編譯報錯找不到QHostAddress,缺失網絡模塊模塊,添加網絡模塊
QT += network
在提取的源碼的.pri中添加:
然後編譯。
查看“入坑二”,因爲之前是庫,使用了PRIVATE_HEADERS,現在是源碼融入,都換成HEADERS,如下圖:
讓頭文件出來:
繼續編譯。
源碼融入編譯通過,這樣後續加入mqtt模塊換系統或者版本就不需要去重新編譯了,比較適合筆者。
新建mqttClientManager管理模塊(先用一個空管理類來佔位),用該模塊來包含mqtt源碼。
Git下來的最新的版本不支持qt5,支持qt6
Q6改爲cmake編譯了,qt5爲qmake,筆者是qt5
這個版本mqtt放棄,尋找最後一個支持qt5的mqtt版本。
源碼都包含了還是找不到
要將私有頭文件宏改爲頭文件宏
無需解決,指示出問題,請下載對應的版本