前言
最近在用正点原子的imx6ull板子做个小项目,用到了lvgl做gui和mqtt做物联网通信。打算先在window平台下写好lvgl界面以及mqtt相关的代码,再移植到imx6ull上。移植lvgl库和mqtt库到imx6ull上,网上都能查到。lvgl在window下的仿真运行,看正点原子的lvgl教程也有提供。
故记录一下把mqtt库在window平台下的编译,然后用Visual Studio运行测试程序。
最后再在codeblocks下运行测试。
正文
下载cmake
cmake官网下载地址 https://cmake.org/download
安装过程一路next,这里注意一下选上把CMake添加到系统环境变量
克隆paho mqtt c
到https://github.com/eclipse/paho.mqtt.c克隆仓库
解压上面clone下来的代码,在根路径新建build文件夹,如下图
打开cmake gui软件,设好项目代码目录,build文件夹目录。点击 Configure
选择自己的Visual Studio版本,点击 Finish
CMAKE_INSTALL_PREFIX
变量存放的是库安装路径,我这里直接用默认的。点击Generate,下面显示Generating done
搜索,以管理员身份打开cmd
先将路径更改到mqtt库代码的路径。我这里是放在下面图片的目录
cd 路径
执行命令
cmake --build build --target install
如出现如下提示,说cmake install错误,是因为没有用管理员身份运行命令,无法创建目录C:/Program Files (x86)/Eclipse Paho
管理员身份打开cmd,切换到代码路径,运行cmake --build build --target install
编译完成,去C:\Program Files (x86)\Eclipse Paho C
能看到4个文件夹,bin文件夹存放着.dll文件,include文件夹是.h头文件,lib文件夹存放.lib文件
下面开始编写实验代码,新建一个vs工程
vs2022 项目设置
由于我在编译时cmake的CMAKE_INSTALL_PREFIX
变量用的默认设置,在路径C:\Program Files (x86)\Eclipse Paho C
,下面有关依赖的路径都基于这个路径。
.h头文件,.lib库文件目录
依赖的.lib
关联.dll目录
main.c 代码
代码基于正点原子imx6ull教程里面的mqtt示例
正点原子阿尔法Linux开发板(A盘)-> 09、文档教程 -> 【正点原子】I.MX6U嵌入式Linux C应用编程指南V1.4.pdf
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "MQTTClient.h" //包含MQTT客户端库头文件
#include <Windows.h>
/* ########################宏定义##################### */
#define BROKER_ADDRESS "tcp://iot.ranye-iot.net:1883" //然也物联平台社区版MQTT服务器地址
/* 客户端id、用户名、密码 *
* 当您成功申请到然也物联平台的社区版MQTT服务后
* 然也物联工作人员会给你发送8组用于连接社区版MQTT服务器
* 的客户端连接认证信息:也就是客户端id、用户名和密码
* 注意一共有8组,您选择其中一组覆盖下面的示例值
* 后续我们使用MQTT.fx或MQTTool的时候 也需要使用一组连接认证信息
* 去连接社区版MQTT服务器!
* 由于这是属于个人隐私 笔者不可能将自己的信息写到下面 */
#define CLIENTID "alientek" // 客户端id
#define USERNAME "" // 用户名
#define PASSWORD "" // 密码
/* 主题定义 */
#define WILL_TOPIC "win/will" // 遗嘱主题
#define SUB_TOPIC "win/msg" // esp32信息主题
int i = 0;
static int msgarrvd(void* context, char* topicName, int topicLen, MQTTClient_message* message)
{
printf("[MQTT msg]:%s: %s\n", topicName, message->payload);
/* 释放占用的内存空间 */
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
/* 连接服务器错误回调函数 */
static void connlost(void* context, char* cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
}
int main(int argc, char* argv[])
{
/****** MQTT ************/
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
int mqtt_rc;
/* 创建mqtt客户端对象 */
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_create(&client, BROKER_ADDRESS, CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL)))
{
printf("Failed to create client, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto exit;
}
/* 设置回调 */
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_setCallbacks(client, NULL, connlost,
msgarrvd, NULL)))
{
printf("Failed to set callbacks, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto destroy_exit;
}
/* 连接MQTT服务器 */
will_opts.topicName = WILL_TOPIC; // 遗嘱主题
will_opts.message = "offline"; // 遗嘱消息
will_opts.retained = 1; // 保留消息
will_opts.qos = 0; // QoS0
conn_opts.will = &will_opts;
conn_opts.keepAliveInterval = 30; // 心跳包间隔时间
conn_opts.cleansession = 0; // cleanSession标志
conn_opts.username = USERNAME; // 用户名
conn_opts.password = PASSWORD; // 密码
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_connect(client, &conn_opts)))
{
printf("Failed to connect, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto destroy_exit;
}
printf("MQTT服务器连接成功!\n");
/* 发布上线消息 */
pubmsg.payload = "online"; // 消息的内容
pubmsg.payloadlen = 6; // 内容的长度
pubmsg.qos = 0; // QoS等级
pubmsg.retained = 1; // 保留消息
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_publishMessage(client, WILL_TOPIC, &pubmsg, NULL)))
{
printf("Failed to publish message, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto disconnect_exit;
}
/* 订阅主题 win/msg */
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_subscribe(client, SUB_TOPIC, 0)))
{
printf("Failed to subscribe, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto disconnect_exit;
}
/* 向服务端发布信息 */
for (;;)
{
MQTTClient_message tempmsg = MQTTClient_message_initializer;
char temp_str[10] = { 0 };
sprintf(temp_str, "%d", i);
/* 发布累加变量信息 */
tempmsg.payload = temp_str; // 消息的内容
tempmsg.payloadlen = strlen(temp_str); // 内容的长度
tempmsg.qos = 0; // QoS等级
tempmsg.retained = 1; // 保留消息
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_publishMessage(client, "win/tmp", &tempmsg, NULL)))
{
printf("Failed to publish message, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
goto unsubscribe_exit;
}
Sleep(3000); // 每隔30秒 更新一次数据
i++;
}
unsubscribe_exit:
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_unsubscribe(client, SUB_TOPIC)))
{
printf("Failed to unsubscribe, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
}
disconnect_exit:
if (MQTTCLIENT_SUCCESS !=
(mqtt_rc = MQTTClient_disconnect(client, 10000)))
{
printf("Failed to disconnect, return code %d\n", mqtt_rc);
mqtt_rc = EXIT_FAILURE;
}
destroy_exit:
MQTTClient_destroy(&client);
exit:
return mqtt_rc;
}
上面代码需要自己设置一下宏定义里面BROKER_ADDRESS
服务器ip地址和端口, USERNAME
用户名
,PASSWORD
密码。
测试效果
我这里使用MQTT Explorer软件,来查看程序发布的信息以及向程序发送消息。
代码会向遗嘱主题win/will
,发送online或者offline,连接上MQTT服务器,MQTT Explorer就会看到主题win/will
下显示online,程序退出或者掉线,win/will
主题就会显示offline;
程序每隔3秒就会往win/tmp
发送一个由0自加1的整数;
程序订阅了win/msg
主题,用MQTT Explorer往这个主题发信息,程序就会收到,并打印在命令行。
codeblocks运行
我的clodeblocks版本为20.03
新建一个项目,在Project --> Build options.. --> Search directories
配置
头文件路径
.dll路径和.lib路径
.lib路径
编译运行效果与在Visual Studio中运行一致。
参考链接
How to build paho mqtt c++ on windows - Stack Overflow
关于CMake(cmake-gui)的使用及注意事项,超详细!
codeblocks由于找不到zxing_dll.dll,无法继续执行代码
CodeBlocks导入第三方库的详细简单过程
codeblocks 使用第三方库