基於mosquitto的嵌入式平臺MQTT消息推送服務的搭建與使用示例

2020-12-23

關鍵字:


 

這篇文章記錄一下在嵌入式平臺搭建MQTT通信框架的過程。

 

此框架由PC端ubuntu運行MQTT服務端,或者叫“消息中間件”。在windows端運行一個MQTT客戶端,這個客戶端用於下發消息到開發板。另有嵌入式linux開發板端運行着自己編寫的程序,通過調用mosquitto的接口來實現MQTT消息訂閱功能。

 

1、什麼是MQTT和mosquitto

 

MQTT 全稱是 Message Queuing Telemetry Transport,消息隊列遙測傳輸。是一個開源的輕量級消息發佈訂閱協議。是專門爲硬件性能低下及通信環境惡劣情況開發的。一句話:MQTT是非常適用於嵌入式平臺的消息發佈訂閱協議。

 

MQTT只是一種抽象的協議,實現了這套協議的工具有不少,mosquitto就是其中之一。一句話:通過mosquitto,我們可以開發和使用MQTT軟件進行通信。

 

2、嵌入式端環境準備

 

嵌入式系統源碼多種多樣,只能使用源碼自行編譯以生成適用於自己平臺的庫及程序。

 

mosquitto的源碼可以在Github上找到,其鏈接如下:

  https://github.com/eclipse/mosquitto/tags

 

這裏我們以 2.0.0 版本爲例,下載並解壓源碼。

 

在編譯之前必須做些配置修改。

 

首先打開mosquitto源碼根目錄下的 Makefile,第一行即可看到如下聲明:

include config.mk

這表明這個Makefile會從源碼根目錄下的 config.mk 文件中導入一些公共配置文件。事實上,mosquitto 源碼擁有衆多Makefile,每個主要源碼都會導入它,config.mk也是我們要重點配置的對象。

 

接着看Makefile文件,再看第二行語句:

DIRS=lib apps client plugins src

這個表示需要編譯的目錄。在本示例中,我們僅需編譯用於嵌入式平臺的mosquitto動態庫,動態庫的源碼只位於 lib 目錄下,因此,我們可以不編譯其餘目錄,將它們刪去,只保留一個lib目錄,如下所示:

DIRS=lib

事實上,如果我們仍然編譯其它目錄,會遇到很多很讓人頭疼的編譯問題,而這些文件編出來在本示例中又用不上,乾脆就節省些精力不編譯算了。

 

至此,源碼根目錄下的Makefile已經修改完畢了。接下來打開 config.mk 文件。按下圖所示修改配置:

 

 

 

然後在UNAME變量之前指定自己平臺的編譯鏈工具名稱,這裏必須注意的是:不同平臺所用到的編譯工具很有可能不一樣,必須根據自己的實際情況來填寫,筆者這裏僅是作個演示,切不可直接照抄,示例寫法如下圖所示:

 

 

另外,由於mosquitto需要依賴openssl庫的功能,因此可能需要手動指定屬於你的嵌入式平臺的openssl庫的路徑。同樣地,不同平臺其openssl的存放位置不一樣,必須根據自己的實際情況來填寫,筆者這裏僅作個寫法演示,切勿直接照抄,添加openssl庫路徑的寫法如下圖所示:

 

 

然後添加openssl頭文件路徑,如下圖所示:

 

 

然後再將自帶的 openssl 引用 -lssl 與 -lcrypto 刪掉,如下圖所示:

 

至此,嵌入式端的配置就修改完畢了。

 

直接在mosquitto源碼根目錄下 make 編譯,一般來說稍等片刻即可無錯誤結束編譯。此時可以在 lib 目錄與 lib/cpp 目錄分別發現 libmosquitto.so.1 與 libmosquittopp.so.1 動態庫文件的了。我們要用的是 libmosquitto.so.1 動態庫。

 

3、嵌入式端示例程序開發

 

這裏筆者直接提供一份示例源碼,源碼非常簡單,大家直接拿去編譯使用即可。

 

在合適的位置準備一個目錄,要求目錄內的文件如下圖所示:

 

其中 ddemo.c 是筆者下方提供的源碼。 第二個文件即是方纔編譯出來的動態庫文件。最後一個文件是從mosquitto源碼根目錄下的include目錄下拷貝過來的。相關文件內容如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "mosquitto.h"

static void mqtt_connected(struct mosquitto *pstMosq, void *pObject, int iResult, int iFlags, const mosquitto_property *pProperties)
{
    printf("mqtt_connected with:%d\n", iResult);
    mosquitto_subscribe_v5(pstMosq, NULL, "my_mosquitto_topic_20201223", 0, 0, NULL);
    printf("subcribe topic:%s\n", "my_mosquitto_topic_20201223");
}

static void mqtt_disconnected(struct mosquitto *pstMosq, void *pObject, int iReasonCode, const mosquitto_property *pProperties)
{
    printf("mqtt_disconnected with: %d\n", iReasonCode);
    return ;
}

void mqtt_msg(struct mosquitto *msqt, void *pObject, const struct mosquitto_message *msg, const mosquitto_property *pProperties)
{
    printf("Got a message!\n");
    printf("Topic:\n\t%s\n", msg->topic);
    printf("Data length:\n\t%d\n", msg->payloadlen);
    printf("Data:\n\t%s\n\n", (char*)msg->payload);
}

