/* **************************************************************************** * Copyright 2019 Open Systems Development BV * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the "Software"), * * to deal in the Software without restriction, including without limitation * * the rights to use, copy, modify, merge, publish, distribute, sublicense, * * and/or sell copies of the Software, and to permit persons to whom the * * Software is furnished to do so, subject to the following conditions: * * * * The above copyright notice and this permission notice shall be included in * * all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * * DEALINGS IN THE SOFTWARE. * * ***************************************************************************/ // osdev::components #include "qmqtt_pubsubclient.h" #include "log.h" // Qt #include using namespace osdev::components; QMqttPubSubClient::QMqttPubSubClient(const QHostAddress& host, const quint16 port, QObject *parent) : QMQTT::Client(host, port, parent) , m_mqtt_topic() , m_current_state(mqtt::E_CLIENT_UNKNOWN) , m_subTemp() , m_pubTemp() { this->connectSignalsAndSlots(); this->connectToHost(); } QMqttPubSubClient::~QMqttPubSubClient() { } void QMqttPubSubClient::subscribe(const QString& message_topic) { if(m_current_state == mqtt::E_CLIENT_CONNECTED) { QMQTT::Client::subscribe(message_topic); } else { m_subTemp.first = message_topic; m_subTemp.second = QString(); } } void QMqttPubSubClient::unsubscribe(const QString& message_topic) { if(m_current_state == mqtt::E_CLIENT_SUBSCRIBED) { QMQTT::Client::unsubscribe( message_topic ); } } void QMqttPubSubClient::publish(const QString& message_topic, const QString& message_payload) { if(m_current_state == mqtt::E_CLIENT_CONNECTED || m_current_state == mqtt::E_CLIENT_SUBSCRIBED || m_current_state == mqtt::E_CLIENT_PUBLISHED) { QMQTT::Message oMessage( QRandomGenerator::global()->generate(), message_topic, QByteArray(message_payload.toStdString().c_str()), 0, true, false ); QMQTT::Client::publish(oMessage); } else { m_pubTemp.first = message_topic; m_pubTemp.second = message_payload; } } void QMqttPubSubClient::slotOnConnected() { // Ok. We're connected at the moment. Lets set the state and see what we need to do. m_current_state = mqtt::E_CLIENT_CONNECTED; if(!m_subTemp.first.isEmpty()) { this->subscribe( m_subTemp.first ); } else if(!m_pubTemp.first.isEmpty()) { this->publish( m_pubTemp.first, m_pubTemp.second ); } } void QMqttPubSubClient::slotOnDisconnected() { m_current_state = mqtt::E_CLIENT_DISCONNECTED; } void QMqttPubSubClient::slotOnError(const QMQTT::ClientError error) { m_current_state = mqtt::E_CLIENT_ERROR; LogError( "[QMqttPubSubClient::slotOnError]", QString( "An error occured : %1" ).arg( error ) ); LogError( "[QMqttPubSubClient::slotOnError]", this->getErrorMessage( error ) ); } QString QMqttPubSubClient::getErrorMessage( const QMQTT::ClientError error ) { QString l_error_message; switch( error ) { case QMQTT::SocketConnectionRefusedError: l_error_message = "[Socket] - Connection Refused"; break; case QMQTT::SocketRemoteHostClosedError: l_error_message = "[Socket] - Remote Host Closed"; emit signalReInitialise(); break; case QMQTT::SocketHostNotFoundError: l_error_message = "[Socket] - Host Not Found."; break; case QMQTT::SocketAccessError: l_error_message = "[Socket] - Access Error."; break; case QMQTT::SocketResourceError: l_error_message = "[Socket] - Resource Error."; break; case QMQTT::SocketTimeoutError: l_error_message = "[Socket] - Timeout."; break; case QMQTT::SocketDatagramTooLargeError: l_error_message = "[Socket] - Datagram Too Large."; break; case QMQTT::SocketNetworkError: l_error_message = "[Socket] - Network Error."; break; case QMQTT::SocketAddressInUseError: l_error_message = "[Socket] - Address In Use."; break; case QMQTT::SocketAddressNotAvailableError: l_error_message = "[Socket] - Address Not Available."; break; case QMQTT::SocketUnsupportedSocketOperationError: l_error_message = "[Socket] - Unsupported Socket Operation."; break; case QMQTT::SocketUnfinishedSocketOperationError: l_error_message = "[Socket] - Unfinished Socket Operation."; break; case QMQTT::SocketProxyAuthenticationRequiredError: l_error_message = "[Socket] - Proxy Authentication Required."; break; case QMQTT::SocketSslHandshakeFailedError: l_error_message = "[Socket] - SSL Handshake Failed."; break; case QMQTT::SocketProxyConnectionRefusedError: l_error_message = "[Socket] - Proxy Connection Refused."; break; case QMQTT::SocketProxyConnectionClosedError: l_error_message = "[Socket] - Proxy Connection Closed."; break; case QMQTT::SocketProxyConnectionTimeoutError: l_error_message = "[Socket] - Proxy Connection Closed."; break; case QMQTT::SocketProxyNotFoundError: l_error_message = "[Socket] - Proxy Not Found."; break; case QMQTT::SocketProxyProtocolError: l_error_message = "[Socket] - Proxy Protocol Error."; break; case QMQTT::SocketOperationError: l_error_message = "[Socket] - Operation Error."; break; case QMQTT::SocketSslInternalError: l_error_message = "[Socket] - SSL Internal Error."; break; case QMQTT::SocketSslInvalidUserDataError: l_error_message = "[Socket] - SSL Invalid User Data."; break; case QMQTT::SocketTemporaryError: l_error_message = "[Socket] - Temporary Error."; break; case QMQTT::MqttUnacceptableProtocolVersionError: l_error_message = "[MQTT] - Unacceptable Protocol Version."; break; case QMQTT::MqttIdentifierRejectedError: l_error_message = "[MQTT] - Identifier Rejected."; break; case QMQTT::MqttServerUnavailableError: l_error_message = "[MQTT] - Server Unavailable."; break; case QMQTT::MqttBadUserNameOrPasswordError: l_error_message = "[MQTT] - Bad Username Or Password."; break; case QMQTT::MqttNotAuthorizedError: l_error_message = "[MQTT] - Not Authorized."; break; case QMQTT::MqttNoPingResponse: l_error_message = "[MQTT] - No Ping Response"; break; case QMQTT::UnknownError: default: l_error_message = "An Unknown Error Occurred"; break; } return l_error_message; } void QMqttPubSubClient::slotOnSubscribed(const QString& topic, const quint8 qos) { Q_UNUSED(qos); m_current_state = mqtt::E_CLIENT_SUBSCRIBED; LogInfo("[QMqttPubSubClient::slotOnSubscribed]", QString("Subscribed to topic %1").arg(topic)); } void QMqttPubSubClient::slotOnUnSubscribed(const QString& topic) { m_current_state = mqtt::E_CLIENT_UNSUBSCRIBED; LogInfo("[QMqttPubSubClient::slotOnUnSubscribed]", QString("Unsubscribed to topic %1").arg(topic)); } void QMqttPubSubClient::slotOnPublished(const QMQTT::Message& message, quint16 msgid) { m_current_state = mqtt::E_CLIENT_PUBLISHED; LogInfo("[QMqttPubSubClient::slotOnPublished]", QString("Message %1 published to topic %2 with id %3").arg(message.topic()).arg(message.payload().toStdString().c_str()).arg(msgid)); } void QMqttPubSubClient::slotOnReceived(const QMQTT::Message& message) { LogDebug("[QMqttPubSubClient::slotOnReceived]", QString("Received payload : %1 from topic : %2").arg(message.payload().toStdString().c_str()).arg(message.topic())); emit signalMessageReceived(message.topic(), message.payload().toStdString().c_str()); } void QMqttPubSubClient::slotOnPingResp() { LogDebug("[QMqttPubSubClient::slotOnPingResp]", QString("Ping Response received.")); } #ifndef QT_NO_SSL void QMqttPubSubClient::slotSslErrors(const QList& errors) { Q_UNUSED(errors); } #endif /* QT_NO_SSL */ void QMqttPubSubClient::connectSignalsAndSlots() { connect(this, &QMQTT::Client::connected, this, &QMqttPubSubClient::slotOnConnected); connect(this, &QMQTT::Client::disconnected, this, &QMqttPubSubClient::slotOnDisconnected); connect(this, &QMQTT::Client::error, this, &QMqttPubSubClient::slotOnError); connect(this, &QMQTT::Client::subscribed, this, &QMqttPubSubClient::slotOnSubscribed); connect(this, &QMQTT::Client::unsubscribed, this, &QMqttPubSubClient::slotOnUnSubscribed); connect(this, &QMQTT::Client::published, this, &QMqttPubSubClient::slotOnPublished); connect(this, &QMQTT::Client::received, this, &QMqttPubSubClient::slotOnReceived); connect(this, &QMQTT::Client::pingresp, this, &QMqttPubSubClient::slotOnPingResp); #ifndef QT_NO_SSL connect(this, &QMQTT::Client::sslErrors, this, &QMqttPubSubClient::slotSslErrors); #endif /* QT_NO_SSL */ }