Linkit 系列博文:
聯(lián)發(fā)科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉編譯環(huán)境,C語言編譯Hello,World
聯(lián)發(fā)科Linkit 7688 (2)GPIO基本操作與C語言編程
聯(lián)發(fā)科Linkit 7688 DUO(3): 通過 Arduino 控制外設(shè)和傳感器
Linkit 7688 DUO(4): 接上各種Arduino傳感器和模塊——基礎(chǔ)篇
Linkit 7688 DUO(5) 接上各種Arduino傳感器和模塊—擴(kuò)大篇
Linkit 7688 DUO(6) 加入MQTT物聯(lián)網(wǎng)協(xié)議
本篇介紹 將 MQTT物聯(lián)網(wǎng)協(xié)議加載到 Linkit 7688 DUO開發(fā)板上 ( 其中的源碼和方法也適用于所有的Linux系統(tǒng)、也合適于Windows系統(tǒng))
MQTT是IBM開發(fā)的1種物聯(lián)網(wǎng)即時通訊協(xié)議,該協(xié)議支持所有平臺,幾近可以把所有聯(lián)網(wǎng)物品、電腦APP、手機APP、網(wǎng)頁等連接起來,讓它們隨時相互交換信息。
有了MQTT協(xié)議,Linkit 7688開發(fā)板就能夠稱得上物聯(lián)網(wǎng)開發(fā)板了,可以實現(xiàn)很多場景,比如:手機遠(yuǎn)程控制、網(wǎng)頁遠(yuǎn)程控制、服務(wù)器監(jiān)測物體狀態(tài)等等。
1、MQTT協(xié)議簡介
1,MQTT是1種基于TCP的網(wǎng)絡(luò)消息協(xié)議,用于發(fā)送和接收消息。
在1個MQTT網(wǎng)絡(luò)中,有1個服務(wù)器和多個客戶端。 每一個客戶端以TCP Socket與服務(wù)器連接,并保持為長連接。
客戶端可以是1個聯(lián)網(wǎng)物體、電腦軟件、手機APP、乃至是網(wǎng)頁。以下圖:
2, 消息傳輸采取發(fā)布/定閱(publish/subscribe)模式。
客戶端可以發(fā)布(publish)消息, 每一個消息由1個主題(topic)和1個消息內(nèi)容組成。比如:某溫度傳感器發(fā)布1個消息: topic = "sensor1/temperature", message="25“
客戶端可以定閱(subscribe)1個或多個主題的消息。 當(dāng)網(wǎng)絡(luò)中有人發(fā)布了這些主題的消息,則客戶端將收到這條消息。比如: 手機App定閱了 “sensor1/temperature"消息,則上述消息將被收到, 手機App就知道sensor1的溫度值了。
由于客戶端與服務(wù)器保持著Socket長連接,消息將立即實時推送到客戶端,也就是說:PUSH到客戶端。
MQTT服務(wù)器的主要作用是接收-轉(zhuǎn)發(fā):接收消息、判斷哪些客戶端定閱了該主題的消息,PUSH給相應(yīng)客戶端。
這類機制,可以實現(xiàn)1對1發(fā)送消息,也能夠?qū)崿F(xiàn)1對多發(fā)送消息(群發(fā))。
利用場景舉例:
場景1: 手機APP發(fā)布查溫度的消息, 各個傳感器裝置收到消息后,發(fā)布溫度消息。則手機就能夠搜集到各個傳感器的溫度。
場景2: 當(dāng)火警傳感器裝置檢測到起火后,發(fā)布消息。 則定閱了該類型消息的手機、電腦等都可立即收到火警。
3,MQTT的消息包傳輸數(shù)據(jù)量很小(固定長度的頭部僅為 2 字節(jié)),能充分下降網(wǎng)絡(luò)流量,非常合適于低帶寬、不可靠連接、嵌入式裝備。
同時非常合適于手機等移動通訊環(huán)境,可以省流量、省電。因此,有人用MQTT作為手機PUSH使用。
4, 為保障消息有效力到達(dá),MQTT定義了3種消息發(fā)布服務(wù)質(zhì)量(Qos, Quality Of Service):
“最多1次”(At most once),開消最小,消息發(fā)布完全依賴底層 TCP/IP 網(wǎng)絡(luò),會產(chǎn)生消息丟失或重復(fù)。這1級別可用于以下情況,環(huán)境傳感器數(shù)據(jù),丟失1次讀記錄無所謂,由于不久后還會有第2次發(fā)送。
“最少1次”(At least once),確保消息到達(dá),但消息重復(fù)可能會產(chǎn)生。
“只有1次”(Exactly once),確保消息到達(dá)1次。這1級別可用于以下情況,在計費系統(tǒng)中,消息重復(fù)或丟失會致使不正確的結(jié)果。經(jīng)常使用于精確控制。
每條消息都可以有自己的Qos定義。每個客戶端定閱某主題時,也能夠指定Qos.
5, MQTT協(xié)議由IBM公司于1999年提出,經(jīng)過量年發(fā)展已比較成熟,目前版本是3.1.1。服務(wù)器和客戶端均有多個開源實現(xiàn),支持各類操作系統(tǒng)和開發(fā)語言。
2、合適嵌入式裝備的MQTT協(xié)議客戶端(C語言實現(xiàn))
對Linkit 7688開發(fā)板,我選取 “Eclipse Paho C” 的MQTT 客戶端開源代碼庫 。其主頁在這:https://www.eclipse.org/paho/clients/c/
這個代碼庫是IBM公司提供的,Eclipse項目組保護(hù)的,可以稱為官方的。
我的使用方式是: 將它作為1個函數(shù)庫, 在Linkit 7688上編寫C語言程序,實現(xiàn)MQTT消息收發(fā)。
這個庫有1點點復(fù)雜,需要對協(xié)議比較了解。如果你要完全弄懂它,需要先讀它的文檔(http://www.eclipse.org/paho/files/mqttdoc/Cclient/index.html)
我們1般總是喜歡把復(fù)雜的事情簡單化,因此,我對這個庫進(jìn)行了封裝, 變成幾個函數(shù), 不需要懂太多就能夠用.
庫和例程在我的資源中下載: MQTT客戶端Paho C代碼
解壓后,其中mqtt目錄是Paho C所有的庫文件( 原本的文件都沒改,我增加了 mqtt_client.c , mqtt_client.h 兩個文件),使用時將mqtt目錄復(fù)制到你的項目文件夾中便可。
在使用前,需要有1個測試用的MQTT服務(wù)器, 我用的是 IBM提供的測試服務(wù)器: messagesight.demos.ibm.com, 端口是1883 (1883是MQTT的默許端口)
同時需要有1個測試用的MQTT客戶端作為對端,我用的是IBM提供的網(wǎng)頁版MQTT客戶端:http://m2m.demos.ibm.com/mqttclient/
1, 在Linkit 7688上編1個發(fā)送MQTT消息的程序:
用Eclipse 建立1個交叉編譯項目 ( 開發(fā)環(huán)境搭建請見:聯(lián)發(fā)科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉編譯環(huán)境,C語言編譯Hello,World)
將mqtt目錄復(fù)制到你的項目文件夾下。
創(chuàng)建1個 mqtt_publish.c文件, 編寫主程序以下:
主程序分為3個步驟:
1, 調(diào)用 mqtt_new()創(chuàng)建 客戶端對象
2, 調(diào)用 mqtt_connect() 連接服務(wù)器
3, 調(diào)用 mqtt_publish() 發(fā)布消息
用Eclipse編譯項目
如果出現(xiàn)毛病提示:
undefined reference to `pthread_create’
undefined reference to `pthread_mutexattr_init’
這是由于沒有在編譯連接時包括pthread庫, 解決辦法: 需在GCC中添加 -lpthread 參數(shù)。
如果出現(xiàn)毛病提示:
undefined reference to `dlclose’
undefined reference to `dlopen’
undefined reference to `dlsym
這是由于沒有在編譯連接時包括dl庫, 解決辦法: 需在GCC中添加 -ldl 參數(shù)
在eclipse中的操作是: 項目Property => C/C++ Build => Settings, 在"Tools Setting"頁,選Cross GCC linker, 在 "Linker flags"編譯框中填入: -lpthread -ldl
OK, 編譯成功了。
用scp將 mqtt_publish 程序上傳到 linkit 7688: scp mqtt_publish root@mylinkit.local:/root
先準(zhǔn)備接收消息的網(wǎng)頁客戶端: 用閱讀器打開 http://m2m.demos.ibm.com/mqttclient/
在Connect欄中, 點Connect.
在Subscribe欄中,將topic設(shè)為 test_topic, 按subscribe
OK, 網(wǎng)頁客戶端準(zhǔn)備好接收主題(topic)為 test_topic的消息了。
用SSH登錄入Linkit 7688, 運行 mqtt_publish 程序。
運行結(jié)果, 顯示mqtt 創(chuàng)建、連接、發(fā)布消息的進(jìn)程, return code >=0 表示成功:
mqtt client created
mqtt client connect
mqtt client publish, return code = 1
這時候,可以看到閱讀器中的MQTT網(wǎng)頁客戶端收到了Linkit 7688發(fā)布的MQTT消息
成功了: Linkit 7688發(fā)布MQTT消息到服務(wù)器, 網(wǎng)頁客戶端實時收到服務(wù)器推送來的消息。
2, 在Linkit 7688上編1個接收MQTT消息的程序:
用Eclipse 建立1個交叉編譯項目 ( 開發(fā)環(huán)境搭建請見:聯(lián)發(fā)科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉編譯環(huán)境,C語言編譯Hello,World)
將mqtt目錄復(fù)制到你的項目文件夾下。
創(chuàng)建1個 mqtt_subscribe.c文件, 編寫主程序以下:
主程序分為幾個步驟:
1, 調(diào)用 mqtt_new()創(chuàng)建 客戶端對象
2, 調(diào)用 mqtt_connect() 連接服務(wù)器
3, 調(diào)用 mqtt_subscribe() 定閱消息
4, 進(jìn)入循環(huán):不斷用 mqtt_receive()檢測有否新消息,如有,則打印出來。
用Eclipse編譯項目 (記得必須在GCC中加入連接選項: -lpthread -ldl )
OK, 編譯成功了。
用scp將 mqtt_subscribe 程序上傳到 linkit 7688: scp mqtt_subscribe root@mylinkit.local:/root
用SSH登錄入Linkit 7688, 運行 mqtt_subscribe 程序。則此時出現(xiàn):
mqtt client created
mqtt client connect
mqtt client subscribe, return code = 0
wait for message of topic: test_topic ...
顯示程序在等待消息到來
準(zhǔn)備發(fā)送消息的網(wǎng)頁客戶端: 用閱讀器打開 http://m2m.demos.ibm.com/mqttclient/
在Connect欄中, 點Connect.
在Publish欄中,將topic設(shè)為 test_topic, 將Message設(shè)為 “Say hello to linkit 7688” 按publish, 則發(fā)出1條MQTT消息。
這時候, 看Linkit 7688 SSH客戶端,可以看到,Linkit7688立即收到了這條MQTT消息
mqtt client created
mqtt client connect
mqtt client subscribe, return code = 0
wait for message of topic: test_topic ...
received Topic=test_topic, Message=Say hello to linkit 7688
成功了: Linkit 7688 實時收到了網(wǎng)頁客戶端發(fā)來的消息。
mqtt_subscribe 程序是死循環(huán),1直在接收消息。 可按CTRL+C退出。
通用性: Eclipse Paho C 的 MQTT客戶端代碼,可以運行在Linux、Windows、Mac上。所以,上述的代碼可以用于Linux、Windows、Mac操作系統(tǒng),編寫各種App。
對Android手機, Eclipse Paho另提供了Java的代碼庫。
上一篇 Bootstrap UI 編輯器哪家強?推薦以下最好的15款 【快速GUI利器,一般人我不告訴他!】
下一篇 網(wǎng)卡驅(qū)動設(shè)計---架構(gòu)分析加回環(huán)網(wǎng)卡驅(qū)動設(shè)計(網(wǎng)卡驅(qū)動上)