C/C++
本文主要介绍如何在 C 项目中使用 Eclipse Paho C ,实现 ST200TH 设备与 MQTT 服务器的连接、订阅、收发消息等功能。 Eclipse Paho C (opens in a new tab) 与 Eclipse Paho Embedded C 均为 Eclipse Paho 项目下的 C 语言客户端库(MQTT C Client),均为使用 ANSI C 编写的功能齐全的 MQTT 客户端。
前提条件
安装依赖包
sudo apt-get update
sudo apt-get -y install build-essential git cmake openssl libssl-dev
编译 Paho MQTT 库
Linux/Mac
git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c
make
sudo make install
Windows
mkdir build.paho
cd build.paho
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cmake -G "NMake Makefiles" -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=FALSE -DPAHO_BUILD_SAMPLES=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=TRUE ..
nmake
连接使用
连接设置
本文将使用自定义的接入认证方式,服务器接入信息如下:
- Broker: mqtt.geek-smart.cn
- TCP Port: 1883
- WebSocket Port: 8083
导入依赖包
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "MQTTClient.h"
定义连接地址、认证信息以及消息发布主题
#define ADDRESS "tcp://mqtt.geek-smart.cn:1883"
#define USERNAME "************" // 用户名
#define PASSWORD "************" // 密码
#define CLIENTID "c-client"
#define QOS 0
#define SUB_TOPIC "/HYUGHV/lVtAcHuor***/4cebd60bf***/subscribe" // 订阅主题
#define PUB_TOPIC "/HYUGHV/lVtAcHuor***/4cebd60bf***/publish" // 发布主题
#define TIMEOUT 10000L
定义消息发布函数
void publish(MQTTClient client, char *topic, char *payload) {
MQTTClient_message message = MQTTClient_message_initializer;
message.payload = payload;
message.payloadlen = strlen(payload);
message.qos = QOS;
message.retained = 0;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage(client, topic, &message, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Send `%s` to topic `%s` \n", payload, PUB_TOPIC);
}
定义 on_message 回调函数,用于打印订阅主题接收的消息内容
int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
char *payload = message->payload;
printf("Received `%s` from `%s` topic \n", payload, topicName);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
初始化 MQTT 客户端并订阅主题
int rc;
MQTTClient client;
MQTTClient_create(&client, ADDRESS, CLIENTID, 0, NULL);
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect, return code %d\n", rc);
exit(-1);
} else {
printf("Connected to MQTT Broker!\n");
}
// subscribe topic
MQTTClient_subscribe(client, SUB_TOPIC, QOS);
循环调用 publish 函数,完成消息发布
char payload[64];
for (int i = 0; i < 100; i += 1) {
// 获取设备基本信息 每隔两秒获取一次
snprintf(payload, 64, "\{\"type\":\"info\"\}");
publish(client, PUB_TOPIC, payload);
sleep(2);
}
完整代码
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "MQTTClient.h"
#define ADDRESS "tcp://mqtt.geek-smart.cn:1883"
#define USERNAME "************" // username
#define PASSWORD "************" // password
#define CLIENTID "c-client"
#define QOS 0
#define SUB_TOPIC "/HYUGHV/lVtAcHuor***/4cebd60bf***/subscribe" // subscribe
#define PUB_TOPIC "/HYUGHV/lVtAcHuor***/4cebd60bf***/publish" // publish
#define TIMEOUT 10000L
void publish(MQTTClient client, char *topic, char *payload) {
MQTTClient_message message = MQTTClient_message_initializer;
message.payload = payload;
message.payloadlen = strlen(payload);
message.qos = QOS;
message.retained = 0;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage(client, topic, &message, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Send `%s` to topic `%s` \n", payload, PUB_TOPIC);
}
int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
char *payload = message->payload;
printf("Received `%s` from `%s` topic \n", payload, topicName);
MQTTClient_freeMessage(&message);
MQTTClient_free(topicName);
return 1;
}
int main(int argc, char *argv[]) {
int rc;
MQTTClient client;
MQTTClient_create(&client, ADDRESS, CLIENTID, 0, NULL);
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect, return code %d\n", rc);
exit(-1);
} else {
printf("Connected to MQTT Broker!\n");
}
// 订阅获取到的内容
MQTTClient_subscribe(client, SUB_TOPIC, QOS);
char payload[64];
for (int i = 0; i < 100; i += 1) {
// 获取设备基本信息 每隔两秒获取一次
snprintf(payload, 64, "\{\"type\":\"info\"\}");
publish(client, PUB_TOPIC, payload);
sleep(2);
}
MQTTClient_disconnect(client, TIMEOUT);
MQTTClient_destroy(&client);
return rc;
}
测试验证
编写 CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(mqtt_c C)
include_directories(/usr/local/include)
link_directories(/usr/local/lib)
set(CMAKE_C_STANDARD 99)
add_executable(mqtt_c main.c)
target_link_libraries(mqtt_c paho-mqtt3c)
编译
cmake .
make
运行
./mqtt_c