基于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 ", iResult); mosquitto_subscribe_v5(pstMosq, NULL, "my_mosquitto_topic_20201223", 0, 0, NULL); printf("subcribe topic:%s ", "my_mosquitto_topic_20201223"); } static void mqtt_disconnected(struct mosquitto *pstMosq, void *pObject, int iReasonCode, const mosquitto_property *pProperties) { printf("mqtt_disconnected with: %d ", iReasonCode); return ; } void mqtt_msg(struct mosquitto *msqt, void *pObject, const struct mosquitto_message *msg, const mosquitto_property *pProperties) { printf("Got a message! "); printf("Topic: %s ", msg->topic); printf("Data length: %d ", msg->payloadlen); printf("Data: %s ", (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; }
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