int main()
{
    struct mosquitto* msqt = NULL;
    
    mosquitto_lib_init();
    msqt = mosquitto_new("mosquitto_demo_id", 0, NULL);
    mosquitto_connect_v5_callback_set(msqt, mqtt_connected);
    mosquitto_disconnect_v5_callback_set(msqt, mqtt_disconnected);
    mosquitto_message_v5_callback_set(msqt, mqtt_msg);
    mosquitto_username_pw_set(msqt, "user1", "123456");
    mosquitto_connect_bind_v5(msqt, "192.168.77.30", 1883, 30, NULL, NULL);
    
    mosquitto_loop_forever(msqt, 2000, 1);
    
    mosquitto_destroy(msqt);
    mosquitto_lib_cleanup();

    return 0;
}
ddemo.c源碼

 

CC = msdk-linux-gcc

all: mosquitto_demo
    

mosquitto_demo:ddemo.c
    $(CC) -c -g $^
    $(CC) ddemo.o -I. -L../mosquitto-2.0.0/lib libmosquitto.so.1 -L../../openssl-1.0.2d  -lssl -lcrypto -lpthread -o $@

clean:
    -rm *.o
    -rm mosquitto_demo
Makefile源碼

 

此時便可編譯示例程序了。

 

直接在示例程序源碼根目錄下以 make 命令編譯。一般都能直接編過。如果很不幸,你遇到了如下所示的錯誤:

[demo]$ make
msdk-linux-gcc -c -g ddemo.c
msdk-linux-gcc ddemo.o -I. -L../mosquitto-2.0.0/lib libmosquitto.so.1 -L../../openssl-1.0.2d  -lssl -lcrypto -lpthread -o mosquitto_demo
libmosquitto.so.1: undefined reference to `pthread_setname_np'
collect2: ld returned 1 exit status
make: *** [mosquitto_demo] Error 1

這需要回到 mosquitto 源碼去註釋掉一條語句。

 

打開 mosquitto-2.0.0/lib/thread_mosq.c,將第47行的代碼註釋掉,如下圖所示:

 

重新編譯 mosquitto,將編譯出來的庫拷貝至示例代碼目錄下再次編譯便可通過的了。

 

將mosquitto動態庫與示例程序下載至開發板中。

 

至此,整個嵌入式端的環境均已準備好。

 

4、MQTT服務端搭建

 

MQTT服務端在PC機的ubuntu上搭建。這裏筆者直接參考另一位大神的博文步驟了,原文鏈接如下:

  https://www.cnblogs.com/lulipro/p/10914482.html

 

這裏將關鍵的步驟提取出來,圖省事的同學直接把下面的命令逐一執行一次即可。另,筆者的PC環境爲 ubuntu 14.04.06。

 

sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa     #添加源到軟件倉庫
sudo apt-get update                                         #更新軟件倉庫列表
sudo apt-get install mosquitto                              #安裝mosquitto

 

sudo service mosquitto status                               #查看運行狀態
sudo service mosquitto start                                #啓動服務
sudo service mosquitto stop                                 #停止服務

 

sudo service mosquitto stop   #首先停止服務

#用戶的局部配置文件放在: /etc/mosquitto/conf.d/目錄下,並且這個目錄下的所有以.conf後綴的文件都將被mosquitto作爲配置文件,在啓動時加載。

#在/etc/mosquitto/conf.d目錄下,新建myconfig.conf配置文件

#在其中輸入如下內容
#-------------------------------------------
# 關閉匿名訪問,客戶端必須使用用戶名
allow_anonymous false

#指定 用戶名-密碼 文件
password_file /etc/mosquitto/pwfile.txt
#--------------------------------------------

 

假設用戶名爲:user1
在命令行運行:mosquitto_passwd -c /etc/mosquitto/pwfile.txt user1

回車後連續輸入2次用戶密碼即可

 

sudo service mosquitto start      #啓動服務

 

至此,PC端的MQTT服務端,或者說“消息中間件”環境也已搭建好了。

 

此時,我們還差最後一個角色:用於發佈消息的程序。當然我們可以以前面那位大神文章中提到的直接使用IOS端的 MQTTool 工具。但筆者其實更推薦使用PC端的工具,這裏直接使用 eclipse 出品的windows端MQTT工具了。下載地址如下:

  https://repo.eclipse.org/content/repositories/paho-releases/org/eclipse/paho/org.eclipse.paho.ui.app/1.0.2/

 

這裏我們根據自己的機器下載相應版本軟件,如下圖所示:

 

 

下載解壓後即可直接使用。

 

5、調試

 

至此,所有環境都已經準備好,可以開始聯合調試了。 

 

首先將嵌入式開發板端自己編寫的示例程序運行起來,這裏必須注意,必須要根據自己的實際情況填寫MQTT服務器IP地址。在地址與端口號配置正確的情況下運行示例可以可以發現如下打印信息:

 

 

如果無法正常連接,請檢查:1、網絡環境;2、示例程序中的配置信息;3、MQTT服務端是否正確安裝並配置。

 

其次打開windows端的MQTT工具,首次打開軟件需要點擊克上角的新建連接按鈕,如下圖所示:

 

填寫好信息後連接服務器,並準備消息主題及內容信息,操作步驟如下圖所示:

 

 

在第5步點擊了“發佈”按鈕後,即可立即在開發板端看到如下打印:

 

 

此結果即表示我們的目的已經達成。

 


參考資料:

  https://www.cnblogs.com/lulipro/p/10914482.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章