153 lines
3.3 KiB
C++
153 lines
3.3 KiB
C++
#include "mqttcontroller.h"
|
|
#include "logger.h"
|
|
|
|
#include <QMetaObject>
|
|
|
|
#include <mosquitto.h>
|
|
|
|
namespace {
|
|
bool g_mqttInitialized = false;
|
|
}
|
|
|
|
MqttController::MqttController(const MqttConfig &configIn, QObject *parent)
|
|
: QObject(parent),
|
|
config(configIn)
|
|
{
|
|
if (!g_mqttInitialized)
|
|
{
|
|
mosquitto_lib_init();
|
|
g_mqttInitialized = true;
|
|
}
|
|
}
|
|
|
|
MqttController::~MqttController()
|
|
{
|
|
if (client)
|
|
{
|
|
mosquitto_disconnect(client);
|
|
mosquitto_loop_stop(client, true);
|
|
mosquitto_destroy(client);
|
|
client = nullptr;
|
|
}
|
|
}
|
|
|
|
void MqttController::start()
|
|
{
|
|
if (!config.enabled)
|
|
{
|
|
Log("MQTT disabled or missing host/topic.");
|
|
return;
|
|
}
|
|
|
|
QString clientId = QString::fromStdString(config.clientId);
|
|
if (clientId.isEmpty())
|
|
clientId = "slide";
|
|
|
|
client = mosquitto_new(clientId.toUtf8().constData(), true, this);
|
|
if (!client)
|
|
{
|
|
Log("MQTT: failed to create client.");
|
|
return;
|
|
}
|
|
|
|
mosquitto_connect_callback_set(client, &MqttController::HandleConnect);
|
|
mosquitto_message_callback_set(client, &MqttController::HandleMessage);
|
|
|
|
if (!config.username.empty())
|
|
{
|
|
mosquitto_username_pw_set(client, config.username.c_str(),
|
|
config.password.empty() ? nullptr : config.password.c_str());
|
|
}
|
|
|
|
mosquitto_reconnect_delay_set(client, 2, 30, true);
|
|
|
|
int rc = mosquitto_connect_async(client, config.host.c_str(), config.port, config.keepAlive);
|
|
if (rc != MOSQ_ERR_SUCCESS)
|
|
{
|
|
Log("MQTT connect failed: ", mosquitto_strerror(rc));
|
|
return;
|
|
}
|
|
|
|
rc = mosquitto_loop_start(client);
|
|
if (rc != MOSQ_ERR_SUCCESS)
|
|
{
|
|
Log("MQTT loop start failed: ", mosquitto_strerror(rc));
|
|
return;
|
|
}
|
|
}
|
|
|
|
void MqttController::HandleConnect(struct mosquitto *mosq, void *userdata, int rc)
|
|
{
|
|
auto *self = static_cast<MqttController *>(userdata);
|
|
if (!self || !mosq)
|
|
return;
|
|
if (rc != 0)
|
|
{
|
|
Log("MQTT connect error: ", mosquitto_strerror(rc));
|
|
return;
|
|
}
|
|
self->connected = true;
|
|
self->subscribe();
|
|
}
|
|
|
|
void MqttController::subscribe()
|
|
{
|
|
if (!client || !connected)
|
|
return;
|
|
int rc = mosquitto_subscribe(client, nullptr, config.topic.c_str(), config.qos);
|
|
if (rc != MOSQ_ERR_SUCCESS)
|
|
{
|
|
Log("MQTT subscribe failed: ", mosquitto_strerror(rc));
|
|
}
|
|
else
|
|
{
|
|
Log("MQTT subscribed to ", config.topic);
|
|
}
|
|
}
|
|
|
|
void MqttController::HandleMessage(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
|
|
{
|
|
Q_UNUSED(mosq);
|
|
auto *self = static_cast<MqttController *>(userdata);
|
|
if (!self || !message || !message->payload)
|
|
return;
|
|
|
|
QString payload = QString::fromUtf8(static_cast<const char *>(message->payload), message->payloadlen);
|
|
QMetaObject::invokeMethod(self, "handleCommand", Qt::QueuedConnection, Q_ARG(QString, payload));
|
|
}
|
|
|
|
void MqttController::handleCommand(const QString &payload)
|
|
{
|
|
QString cmd = payload.trimmed().toLower();
|
|
if (cmd.isEmpty())
|
|
return;
|
|
|
|
if (cmd == "play" || cmd == "resume")
|
|
{
|
|
emit play();
|
|
return;
|
|
}
|
|
if (cmd == "pause")
|
|
{
|
|
emit pause();
|
|
return;
|
|
}
|
|
if (cmd == "next" || cmd == "skip" || cmd == "next-image")
|
|
{
|
|
emit nextImage();
|
|
return;
|
|
}
|
|
if (cmd == "next-folder" || cmd == "folder-next" || cmd == "skip-folder")
|
|
{
|
|
emit nextFolder();
|
|
return;
|
|
}
|
|
if (cmd == "restart" || cmd == "reset")
|
|
{
|
|
emit restart();
|
|
return;
|
|
}
|
|
|
|
Log("MQTT unknown command: ", cmd.toStdString());
|
|
}
|