統(tǒng)信UOS系統(tǒng)開發(fā)筆記(八):在統(tǒng)信UOS上編譯搭建mqtt基礎(chǔ)環(huán)境(版本使用QMQTT::Cline
前言
??統(tǒng)信uos使用到mqtt開發(fā),需要重新編譯mqtt,本篇描述統(tǒng)信uos20上的mqtt源碼編譯和環(huán)境搭建。
注意
??這里下載的mqtt版本與其他幾篇文章的不同,這里是使用QMQTT::CLIENT來操作的,這里筆者已知Qt的版本分為兩個(gè):一個(gè)是QMQTT::QMQTTCLIENT,一個(gè)是QTMQTT:CLIENT,對(duì)應(yīng)不同的類和方式,請(qǐng)根據(jù)需求選擇)
??

??

相關(guān)博客
??《Mqtt開發(fā)筆記:Mqtt服務(wù)器搭建》
??《Qt開發(fā)技術(shù):mqtt介紹、QtMqtt編譯和開發(fā)環(huán)境搭建]》
??《Mqtt開發(fā)筆記:windows下C++ ActiveMQ客戶端介紹、編譯和使用》
MQTT協(xié)議
簡(jiǎn)介
??MQTT(Message Queuing Telemetry Transport,消息隊(duì)列遙測(cè)傳輸協(xié)議),是一種基于發(fā)布/訂閱(publish/subscribe)模式的"輕量級(jí)"通訊協(xié)議,該協(xié)議構(gòu)建于TCP/IP協(xié)議上,由IBM在1999年發(fā)布。MQTT最大優(yōu)點(diǎn)在于,可以以極少的代碼和有限的帶寬,為連接遠(yuǎn)程設(shè)備提供實(shí)時(shí)可靠的消息服務(wù)。作為一種低開銷、低帶寬占用的即時(shí)通訊協(xié)議,使其在物聯(lián)網(wǎng)、小型設(shè)備、移動(dòng)應(yīng)用等方面有較廣泛的應(yīng)用。
設(shè)計(jì)原則
精簡(jiǎn),不添加可有可無的功能;
發(fā)布/訂閱(Pub/Sub)模式,方便消息在傳感器之間傳遞;
允許用戶動(dòng)態(tài)創(chuàng)建主題,零運(yùn)維成本;
把傳輸量降到最低以提高傳輸效率;
把低帶寬、高延遲、不穩(wěn)定的網(wǎng)絡(luò)等因素考慮在內(nèi);
支持連續(xù)的會(huì)話控制;
理解客戶端計(jì)算能力可能很低;
提供服務(wù)質(zhì)量管理;
假設(shè)數(shù)據(jù)不可知,不強(qiáng)求傳輸數(shù)據(jù)的類型與格式,保持靈活性。
特點(diǎn)
1) 使用發(fā)布/訂閱消息模式,提供一對(duì)多的消息發(fā)布,解除應(yīng)用程序耦合
??這一點(diǎn)很類似于XMPP,但是MQTT的信息冗余遠(yuǎn)小于XMPP,,因?yàn)閄MPP使用XML格式文本來傳遞數(shù)據(jù)。
2) 對(duì)負(fù)載內(nèi)容屏蔽的消息傳輸
3) 使用TCP/IP提供網(wǎng)絡(luò)連接
??主流的MQTT是基于TCP連接進(jìn)行數(shù)據(jù)推送的,但是同樣有基于UDP的版本,叫做MQTT-SN。這兩種版本由于基于不同的連接方式,優(yōu)缺點(diǎn)自然也就各有不同了。
4) 有三種消息發(fā)布服務(wù)質(zhì)量
“至多一次”,消息發(fā)布完全依賴底層TCP/IP網(wǎng)絡(luò)。會(huì)發(fā)生消息丟失或重復(fù)。這一級(jí)別可用于如下情況,環(huán)境傳感器數(shù)據(jù),丟失一次讀記錄無所謂,因?yàn)椴痪煤筮€會(huì)有第二次發(fā)送。這一種方式主要普通APP的推送,倘若你的智能設(shè)備在消息推送時(shí)未聯(lián)網(wǎng),推送過去沒收到,再次聯(lián)網(wǎng)也就收不到了。
“至少一次”,確保消息到達(dá),但消息重復(fù)可能會(huì)發(fā)生。
“只有一次”,確保消息到達(dá)一次。在一些要求比較嚴(yán)格的計(jì)費(fèi)系統(tǒng)中,可以使用此級(jí)別。在計(jì)費(fèi)系統(tǒng)中,消息重復(fù)或丟失會(huì)導(dǎo)致不正確的結(jié)果。這種最高質(zhì)量的消息發(fā)布服務(wù)還可以用于即時(shí)通訊類的APP的推送,確保用戶收到且只會(huì)收到一次。
5) 小型傳輸,開銷小
??(固定長(zhǎng)度的頭部是2字節(jié)),協(xié)議交換最小化,以降低網(wǎng)絡(luò)流量。非常適合"在物聯(lián)網(wǎng)領(lǐng)域,傳感器與服務(wù)器的通信,信息的收集",嵌入式設(shè)備的運(yùn)算能力和帶寬都相對(duì)薄弱,使用這種協(xié)議來傳遞消息再適合不過了。
6) 客戶端異常中斷的機(jī)制。
Last Will:即遺言機(jī)制,用于通知同一主題下的其他設(shè)備發(fā)送遺言的設(shè)備已經(jīng)斷開了連接。
Testament:遺囑機(jī)制,功能類似于Last Will。
發(fā)布/訂閱者模式
??MQTT是一個(gè)基于客戶端-服務(wù)器的消息發(fā)布/訂閱傳輸協(xié)議。MQTT協(xié)議是輕量、簡(jiǎn)單、開放和易于實(shí)現(xiàn)的,這些特點(diǎn)使它適用范圍非常廣泛。在很多情況下,包括受限的環(huán)境中,如:機(jī)器與機(jī)器(M2M)通信和物聯(lián)網(wǎng)(IoT)。其在,通過衛(wèi)星鏈路通信傳感器、偶爾撥號(hào)的醫(yī)療設(shè)備、智能家居、及一些小型化設(shè)備中已廣泛使用。
??

