6 #include <QLoggingCategory>
14 #define debug() qCDebug(category)
16 static const QLoggingCategory
category(
"MQTTClient");
19 const mosquitto_property*)
25 for (
const auto&
topic : self->config().topics)
27 mosquitto_subscribe(mosq,
nullptr,
topic.c_str(), self->config().qos);
33 nullptr,
"MQTT Client",
34 QString(
"Connection error: %1").
arg(mosquitto_reason_string(result)),
37 self->_connected =
true;
44 if (self->isConnected() && result == MOSQ_ERR_CONN_LOST)
51 const struct mosquitto_message* message,
const mosquitto_property*)
57 void log_callback(
struct mosquitto* mosq,
void* context,
int log_level,
const char*
msg)
59 const std::pair<int, const char*> log_level_map[] = {
60 { MOSQ_LOG_INFO,
"MOSQ_LOG_INFO" },
61 { MOSQ_LOG_NOTICE,
"MOSQ_LOG_NOTICE" },
62 { MOSQ_LOG_WARNING,
"MOSQ_LOG_WARNING" },
63 { MOSQ_LOG_ERR,
"MOSQ_LOG_ERR " },
64 { MOSQ_LOG_DEBUG,
"MOSQ_LOG_DEBUG" },
65 { MOSQ_LOG_SUBSCRIBE,
"MOSQ_LOG_SUBSCRIBE" },
66 { MOSQ_LOG_UNSUBSCRIBE,
"MOSQ_LOG_UNSUBSCRIBE" },
67 { MOSQ_LOG_WEBSOCKETS,
"MOSQ_LOG_WEBSOCKETS" },
71 std::find_if(std::begin(log_level_map), std::end(log_level_map),
72 [log_level](
const auto& pair) {
return log_level == pair.first; });
73 if (it == std::end(log_level_map))
76 debug() << it->second <<
": " <<
msg;
86 int major = 0, minor = 0, revision = 0;
87 mosquitto_lib_version(&major, &minor, &revision);
88 debug() <<
"mosquitto version: " << major <<
"." << minor <<
"." << revision;
98 mosquitto_lib_cleanup();
109 Q_ASSERT(
_mosq ==
nullptr);
110 _mosq = mosquitto_new(
nullptr,
true,
this);
115 mosquitto_destroy(
_mosq);
136 if (rc != MOSQ_ERR_SUCCESS)
138 QMessageBox::warning(
nullptr,
"MQTT Client", QString(
"MQTT initialization failed."),
140 debug() <<
"MQTT initialization failed:" << mosquitto_strerror(rc);
148 if (rc != MOSQ_ERR_SUCCESS)
150 QMessageBox::warning(
nullptr,
"MQTT Client",
151 QString(
"MQTT initialization failed. Double check username "
154 debug() <<
"MQTT username or password error:" << mosquitto_strerror(rc);
164 rc = mosquitto_tls_set(
_mosq, cafile,
nullptr, certfile, keyfile,
nullptr);
165 if (rc != MOSQ_ERR_SUCCESS)
167 QMessageBox::warning(
nullptr,
"MQTT Client",
168 QString(
"MQTT initialization failed. Double check "
171 debug() <<
"MQTT certificate error:" << mosquitto_strerror(rc);
177 if (rc != MOSQ_ERR_SUCCESS)
179 QMessageBox::warning(
nullptr,
"MQTT Client", QString(
"MQTT initialization failed."),
181 debug() <<
"MQTT setting max inflight messages failed:" << mosquitto_strerror(rc);
185 const mosquitto_property* properties =
nullptr;
192 if (rc == MOSQ_ERR_ERRNO)
196 strerror_r(errno, err, 1024);
198 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errno, 0, (LPTSTR)&err, 1024, NULL);
200 QMessageBox::warning(
nullptr,
"MQTT Client", QString(
"Error: %1").
arg(err),
205 QMessageBox::warning(
nullptr,
"MQTT Client",
206 QString(
"Unable to connect (%1)").
arg(mosquitto_strerror(rc)),
209 debug() <<
"MQTT connect failed:" << mosquitto_strerror(rc);
213 rc = mosquitto_loop_start(
_mosq);
214 if (rc == MOSQ_ERR_NOT_SUPPORTED)
218 _thread = std::thread([
this]() {
219 int rc = mosquitto_loop_forever(this->
_mosq, -1, 1);
220 if (rc != MOSQ_ERR_SUCCESS)
222 debug() <<
"MQTT loop forever failed:" << mosquitto_strerror(rc);
226 else if (rc != MOSQ_ERR_SUCCESS)
228 QMessageBox::warning(
nullptr,
"MQTT Client", QString(
"Failed to start MQTT client"),
230 debug() <<
"MQTT start loop failed:" << mosquitto_strerror(rc);
240 mosquitto_disconnect(
_mosq);
241 mosquitto_loop_stop(
_mosq,
true);
246 mosquitto_destroy(
_mosq);
262 std::unique_lock<std::mutex> lk(
_mutex);
268 std::unique_lock<std::mutex> lk(
_mutex);
286 std::unique_lock<std::mutex> lk(
_mutex);
294 mosquitto_subscribe(
_mosq,
nullptr,
topic.c_str(), qos);
302 mosquitto_unsubscribe(
_mosq,
nullptr,
topic.c_str());