/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright 2013 - 2020, nymea GmbH
* Contact: contact@nymea.io
*
* This file is part of nymea.
* This project including source code and documentation is protected by
* copyright law, and remains the property of nymea GmbH. All rights, including
* reproduction, publication, editing and translation, are reserved. The use of
* this project is subject to the terms of a license agreement to be concluded
* with nymea GmbH in accordance with the terms of use of nymea GmbH, available
* under https://nymea.io/license
*
* GNU Lesser General Public License Usage
* Alternatively, this project may be redistributed and/or modified under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; version 3. This project is distributed in the hope that
* it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this project. If not, see .
*
* For any further details and any questions please contact us under
* contact@nymea.io or see our FAQ/Licensing Information on
* https://nymea.io/license/faq
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class CoapReply
\brief Represents a reply of a CoAP request.
\ingroup coap-group
\inmodule libnymea
The CoapReply class contains the data and headers for a request sent with \l{Coap} client.
\note Please don't forget to delete the reply once it is finished.
\section2 Example
\code
Coap *coap = new Coap(this);
connect(coap, SIGNAL(replyFinished(CoapReply*)), this, SLOT(onReplyFinished(CoapReply*)));
CoapRequest request(QUrl("coap://example.com/"));
CoapReply *reply = coap->ping(request);
\endcode
\code
void MyClass::onReplyFinished(CoapReply *reply)
{
if (reply->error() != CoapReply::NoError) {
qWarning() << "Reply finished with error" << reply->errorString();
reply->deleteLater();
return;
}
qDebug() << "Reply finished" << reply;
reply->deleteLater();
}
\endcode
\sa Coap, CoapRequest
*/
/*! \fn void CoapReply::timeout();
This signal is emitted when the reply took to long.
*/
/*! \fn void CoapReply::finished();
This signal is emitted when the reply is finished.
*/
/*! \fn void CoapReply::error(const Error &code);
This signal is emitted when an error occurred. The given \a code represents the \l{CoapReply::Error}.
\sa error(), errorString()
*/
/*! \enum CoapReply::Error
\value NoError
No error occurred. Everything ok.
\value HostNotFoundError
The remote host name was not found (invalid hostname).
\value TimeoutError
The server did not respond after 4 retransmissions.
\value InvalidUrlSchemeError
The given URL does not have a valid scheme.
\value InvalidPduError
The package data unit (PDU) could not be parsed successfully.
*/
#include "coapreply.h"
#include "coappdu.h"
#include
/*! Returns the request for this \l{CoapReply}. */
CoapRequest CoapReply::request() const
{
return m_request;
}
/*! Returns the payload of this \l{CoapReply}. The payload will be available once the \l{CoapReply} is finished.
\sa isFinished
*/
QByteArray CoapReply::payload() const
{
return m_payload;
}
/*! Returns true if the \l{CoapReply} is finished.
\sa finished()
*/
bool CoapReply::isFinished() const
{
return m_isFinished;
}
/*! Returns true if the \l{CoapReply} is running.
\sa finished()
*/
bool CoapReply::isRunning() const
{
return m_timer->isActive();
}
/*! Returns error \l{CoapReply::Error} of the \l{CoapReply}.
\sa errorString()
*/
CoapReply::Error CoapReply::error() const
{
return m_error;
}
/*! Returns error string of the \l{CoapReply}.
\sa error()
*/
QString CoapReply::errorString() const
{
QString errorString;
switch (m_error) {
case NoError:
break;
case HostNotFoundError:
errorString = "The remote host name was not found (invalid hostname).";
break;
case TimeoutError:
errorString = "The server did not respond after 4 retransmissions.";
break;
case InvalidUrlSchemeError:
errorString = "The given URL does not have a valid scheme.";
break;
case InvalidPduError:
errorString = "The package data unit (PDU) could not be parsed successfully.";
break;
default:
break;
}
return errorString;
}
/*! Returns the \l{CoapPdu::ContentType} of this \l{CoapReply}. */
CoapPdu::ContentType CoapReply::contentType() const
{
return m_contentType;
}
/*! Returns the \l{CoapPdu::MessageType} of this \l{CoapReply}. */
CoapPdu::MessageType CoapReply::messageType() const
{
return m_messageType;
}
/*! Returns the \l{CoapPdu::StatusCode} of this \l{CoapReply}. */
CoapPdu::StatusCode CoapReply::statusCode() const
{
return m_statusCode;
}
CoapReply::CoapReply(const CoapRequest &request, QObject *parent) :
QObject(parent),
m_request(request),
m_error(NoError),
m_isFinished(false),
m_retransmissions(1),
m_contentType(CoapPdu::TextPlain),
m_messageType(CoapPdu::Acknowledgement),
m_statusCode(CoapPdu::Empty),
m_lockedUp(false)
{
m_timer = new QTimer(this);
m_timer->setSingleShot(false);
m_timer->setInterval(2000);
connect(m_timer, &QTimer::timeout, this, &CoapReply::timeout);
}
QByteArray CoapReply::requestData() const
{
return m_requestData;
}
int CoapReply::messageId() const
{
return m_messageId;
}
void CoapReply::setMessageId(const int &messageId)
{
m_messageId = messageId;
}
QByteArray CoapReply::messageToken() const
{
return m_messageToken;
}
void CoapReply::setMessageToken(const QByteArray &messageToken)
{
m_messageToken = messageToken;
}
bool CoapReply::observation() const
{
return m_observation;
}
void CoapReply::setObservation(const bool &observation)
{
m_observation = observation;
}
bool CoapReply::observationEnable() const
{
return m_observationEnable;
}
void CoapReply::setObservationEnable(const bool &observationEnable)
{
m_observationEnable = observationEnable;
}
void CoapReply::setFinished()
{
m_isFinished = true;
m_timer->stop();
emit finished();
}
void CoapReply::setError(const CoapReply::Error &code)
{
m_error = code;
emit error(m_error);
}
void CoapReply::resend()
{
m_retransmissions++;
if (m_retransmissions > 5) {
setError(CoapReply::TimeoutError);
setFinished();
}
}
void CoapReply::setContentType(const CoapPdu::ContentType contentType)
{
m_contentType = contentType;
}
void CoapReply::setMessageType(const CoapPdu::MessageType &messageType)
{
m_messageType = messageType;
}
void CoapReply::setStatusCode(const CoapPdu::StatusCode &statusCode)
{
m_statusCode = statusCode;
}
void CoapReply::setHostAddress(const QHostAddress &address)
{
m_hostAddress = address;
}
QHostAddress CoapReply::hostAddress() const
{
return m_hostAddress;
}
void CoapReply::setPort(const int &port)
{
m_port = port;
}
int CoapReply::port() const
{
return m_port;
}
void CoapReply::setRequestPayload(const QByteArray &requestPayload)
{
m_requestPayload = requestPayload;
}
QByteArray CoapReply::requestPayload() const
{
return m_requestPayload;
}
void CoapReply::setRequestMethod(const CoapPdu::StatusCode &method)
{
m_requestMethod = method;
}
CoapPdu::StatusCode CoapReply::requestMethod() const
{
return m_requestMethod;
}
void CoapReply::appendPayloadData(const QByteArray &data)
{
m_payload.append(data);
m_timer->start();
m_retransmissions = 1;
}
void CoapReply::setRequestData(const QByteArray &requestData)
{
m_requestData = requestData;
}
/*! Writes the data of the given \a reply to \a dbg.
\sa CoapReply
*/
QDebug operator<<(QDebug debug, CoapReply *reply)
{
const QMetaObject &metaObject = CoapPdu::staticMetaObject;
QMetaEnum messageTypeEnum = metaObject.enumerator(metaObject.indexOfEnumerator("MessageType"));
QMetaEnum contentTypeEnum = metaObject.enumerator(metaObject.indexOfEnumerator("ContentType"));
debug.nospace() << "CoapReply(" << messageTypeEnum.valueToKey(reply->messageType()) << ")" << endl;
debug.nospace() << " Status code: " << CoapPdu::getStatusCodeString(reply->statusCode()) << endl;
debug.nospace() << " Content type: " << contentTypeEnum.valueToKey(reply->contentType()) << endl;
debug.nospace() << " Payload size: " << reply->payload().size() << endl;
if (!reply->payload().isEmpty())
debug.nospace() << endl << reply->payload() << endl;
return debug.space();
}