??從圖上MQTT有三種角色的存在:
Broker代理:很多人理解為中間件,當(dāng)然可以這樣子認(rèn)為。他就是一個(gè)中間件。用于處理信息并發(fā)送到相應(yīng)的訂閱者。
發(fā)布者:用于發(fā)布信息到代理上面。注意:發(fā)布者也可以是訂閱者。
訂閱者:就是用于接受信息的客戶端。
MQTT服務(wù)器
??MQTT服務(wù)器以稱為"消息代理"(Broker),可以是一個(gè)應(yīng)用程序或一臺(tái)設(shè)備。它是位于消息發(fā)布者和訂閱者之間,它可以:
接受來自客戶的網(wǎng)絡(luò)連接;
接受客戶發(fā)布的應(yīng)用信息;
處理來自客戶端的訂閱和退訂請(qǐng)求;
向訂閱的客戶轉(zhuǎn)發(fā)應(yīng)用程序消息。
MQTT協(xié)議中的方法
??MQTT協(xié)議中定義了一些方法(也被稱為動(dòng)作),來于表示對(duì)確定資源所進(jìn)行操作。這個(gè)資源可以代表預(yù)先存在的數(shù)據(jù)或動(dòng)態(tài)生成數(shù)據(jù),這取決于服務(wù)器的實(shí)現(xiàn)。通常來說,資源指服務(wù)器上的文件或輸出。主要方法有:
Connect:等待與服務(wù)器建立連接
Disconnect:等待MQTT客戶端完成所作的工作,并于服務(wù)器斷開TCP/IP會(huì)話
Subscribe:等待完成訂閱
UnSubscribe:等待服務(wù)器取消客戶端的一個(gè)活多個(gè)和topics訂閱
Publish:MQTT客戶端發(fā)送消息請(qǐng)求,發(fā)送完成后返回應(yīng)用程序線程
統(tǒng)信UOS系統(tǒng)版本
??系統(tǒng)版本:
??

Qt編譯Mqtt(uos系統(tǒng))
??Qt在5,10版本開始支持mqtt,但是也沒有集成到安裝包里面,需要自己下載編譯。(也使用Qt5.9.3可以運(yùn)行mqtt)
??Qt提供的qtmqtt庫(kù)不支持queue方式(點(diǎn)對(duì)點(diǎn)),只支持訂閱/發(fā)布者模式。
步驟一:下載mqtt,copy解壓至目標(biāo)系統(tǒng)(本步驟廢了)
??下載地址:https://codereview.qt-project.org/admin/repos/qt%2Fqtmqtt,general
??指令:
git clone "https://codereview.qt-project.org/qt/qtmqtt"
???

??(PS:當(dāng)前時(shí)間為2023年6月16日,此時(shí)下下來的qtmqtt已經(jīng)更新為使用CMakeList去配置編譯的版本了,博主同類其他博客的qtmqtt版本是.pro版本的)
??

??這里查看“入坑一”,我們是qt5版本,所以git下載的無用,現(xiàn)在切換到qt的源碼下載,去下載對(duì)應(yīng)版本的mqtt模塊。
步驟二:qt源碼去下載mqtt模塊源碼,解壓至目標(biāo)系統(tǒng)
??這里因?yàn)橐螺d對(duì)應(yīng)版本的qtmqtt,還得挑版本了。
??不好下,github找了個(gè)版本:https://github.com/emqx/qmqtt
??

??這個(gè)既支持pro也支持cmake,下下來,放過去解壓:
??

步驟三:使用QtQCreator打開pro工程編譯
??

??調(diào)整為release,這個(gè)錯(cuò)誤跟我們之前其他版本博客在此處編譯得結(jié)果錯(cuò)誤是一致得,所以下載新的試錯(cuò)了,證明是一樣的。
??

??清空后,單獨(dú)構(gòu)建mqtt庫(kù),也是一樣:
??

??經(jīng)研究,發(fā)現(xiàn)問題是沒有創(chuàng)建文件 Qt5Mqtt。當(dāng)在…/qtmqtt/src/mqtt/.pch路徑上手動(dòng)創(chuàng)建Qt5Mqtt文件時(shí),則解決了。
??

??然后,輕而易舉的就成功了:
??

??然后把debug也編譯了,進(jìn)行模塊化。
部署mqtt模塊到qt
??此處有三種方式,第一種是直接將源碼代入工程,第二種是以模塊的形式直接將其部署到qt的安裝目錄中去,第三種是直接添加庫(kù)和頭文件使用,我們使用將第一種方式,將其添加到Qt安裝庫(kù)的安裝目錄中去,至于第二種方式可以查看《Qt開發(fā)技術(shù):mqtt介紹、QtMqtt編譯和開發(fā)環(huán)境搭建》。
??前面可以編譯成庫(kù),那么代碼就是可以直接融入源碼的:
步驟一:新建mqttClientDemo工程
??

步驟二:提取源碼中的mqtt模塊融入
??提取qtmqtt源碼中的一個(gè),將其當(dāng)作一個(gè)普通的代碼模塊加入新工程的modules,引入其qmqtt.pri文件:
??

步驟三:編譯報(bào)錯(cuò),添加網(wǎng)絡(luò)模塊
??編譯報(bào)錯(cuò)找不到QHostAddress,缺失網(wǎng)絡(luò)模塊模塊,添加網(wǎng)絡(luò)模塊
QT += network
??在提取的源碼的.pri中添加:
??

??然后編譯。
步驟四:編譯報(bào)錯(cuò),函數(shù)定義找不到
??

??查看“入坑二”,因?yàn)橹笆菐?kù),使用了PRIVATE_HEADERS,現(xiàn)在是源碼融入,都換成HEADERS,如下圖:
??

??讓頭文件出來:
??

??繼續(xù)編譯。
步驟五:編譯通過
??

??
源碼融入編譯通過,這樣后續(xù)加入mqtt模塊換系統(tǒng)或者版本就不需要去重新編譯了,比較適合筆者。
步驟六:優(yōu)化下部署模塊
??新建mqttClientManager管理模塊(先用一個(gè)空管理類來占位),用該模塊來包含mqtt源碼。
??

模塊化部署
??

工程模板
??

入坑
入坑一:下載最新的版本不支持qt5,支持qt6
問題
??Git下來的最新的版本不支持qt5,支持qt6
??

原因
??Q6改為cmake編譯了,qt5為qmake,筆者是qt5
解決
??這個(gè)版本mqtt放棄,尋找最后一個(gè)支持qt5的mqtt版本。
入坑二:找不到mqtt頭文件
問題
??源碼都包含了還是找不到
原因
??要將私有頭文件宏改為頭文件宏
解決
??

入坑三:老版本嘗試融入qt5.12.8編譯無法通過
問題和原因
??

解決
??無需解決,指示出問題,請(qǐng)下載對(duì)應(yīng)的版本