add more rest resources
This commit is contained in:
parent
b86a062a87
commit
34e53ef5b3
@ -97,16 +97,41 @@
|
|||||||
...
|
...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*! \enum HttpReply::Type
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
#include "httpreply.h"
|
#include "httpreply.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QPair>
|
#include <QPair>
|
||||||
|
|
||||||
/*! Construct a HttpReply with the given \a statusCode. */
|
/*! Construct a HttpReply with the given \a statusCode. */
|
||||||
HttpReply::HttpReply(const HttpStatusCode &statusCode) :
|
HttpReply::HttpReply(QObject *parent) :
|
||||||
m_statusCode(statusCode),
|
QObject(parent),
|
||||||
m_payload(QByteArray())
|
m_statusCode(HttpReply::Ok),
|
||||||
|
m_type(HttpReply::TypeSync),
|
||||||
|
m_payload(QByteArray()),
|
||||||
|
m_timedOut(false)
|
||||||
{
|
{
|
||||||
|
connect(&m_timer, &QTimer::timeout, this, &HttpReply::timedOut);
|
||||||
|
|
||||||
|
// set known headers
|
||||||
|
setHeader(HttpHeaderType::ServerHeader, "guh/" + QByteArray(GUH_VERSION_STRING));
|
||||||
|
setHeader(HttpHeaderType::DateHeader, QDateTime::currentDateTime().toString("ddd, dd MMM yyyy hh:mm:ss").toUtf8() + " GMT");
|
||||||
|
setHeader(HttpHeaderType::CacheControlHeader, "no-cache");
|
||||||
|
packReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply::HttpReply(const HttpReply::HttpStatusCode &statusCode, const HttpReply::Type &type, QObject *parent):
|
||||||
|
QObject(parent),
|
||||||
|
m_statusCode(statusCode),
|
||||||
|
m_type(type),
|
||||||
|
m_payload(QByteArray()),
|
||||||
|
m_timedOut(false)
|
||||||
|
{
|
||||||
|
connect(&m_timer, &QTimer::timeout, this, &HttpReply::timedOut);
|
||||||
|
|
||||||
// set known headers
|
// set known headers
|
||||||
setHeader(HttpHeaderType::ServerHeader, "guh/" + QByteArray(GUH_VERSION_STRING));
|
setHeader(HttpHeaderType::ServerHeader, "guh/" + QByteArray(GUH_VERSION_STRING));
|
||||||
setHeader(HttpHeaderType::DateHeader, QDateTime::currentDateTime().toString("ddd, dd MMM yyyy hh:mm:ss").toUtf8() + " GMT");
|
setHeader(HttpHeaderType::DateHeader, QDateTime::currentDateTime().toString("ddd, dd MMM yyyy hh:mm:ss").toUtf8() + " GMT");
|
||||||
@ -118,6 +143,7 @@ HttpReply::HttpReply(const HttpStatusCode &statusCode) :
|
|||||||
void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode)
|
void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode)
|
||||||
{
|
{
|
||||||
m_statusCode = statusCode;
|
m_statusCode = statusCode;
|
||||||
|
packReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the status code of this \l{HttpReply}.*/
|
/*! Returns the status code of this \l{HttpReply}.*/
|
||||||
@ -126,11 +152,30 @@ HttpReply::HttpStatusCode HttpReply::httpStatusCode() const
|
|||||||
return m_statusCode;
|
return m_statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Returns the type of this \l{HttpReply}.
|
||||||
|
* \sa Type
|
||||||
|
*/
|
||||||
|
HttpReply::Type HttpReply::type() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpReply::setClientId(const QUuid &clientId)
|
||||||
|
{
|
||||||
|
m_clientId = clientId;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUuid HttpReply::clientId() const
|
||||||
|
{
|
||||||
|
return m_clientId;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Set the payload of this \l{HttpReply} to the given \a data.*/
|
/*! Set the payload of this \l{HttpReply} to the given \a data.*/
|
||||||
void HttpReply::setPayload(const QByteArray &data)
|
void HttpReply::setPayload(const QByteArray &data)
|
||||||
{
|
{
|
||||||
m_payload = data;
|
m_payload = data;
|
||||||
setHeader(HttpHeaderType::ContentLenghtHeader, QByteArray::number(data.length()));
|
setHeader(HttpHeaderType::ContentLenghtHeader, QByteArray::number(data.length()));
|
||||||
|
packReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Returns the payload of this \l{HttpReply}.*/
|
/*! Returns the payload of this \l{HttpReply}.*/
|
||||||
@ -149,6 +194,7 @@ void HttpReply::setRawHeader(const QByteArray headerType, const QByteArray &valu
|
|||||||
m_rawHeaderList.remove(headerType);
|
m_rawHeaderList.remove(headerType);
|
||||||
}
|
}
|
||||||
m_rawHeaderList.insert(headerType, value);
|
m_rawHeaderList.insert(headerType, value);
|
||||||
|
packReply();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! This method appends a known header to the header list of this \l{HttpReply}.
|
/*! This method appends a known header to the header list of this \l{HttpReply}.
|
||||||
@ -211,6 +257,11 @@ QByteArray HttpReply::data() const
|
|||||||
return m_data;
|
return m_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HttpReply::timedOut() const
|
||||||
|
{
|
||||||
|
return m_timedOut;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray HttpReply::getHttpReasonPhrase(const HttpReply::HttpStatusCode &statusCode)
|
QByteArray HttpReply::getHttpReasonPhrase(const HttpReply::HttpStatusCode &statusCode)
|
||||||
{
|
{
|
||||||
switch (statusCode) {
|
switch (statusCode) {
|
||||||
@ -278,3 +329,14 @@ QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
|
|||||||
return QByteArray();
|
return QByteArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpReply::startWait()
|
||||||
|
{
|
||||||
|
m_timer.start(5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HttpReply::timeout()
|
||||||
|
{
|
||||||
|
m_timedOut = true;
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
|||||||
@ -21,13 +21,17 @@
|
|||||||
#ifndef HTTPREPLY_H
|
#ifndef HTTPREPLY_H
|
||||||
#define HTTPREPLY_H
|
#define HTTPREPLY_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QUuid>
|
||||||
|
|
||||||
// Note: RFC 7231 HTTP/1.1 Semantics and Content -> http://tools.ietf.org/html/rfc7231
|
// Note: RFC 7231 HTTP/1.1 Semantics and Content -> http://tools.ietf.org/html/rfc7231
|
||||||
|
|
||||||
class HttpReply
|
class HttpReply: public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum HttpStatusCode {
|
enum HttpStatusCode {
|
||||||
@ -62,11 +66,22 @@ public:
|
|||||||
ServerHeader
|
ServerHeader
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit HttpReply(const HttpStatusCode &statusCode = HttpStatusCode::Ok);
|
enum Type {
|
||||||
|
TypeSync,
|
||||||
|
TypeAsync
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpReply(QObject *parent = 0);
|
||||||
|
HttpReply(const HttpStatusCode &statusCode = HttpStatusCode::Ok, const Type &type = TypeSync, QObject *parent = 0);
|
||||||
|
|
||||||
void setHttpStatusCode(const HttpStatusCode &statusCode);
|
void setHttpStatusCode(const HttpStatusCode &statusCode);
|
||||||
HttpStatusCode httpStatusCode() const;
|
HttpStatusCode httpStatusCode() const;
|
||||||
|
|
||||||
|
Type type() const;
|
||||||
|
|
||||||
|
void setClientId(const QUuid &clientId);
|
||||||
|
QUuid clientId() const;
|
||||||
|
|
||||||
void setPayload(const QByteArray &data);
|
void setPayload(const QByteArray &data);
|
||||||
QByteArray payload() const;
|
QByteArray payload() const;
|
||||||
|
|
||||||
@ -82,18 +97,34 @@ public:
|
|||||||
|
|
||||||
QByteArray data() const;
|
QByteArray data() const;
|
||||||
|
|
||||||
|
bool timedOut() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpStatusCode m_statusCode;
|
HttpStatusCode m_statusCode;
|
||||||
|
Type m_type;
|
||||||
|
QUuid m_clientId;
|
||||||
|
|
||||||
QByteArray m_rawHeader;
|
QByteArray m_rawHeader;
|
||||||
QByteArray m_payload;
|
QByteArray m_payload;
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
|
|
||||||
QHash<QByteArray, QByteArray> m_rawHeaderList;
|
QHash<QByteArray, QByteArray> m_rawHeaderList;
|
||||||
|
|
||||||
|
QTimer m_timer;
|
||||||
|
bool m_timedOut;
|
||||||
|
|
||||||
QByteArray getHttpReasonPhrase(const HttpStatusCode &statusCode);
|
QByteArray getHttpReasonPhrase(const HttpStatusCode &statusCode);
|
||||||
QByteArray getHeaderType(const HttpHeaderType &headerType);
|
QByteArray getHeaderType(const HttpHeaderType &headerType);
|
||||||
|
|
||||||
QByteArray packHeader() const;
|
public slots:
|
||||||
|
void startWait();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void timeout();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HTTPREPLY_H
|
#endif // HTTPREPLY_H
|
||||||
|
|||||||
@ -56,9 +56,13 @@ HttpRequest::HttpRequest(QByteArray rawData) :
|
|||||||
qCWarning(dcWebServer) << "Unknown HTTP version:" << m_httpVersion;
|
qCWarning(dcWebServer) << "Unknown HTTP version:" << m_httpVersion;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_method = getRequestMethodType(statusLineTokens.at(0).simplified());
|
m_methodString = statusLineTokens.at(0).simplified();
|
||||||
|
m_method = getRequestMethodType(m_methodString);
|
||||||
|
|
||||||
m_urlQuery = QUrlQuery(statusLineTokens.at(1).simplified());
|
m_url = QUrl("http://example.com" + statusLineTokens.at(1).simplified());
|
||||||
|
|
||||||
|
if (m_url.hasQuery())
|
||||||
|
m_urlQuery = QUrlQuery(m_url.query());
|
||||||
|
|
||||||
// verify headers
|
// verify headers
|
||||||
foreach (const QString &line, headerLines) {
|
foreach (const QString &line, headerLines) {
|
||||||
@ -92,11 +96,21 @@ HttpRequest::RequestMethod HttpRequest::method() const
|
|||||||
return m_method;
|
return m_method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString HttpRequest::methodString() const
|
||||||
|
{
|
||||||
|
return m_methodString;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray HttpRequest::httpVersion() const
|
QByteArray HttpRequest::httpVersion() const
|
||||||
{
|
{
|
||||||
return m_httpVersion;
|
return m_httpVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl HttpRequest::url() const
|
||||||
|
{
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
QUrlQuery HttpRequest::urlQuery() const
|
QUrlQuery HttpRequest::urlQuery() const
|
||||||
{
|
{
|
||||||
return m_urlQuery;
|
return m_urlQuery;
|
||||||
@ -134,9 +148,10 @@ HttpRequest::RequestMethod HttpRequest::getRequestMethodType(const QString &meth
|
|||||||
|
|
||||||
QDebug operator<<(QDebug debug, const HttpRequest &httpRequest)
|
QDebug operator<<(QDebug debug, const HttpRequest &httpRequest)
|
||||||
{
|
{
|
||||||
debug << "===================================" << "\n";
|
debug << "\n===================================" << "\n";
|
||||||
debug << " http version: " << httpRequest.httpVersion() << "\n";
|
debug << " http version: " << httpRequest.httpVersion() << "\n";
|
||||||
debug << " method: " << httpRequest.method() << "\n";
|
debug << " method: " << httpRequest.methodString() << "\n";
|
||||||
|
debug << " URL path: " << httpRequest.url().path() << "\n";
|
||||||
debug << " URL query: " << httpRequest.urlQuery().query() << "\n";
|
debug << " URL query: " << httpRequest.urlQuery().query() << "\n";
|
||||||
debug << " is valid: " << httpRequest.isValid() << "\n";
|
debug << " is valid: " << httpRequest.isValid() << "\n";
|
||||||
debug << "-----------------------------------" << "\n";
|
debug << "-----------------------------------" << "\n";
|
||||||
|
|||||||
@ -43,7 +43,10 @@ public:
|
|||||||
QHash<QByteArray, QByteArray> rawHeaderList() const;
|
QHash<QByteArray, QByteArray> rawHeaderList() const;
|
||||||
|
|
||||||
RequestMethod method() const;
|
RequestMethod method() const;
|
||||||
|
QString methodString() const;
|
||||||
QByteArray httpVersion() const;
|
QByteArray httpVersion() const;
|
||||||
|
|
||||||
|
QUrl url() const;
|
||||||
QUrlQuery urlQuery() const;
|
QUrlQuery urlQuery() const;
|
||||||
|
|
||||||
QByteArray payload() const;
|
QByteArray payload() const;
|
||||||
@ -57,7 +60,10 @@ private:
|
|||||||
QHash<QByteArray, QByteArray> m_rawHeaderList;
|
QHash<QByteArray, QByteArray> m_rawHeaderList;
|
||||||
|
|
||||||
RequestMethod m_method;
|
RequestMethod m_method;
|
||||||
|
QString m_methodString;
|
||||||
QByteArray m_httpVersion;
|
QByteArray m_httpVersion;
|
||||||
|
|
||||||
|
QUrl m_url;
|
||||||
QUrlQuery m_urlQuery;
|
QUrlQuery m_urlQuery;
|
||||||
|
|
||||||
QByteArray m_payload;
|
QByteArray m_payload;
|
||||||
|
|||||||
@ -574,12 +574,9 @@ void DeviceHandler::devicesDiscovered(const DeviceClassId &deviceClassId, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonReply *reply = m_discoverRequests.take(deviceClassId);
|
JsonReply *reply = m_discoverRequests.take(deviceClassId);
|
||||||
QVariantList list;
|
|
||||||
foreach (const DeviceDescriptor &descriptor, deviceDescriptors) {
|
|
||||||
list.append(JsonTypes::packDeviceDescriptor(descriptor));
|
|
||||||
}
|
|
||||||
QVariantMap returns;
|
QVariantMap returns;
|
||||||
returns.insert("deviceDescriptors", list);
|
returns.insert("deviceDescriptors", JsonTypes::packDeviceDescriptors(deviceDescriptors));
|
||||||
returns.insert("deviceError", JsonTypes::deviceErrorToString(DeviceManager::DeviceErrorNoError));
|
returns.insert("deviceError", JsonTypes::deviceErrorToString(DeviceManager::DeviceErrorNoError));
|
||||||
|
|
||||||
reply->setData(returns);
|
reply->setData(returns);
|
||||||
|
|||||||
@ -713,6 +713,42 @@ QVariantList JsonTypes::packDeviceStates(Device *device)
|
|||||||
return stateValues;
|
return stateValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QVariantList JsonTypes::packDeviceDescriptors(const QList<DeviceDescriptor> deviceDescriptors)
|
||||||
|
{
|
||||||
|
QVariantList deviceDescriptorList;
|
||||||
|
foreach (const DeviceDescriptor &deviceDescriptor, deviceDescriptors) {
|
||||||
|
deviceDescriptorList.append(JsonTypes::packDeviceDescriptor(deviceDescriptor));
|
||||||
|
}
|
||||||
|
return deviceDescriptorList;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList JsonTypes::packActionTypes(const DeviceClass &deviceClass)
|
||||||
|
{
|
||||||
|
QVariantList actionTypes;
|
||||||
|
foreach (const ActionType &actionType, deviceClass.actionTypes()) {
|
||||||
|
actionTypes.append(JsonTypes::packActionType(actionType));
|
||||||
|
}
|
||||||
|
return actionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList JsonTypes::packStateTypes(const DeviceClass &deviceClass)
|
||||||
|
{
|
||||||
|
QVariantList stateTypes;
|
||||||
|
foreach (const StateType &stateType, deviceClass.stateTypes()) {
|
||||||
|
stateTypes.append(JsonTypes::packStateType(stateType));
|
||||||
|
}
|
||||||
|
return stateTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantList JsonTypes::packEventTypes(const DeviceClass &deviceClass)
|
||||||
|
{
|
||||||
|
QVariantList eventTypes;
|
||||||
|
foreach (const EventType &eventType, deviceClass.eventTypes()) {
|
||||||
|
eventTypes.append(JsonTypes::packEventType(eventType));
|
||||||
|
}
|
||||||
|
return eventTypes;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantList JsonTypes::packPlugins()
|
QVariantList JsonTypes::packPlugins()
|
||||||
{
|
{
|
||||||
QVariantList pluginsList;
|
QVariantList pluginsList;
|
||||||
|
|||||||
@ -165,6 +165,13 @@ public:
|
|||||||
static QVariantList packSupportedDevices(const VendorId &vendorId);
|
static QVariantList packSupportedDevices(const VendorId &vendorId);
|
||||||
static QVariantList packConfiguredDevices();
|
static QVariantList packConfiguredDevices();
|
||||||
static QVariantList packDeviceStates(Device *device);
|
static QVariantList packDeviceStates(Device *device);
|
||||||
|
static QVariantList packDeviceDescriptors(const QList<DeviceDescriptor> deviceDescriptors);
|
||||||
|
|
||||||
|
|
||||||
|
static QVariantList packActionTypes(const DeviceClass &deviceClass);
|
||||||
|
static QVariantList packStateTypes(const DeviceClass &deviceClass);
|
||||||
|
static QVariantList packEventTypes(const DeviceClass &deviceClass);
|
||||||
|
|
||||||
|
|
||||||
static QVariantList packPlugins();
|
static QVariantList packPlugins();
|
||||||
|
|
||||||
|
|||||||
269
server/rest/deviceclassesresource.cpp
Normal file
269
server/rest/deviceclassesresource.cpp
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "deviceclassesresource.h"
|
||||||
|
#include "network/httprequest.h"
|
||||||
|
#include "guhcore.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
DeviceClassesResource::DeviceClassesResource(QObject *parent) :
|
||||||
|
RestResource(parent)
|
||||||
|
{
|
||||||
|
connect(GuhCore::instance(), &GuhCore::devicesDiscovered, this, &DeviceClassesResource::devicesDiscovered, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
|
||||||
|
// get the main resource
|
||||||
|
|
||||||
|
// /api/v1/deviceclasses/{deviceClassId}/
|
||||||
|
if (urlTokens.count() >= 4) {
|
||||||
|
DeviceClassId deviceClassId = DeviceClassId(urlTokens.at(3));
|
||||||
|
if (deviceClassId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse DeviceClassId:" << urlTokens.at(3);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
m_deviceClass = GuhCore::instance()->findDeviceClass(deviceClassId);
|
||||||
|
if (!m_deviceClass.isValid()) {
|
||||||
|
return createErrorReply(HttpReply::NotFound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check method
|
||||||
|
HttpReply *reply;
|
||||||
|
switch (request.method()) {
|
||||||
|
case HttpRequest::Get:
|
||||||
|
reply = proccessGetRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reply = createErrorReply(HttpReply::BadRequest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses?vendorId="{vendorId}"
|
||||||
|
if (urlTokens.count() == 3) {
|
||||||
|
VendorId vendorId;
|
||||||
|
if (request.url().hasQuery()) {
|
||||||
|
if (request.urlQuery().hasQueryItem("vendorId")) {
|
||||||
|
vendorId = VendorId(request.urlQuery().queryItemValue("vendorId"));
|
||||||
|
if (vendorId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse VendorId:" << request.urlQuery().queryItemValue("vendorId");
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getDeviceClasses(vendorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}
|
||||||
|
if (urlTokens.count() == 4)
|
||||||
|
return getDeviceClass();
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/actiontypes
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "actiontypes")
|
||||||
|
return getActionTypes();
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/actiontypes/{actionTypeId}
|
||||||
|
if (urlTokens.count() == 6 && urlTokens.at(4) == "actiontypes") {
|
||||||
|
ActionTypeId actionTypeId = ActionTypeId(urlTokens.at(5));
|
||||||
|
if (actionTypeId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse ActionTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
return getActionType(actionTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/statetypes
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "statetypes")
|
||||||
|
return getStateTypes();
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/statetypes/{stateTypeId}
|
||||||
|
if (urlTokens.count() == 6 && urlTokens.at(4) == "statetypes") {
|
||||||
|
StateTypeId stateTypeId = StateTypeId(urlTokens.at(5));
|
||||||
|
if (stateTypeId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse StateTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
return getStateType(stateTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/eventtypes
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "eventtypes")
|
||||||
|
return getEventTypes();
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/eventtypes/{eventTypeId}
|
||||||
|
if (urlTokens.count() == 6 && urlTokens.at(4) == "eventtypes") {
|
||||||
|
EventTypeId eventTypeId = EventTypeId(urlTokens.at(5));
|
||||||
|
if (eventTypeId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse EventTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
return getEventType(eventTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GET /api/v1/deviceclasses/{deviceClassId}/discover?name=paramName&value=paramValue
|
||||||
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "discover") {
|
||||||
|
|
||||||
|
// FIXME: find a better way to get discovery params
|
||||||
|
|
||||||
|
ParamList paramList;
|
||||||
|
if (request.url().hasQuery()) {
|
||||||
|
if (request.urlQuery().hasQueryItem("name") && request.urlQuery().hasQueryItem("name")) {
|
||||||
|
paramList.append(Param(request.urlQuery().queryItemValue("name"), QVariant(request.urlQuery().queryItemValue("value"))));
|
||||||
|
} else {
|
||||||
|
qCWarning(dcRest) << "Invalid discovery params in" << request.urlQuery().query();
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getDiscoverdDevices(paramList);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getDeviceClass()
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get device class with id " << m_deviceClass.id();
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceClass(m_deviceClass)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getActionTypes()
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get action types for device class" << m_deviceClass.id();
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionTypes(m_deviceClass)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getActionType(const ActionTypeId &actionTypeId)
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get action type with id" << actionTypeId;
|
||||||
|
|
||||||
|
foreach (const ActionType &actionType, m_deviceClass.actionTypes()) {
|
||||||
|
if (actionType.id() == actionTypeId) {
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packActionType(actionType)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createErrorReply(HttpReply::NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getStateTypes()
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get state types for device class" << m_deviceClass.id();
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateTypes(m_deviceClass)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getStateType(const StateTypeId &stateTypeId)
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get state type with id" << stateTypeId;
|
||||||
|
|
||||||
|
foreach (const StateType &stateType, m_deviceClass.stateTypes()) {
|
||||||
|
if (stateType.id() == stateTypeId) {
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packStateType(stateType)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createErrorReply(HttpReply::NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getEventTypes()
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get event types for device class" << m_deviceClass.id();
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventTypes(m_deviceClass)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getEventType(const EventTypeId &eventTypeId)
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Get event type with id" << eventTypeId;
|
||||||
|
|
||||||
|
foreach (const EventType &eventType, m_deviceClass.eventTypes()) {
|
||||||
|
if (eventType.id() == eventTypeId) {
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packEventType(eventType)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return createErrorReply(HttpReply::NotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getDiscoverdDevices(const ParamList &discoveryParams)
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Discover devices for DeviceClass" << m_deviceClass.id();
|
||||||
|
|
||||||
|
DeviceManager::DeviceError status = GuhCore::instance()->discoverDevices(m_deviceClass.id(), discoveryParams);
|
||||||
|
|
||||||
|
if (status == DeviceManager::DeviceErrorAsync) {
|
||||||
|
HttpReply *reply = createAsyncReply();
|
||||||
|
m_discoverRequests.insert(m_deviceClass.id(), reply);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != DeviceManager::DeviceErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::InternalServerError);
|
||||||
|
|
||||||
|
return createSuccessReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceClassesResource::devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors)
|
||||||
|
{
|
||||||
|
if (!m_discoverRequests.contains(deviceClassId))
|
||||||
|
return; // Not the discovery we are waiting for.
|
||||||
|
|
||||||
|
qCDebug(dcRest) << "Discovery finished. Found" << deviceDescriptors.count() << "devices.";
|
||||||
|
HttpReply *reply = m_discoverRequests.take(deviceClassId);
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceDescriptors(deviceDescriptors)).toJson());
|
||||||
|
reply->finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId)
|
||||||
|
{
|
||||||
|
if (vendorId == VendorId()) {
|
||||||
|
qCDebug(dcRest) << "Get all device classes.";
|
||||||
|
} else {
|
||||||
|
qCDebug(dcRest) << "Get device classes for vendor" << vendorId.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *reply = createSuccessReply();
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packSupportedDevices(vendorId)).toJson());
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
74
server/rest/deviceclassesresource.h
Normal file
74
server/rest/deviceclassesresource.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef DEVICECLASSESRESOURCE_H
|
||||||
|
#define DEVICECLASSESRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class DeviceClassesResource : public RestResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit DeviceClassesResource(QObject *parent = 0);
|
||||||
|
|
||||||
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
mutable QHash<DeviceClassId, HttpReply *> m_discoverRequests;
|
||||||
|
|
||||||
|
DeviceClass m_deviceClass;
|
||||||
|
|
||||||
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
// Get methods
|
||||||
|
HttpReply *getDeviceClasses(const VendorId &vendorId);
|
||||||
|
HttpReply *getDeviceClass();
|
||||||
|
|
||||||
|
HttpReply *getActionTypes();
|
||||||
|
HttpReply *getActionType(const ActionTypeId &actionTypeId);
|
||||||
|
|
||||||
|
HttpReply *getStateTypes();
|
||||||
|
HttpReply *getStateType(const StateTypeId &stateTypeId);
|
||||||
|
|
||||||
|
HttpReply *getEventTypes();
|
||||||
|
HttpReply *getEventType(const EventTypeId &eventTypeId);
|
||||||
|
|
||||||
|
HttpReply *getDiscoverdDevices(const ParamList &discoveryParams);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DEVICECLASSESRESOURCE_H
|
||||||
@ -19,135 +19,342 @@
|
|||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
#include "devicesresource.h"
|
#include "devicesresource.h"
|
||||||
#include "jsontypes.h"
|
|
||||||
#include "guhcore.h"
|
|
||||||
#include "network/httpreply.h"
|
#include "network/httpreply.h"
|
||||||
#include "network/httprequest.h"
|
#include "network/httprequest.h"
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "guhcore.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
DevicesResource::DevicesResource(QObject *parent) :
|
DevicesResource::DevicesResource(QObject *parent) :
|
||||||
QObject(parent)
|
RestResource(parent)
|
||||||
{
|
{
|
||||||
|
connect(GuhCore::instance(), &GuhCore::actionExecuted, this, &DevicesResource::actionExecuted);
|
||||||
|
connect(GuhCore::instance(), &GuhCore::deviceSetupFinished, this, &DevicesResource::deviceSetupFinished);
|
||||||
|
connect(GuhCore::instance(), &GuhCore::deviceEditFinished, this, &DevicesResource::deviceEditFinished);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::proccessDeviceRequest(const HttpRequest &request, const QStringList &urlTokens)
|
HttpReply *DevicesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
{
|
{
|
||||||
DeviceId deviceId;
|
m_device = 0;
|
||||||
StateTypeId stateTypeId;
|
|
||||||
|
|
||||||
Device *device = 0;
|
// get the main resource
|
||||||
|
|
||||||
// first parse device, stateTypeId
|
|
||||||
if (urlTokens.count() >= 4) {
|
if (urlTokens.count() >= 4) {
|
||||||
deviceId = DeviceId(urlTokens.at(3));
|
DeviceId deviceId = DeviceId(urlTokens.at(3));
|
||||||
if (deviceId.isNull()) {
|
if (deviceId.isNull()) {
|
||||||
qCWarning(dcRest) << "Could not parse DeviceId:" << urlTokens.at(3);
|
qCWarning(dcRest) << "Could not parse DeviceId:" << urlTokens.at(3);
|
||||||
return HttpReply(HttpReply::BadRequest);
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
}
|
}
|
||||||
device = GuhCore::instance()->findConfiguredDevice(deviceId);
|
m_device = GuhCore::instance()->findConfiguredDevice(deviceId);
|
||||||
if (!device) {
|
if (!m_device) {
|
||||||
qCWarning(dcRest) << "Could find any device with DeviceId:" << urlTokens.at(3);
|
qCWarning(dcRest) << "Could find any device with DeviceId:" << urlTokens.at(3);
|
||||||
return HttpReply(HttpReply::NotFound);
|
return createErrorReply(HttpReply::NotFound);
|
||||||
}
|
|
||||||
|
|
||||||
// /api/v1/devices/{deviceId}/states/{stateTypeId}
|
|
||||||
if (urlTokens.count() >= 6 && urlTokens.at(4) == "states") {
|
|
||||||
stateTypeId = StateTypeId(urlTokens.at(5));
|
|
||||||
if (stateTypeId.isNull()) {
|
|
||||||
qCWarning(dcRest) << "Could not parse StateTypeId:" << urlTokens.at(5);
|
|
||||||
return HttpReply(HttpReply::BadRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!device->hasState(stateTypeId)){
|
|
||||||
qCWarning(dcRest) << "This device has no StateTypeId:" << urlTokens.at(5);
|
|
||||||
return HttpReply(HttpReply::NotFound);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check methods
|
// check method
|
||||||
if (request.method() == HttpRequest::Get) {
|
HttpReply *reply;
|
||||||
|
switch (request.method()) {
|
||||||
|
case HttpRequest::Get:
|
||||||
|
reply = proccessGetRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
|
case HttpRequest::Post:
|
||||||
|
reply = proccessPostRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
|
case HttpRequest::Put:
|
||||||
|
reply = proccessPutRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
|
case HttpRequest::Delete:
|
||||||
|
reply = proccessDeleteRequest(request, urlTokens);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reply = createErrorReply(HttpReply::BadRequest);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
// /api/v1/devices
|
HttpReply *DevicesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
if (urlTokens.count() == 3)
|
{
|
||||||
return getConfiguredDevices();
|
Q_UNUSED(request)
|
||||||
|
|
||||||
// /api/v1/devices/{deviceId}
|
// GET /api/v1/devices
|
||||||
if (urlTokens.count() == 4)
|
if (urlTokens.count() == 3)
|
||||||
return getConfiguredDevice(device);
|
return getConfiguredDevices();
|
||||||
|
|
||||||
// /api/v1/devices/{deviceId}/states
|
// GET /api/v1/devices/{deviceId}
|
||||||
if (urlTokens.count() == 5 && urlTokens.at(4) == "states")
|
if (urlTokens.count() == 4)
|
||||||
return getDeviceStateValues(device);
|
return getConfiguredDevice(m_device);
|
||||||
|
|
||||||
// /api/v1/devices/{deviceId}/states/{stateTypeId}
|
// GET /api/v1/devices/{deviceId}/states
|
||||||
if (urlTokens.count() == 6 && urlTokens.at(4) == "states")
|
if (urlTokens.count() == 5 && urlTokens.at(4) == "states")
|
||||||
return getDeviceStateValue(device, stateTypeId);
|
return getDeviceStateValues(m_device);
|
||||||
} else if (request.method() == HttpRequest::Delete) {
|
|
||||||
|
|
||||||
// /api/v1/devices
|
|
||||||
if (urlTokens.count() == 3)
|
|
||||||
return HttpReply(HttpReply::BadRequest);
|
|
||||||
|
|
||||||
if (urlTokens.count() == 4)
|
// /api/v1/devices/{deviceId}/states/{stateTypeId}
|
||||||
return removeDevice(device);
|
if (urlTokens.count() >= 6 && urlTokens.at(4) == "states") {
|
||||||
|
StateTypeId stateTypeId = StateTypeId(urlTokens.at(5));
|
||||||
|
if (stateTypeId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse StateTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_device->hasState(stateTypeId)){
|
||||||
|
qCWarning(dcRest) << "This device has no StateTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::NotFound);
|
||||||
|
}
|
||||||
|
return getDeviceStateValue(m_device, stateTypeId);
|
||||||
|
}
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
|
||||||
|
// DELETE /api/v1/devices
|
||||||
|
if (urlTokens.count() == 3)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// DELETE /api/v1/devices/{deviceId}
|
||||||
|
if (urlTokens.count() == 4)
|
||||||
|
return removeDevice(m_device);
|
||||||
|
|
||||||
|
// TODO: /api/v1/devices/{deviceId}?ruleId={ruleId}&removePolicy={RemovePolicy}
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
// POST /api/v1/devices
|
||||||
|
if (urlTokens.count() == 3)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// POST /api/v1/devices/{deviceId}
|
||||||
|
if (urlTokens.count() == 4)
|
||||||
|
return editDevice(m_device, request.payload());
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
// POST /api/v1/devices
|
||||||
|
if (urlTokens.count() == 3)
|
||||||
|
return addConfiguredDevice(request.payload());
|
||||||
|
|
||||||
|
// POST /api/v1/devices/{deviceId}
|
||||||
|
if (urlTokens.count() == 4)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
// POST /api/v1/devices/{deviceId}/execute/{actionTypeId}
|
||||||
|
if (urlTokens.count() >= 6 && urlTokens.at(4) == "execute") {
|
||||||
|
ActionTypeId actionTypeId = ActionTypeId(urlTokens.at(5));
|
||||||
|
if (actionTypeId.isNull()) {
|
||||||
|
qCWarning(dcRest) << "Could not parse ActionTypeId:" << urlTokens.at(5);
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
return executeAction(m_device, actionTypeId, request.payload());
|
||||||
}
|
}
|
||||||
|
|
||||||
return HttpReply(HttpReply::BadRequest);
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::getConfiguredDevices()
|
HttpReply *DevicesResource::getConfiguredDevices() const
|
||||||
{
|
{
|
||||||
HttpReply httpReply(HttpReply::Ok);
|
qCDebug(dcRest) << "Get all configured devices";
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
HttpReply *reply = createSuccessReply();
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(JsonTypes::packConfiguredDevices()).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packConfiguredDevices()).toJson());
|
||||||
httpReply.packReply();
|
return reply;
|
||||||
return httpReply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::getConfiguredDevice(Device *device)
|
HttpReply *DevicesResource::getConfiguredDevice(Device *device) const
|
||||||
{
|
{
|
||||||
HttpReply httpReply(HttpReply::Ok);
|
qCDebug(dcRest) << "Get configured device with id:" << device->id().toString();
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
HttpReply *reply = createSuccessReply();
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(JsonTypes::packDevice(device)).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDevice(device)).toJson());
|
||||||
httpReply.packReply();
|
return reply;
|
||||||
return httpReply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::getDeviceStateValues(Device *device)
|
HttpReply *DevicesResource::getDeviceStateValues(Device *device) const
|
||||||
{
|
{
|
||||||
HttpReply httpReply(HttpReply::Ok);
|
qCDebug(dcRest) << "Get states of device with id:" << device->id().toString();
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
HttpReply *reply = createSuccessReply();
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceStates(device)).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceStates(device)).toJson());
|
||||||
httpReply.packReply();
|
return reply;
|
||||||
return httpReply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::getDeviceStateValue(Device *device, const StateTypeId &stateTypeId)
|
HttpReply *DevicesResource::getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const
|
||||||
{
|
{
|
||||||
HttpReply httpReply(HttpReply::Ok);
|
qCDebug(dcRest) << "Get device state value of state with id:" << stateTypeId.toString();
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
HttpReply *reply = createSuccessReply();
|
||||||
QVariantMap stateValue;
|
QVariantMap stateValueMap;
|
||||||
stateValue.insert("value", device->state(stateTypeId).value());
|
stateValueMap.insert("value", device->state(stateTypeId).value());
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(stateValue).toJson());
|
reply->setPayload(QJsonDocument::fromVariant(stateValueMap).toJson());
|
||||||
httpReply.packReply();
|
return reply;
|
||||||
return httpReply;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpReply DevicesResource::removeDevice(Device *device)
|
HttpReply *DevicesResource::removeDevice(Device *device) const
|
||||||
{
|
{
|
||||||
|
qCDebug(dcRest) << "Remove device with id:" << device->id().toString();
|
||||||
DeviceManager::DeviceError result = GuhCore::instance()->removeConfiguredDevice(device->id(), QHash<RuleId, RuleEngine::RemovePolicy>());
|
DeviceManager::DeviceError result = GuhCore::instance()->removeConfiguredDevice(device->id(), QHash<RuleId, RuleEngine::RemovePolicy>());
|
||||||
|
|
||||||
// TODO: parse removepolicy query params
|
// TODO: /api/v1/devices/{deviceId}?ruleId={ruleId}&removePolicy={RemovePolicy}
|
||||||
|
|
||||||
if (result == DeviceManager::DeviceErrorNoError)
|
if (result == DeviceManager::DeviceErrorNoError)
|
||||||
return HttpReply(HttpReply::Ok);
|
return createSuccessReply();
|
||||||
|
|
||||||
return HttpReply(HttpReply::Forbidden);
|
return createErrorReply(HttpReply::Forbidden);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Execute action" << actionTypeId.toString();
|
||||||
|
|
||||||
|
QPair<bool, QVariant> verification = RestResource::verifyPayload(payload);
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
QVariantMap message = verification.second.toMap();
|
||||||
|
|
||||||
|
if (!message.contains("params"))
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
ParamList actionParams = JsonTypes::unpackParams(message.value("params").toList());
|
||||||
|
|
||||||
|
Action action(actionTypeId, device->id());
|
||||||
|
action.setParams(actionParams);
|
||||||
|
|
||||||
|
DeviceManager::DeviceError status = GuhCore::instance()->executeAction(action);
|
||||||
|
if (status == DeviceManager::DeviceErrorAsync) {
|
||||||
|
HttpReply *reply = createAsyncReply();
|
||||||
|
m_asyncActionExecutions.insert(action.id(), reply);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != DeviceManager::DeviceErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::InternalServerError);
|
||||||
|
|
||||||
|
return createSuccessReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
|
||||||
|
{
|
||||||
|
QPair<bool, QVariant> verification = RestResource::verifyPayload(payload);
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
qCDebug(dcRest) << "Add device";
|
||||||
|
|
||||||
|
QVariantMap params = verification.second.toMap();
|
||||||
|
|
||||||
|
DeviceClassId deviceClass(params.value("deviceClassId").toString());
|
||||||
|
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
|
||||||
|
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
|
||||||
|
DeviceId newDeviceId = DeviceId::createDeviceId();
|
||||||
|
|
||||||
|
DeviceManager::DeviceError status;
|
||||||
|
if (deviceDescriptorId.isNull()) {
|
||||||
|
qCDebug(dcRest) << "...adding device with params" << deviceParams;
|
||||||
|
status = GuhCore::instance()->addConfiguredDevice(deviceClass, deviceParams, newDeviceId);
|
||||||
|
} else {
|
||||||
|
qCDebug(dcRest) << "...adding discovered device with descriptor id" << deviceDescriptorId;
|
||||||
|
status = GuhCore::instance()->addConfiguredDevice(deviceClass, deviceDescriptorId, newDeviceId);
|
||||||
|
}
|
||||||
|
if (status == DeviceManager::DeviceErrorAsync) {
|
||||||
|
HttpReply *reply = createAsyncReply();
|
||||||
|
m_asynDeviceAdditions.insert(newDeviceId, reply);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != DeviceManager::DeviceErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::InternalServerError);
|
||||||
|
|
||||||
|
return createSuccessReply();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *DevicesResource::editDevice(Device *device, const QByteArray &payload) const
|
||||||
|
{
|
||||||
|
qCDebug(dcRest) << "Edit device" << device->id();
|
||||||
|
QPair<bool, QVariant> verification = RestResource::verifyPayload(payload);
|
||||||
|
if (!verification.first)
|
||||||
|
return createErrorReply(HttpReply::BadRequest);
|
||||||
|
|
||||||
|
QVariantMap params = verification.second.toMap();
|
||||||
|
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
|
||||||
|
|
||||||
|
qCDebug(dcRest) << "Edit device with params:" << deviceParams;
|
||||||
|
DeviceManager::DeviceError status;
|
||||||
|
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
|
||||||
|
if (deviceDescriptorId.isNull()) {
|
||||||
|
status = GuhCore::instance()->editDevice(device->id(), deviceParams);
|
||||||
|
} else {
|
||||||
|
status = GuhCore::instance()->editDevice(device->id(), deviceDescriptorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == DeviceManager::DeviceErrorAsync) {
|
||||||
|
HttpReply *reply = createAsyncReply();
|
||||||
|
m_asyncEditDevice.insert(device, reply);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != DeviceManager::DeviceErrorNoError)
|
||||||
|
return createErrorReply(HttpReply::InternalServerError);
|
||||||
|
|
||||||
|
return createSuccessReply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicesResource::actionExecuted(const ActionId &actionId, DeviceManager::DeviceError status)
|
||||||
|
{
|
||||||
|
if (!m_asyncActionExecutions.contains(actionId))
|
||||||
|
return; // Not the action we are waiting for.
|
||||||
|
|
||||||
|
HttpReply *reply = m_asyncActionExecutions.take(actionId);
|
||||||
|
if (status == DeviceManager::DeviceErrorNoError) {
|
||||||
|
reply->setHttpStatusCode(HttpReply::Ok);
|
||||||
|
} else {
|
||||||
|
reply->setHttpStatusCode(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicesResource::deviceSetupFinished(Device *device, DeviceManager::DeviceError status)
|
||||||
|
{
|
||||||
|
if (!m_asyncEditDevice.contains(device))
|
||||||
|
return; // Not the device we are waiting for.
|
||||||
|
|
||||||
|
HttpReply *reply = m_asyncEditDevice.take(device);
|
||||||
|
if (status == DeviceManager::DeviceErrorNoError) {
|
||||||
|
reply->setHttpStatusCode(HttpReply::Ok);
|
||||||
|
} else {
|
||||||
|
reply->setHttpStatusCode(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap result;
|
||||||
|
result.insert("deviceId", device->id());
|
||||||
|
|
||||||
|
reply->setPayload(QJsonDocument::fromVariant(result).toJson());
|
||||||
|
reply->finished();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DevicesResource::deviceEditFinished(Device *device, DeviceManager::DeviceError status)
|
||||||
|
{
|
||||||
|
if (!m_asynDeviceAdditions.contains(device->id()))
|
||||||
|
return; // Not the device we are waiting for.
|
||||||
|
|
||||||
|
HttpReply *reply = m_asyncEditDevice.take(device);
|
||||||
|
if (status == DeviceManager::DeviceErrorNoError) {
|
||||||
|
reply->setHttpStatusCode(HttpReply::Ok);
|
||||||
|
} else {
|
||||||
|
reply->setHttpStatusCode(HttpReply::BadRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->finished();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,32 +22,58 @@
|
|||||||
#define DEVICESRESOURCE_H
|
#define DEVICESRESOURCE_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "jsontypes.h"
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
class HttpReply;
|
|
||||||
class HttpRequest;
|
class HttpRequest;
|
||||||
|
|
||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
class DevicesResource : public QObject
|
class DevicesResource: public RestResource
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit DevicesResource(QObject *parent = 0);
|
explicit DevicesResource(QObject *parent = 0);
|
||||||
|
|
||||||
HttpReply proccessDeviceRequest(const HttpRequest &request, const QStringList &urlTokens);
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HttpReply getConfiguredDevices();
|
mutable QHash<ActionId, HttpReply *> m_asyncActionExecutions;
|
||||||
HttpReply getConfiguredDevice(Device *device);
|
mutable QHash<DeviceId, HttpReply *> m_asynDeviceAdditions;
|
||||||
HttpReply getDeviceStateValues(Device *device);
|
mutable QHash<Device *, HttpReply *> m_asyncEditDevice;
|
||||||
HttpReply getDeviceStateValue(Device *device, const StateTypeId &stateTypeId);
|
mutable QHash<QUuid, HttpReply *> m_asyncPairingRequests;
|
||||||
|
|
||||||
HttpReply removeDevice(Device *device);
|
Device *m_device;
|
||||||
|
|
||||||
signals:
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
public slots:
|
// Get methods
|
||||||
|
HttpReply *getConfiguredDevices() const;
|
||||||
|
HttpReply *getConfiguredDevice(Device *device) const;
|
||||||
|
HttpReply *getDeviceStateValues(Device *device) const;
|
||||||
|
HttpReply *getDeviceStateValue(Device *device, const StateTypeId &stateTypeId) const;
|
||||||
|
|
||||||
|
// Delete methods
|
||||||
|
HttpReply *removeDevice(Device *device) const;
|
||||||
|
|
||||||
|
// Post methods
|
||||||
|
HttpReply *executeAction(Device *device, const ActionTypeId &actionTypeId, const QByteArray &payload) const;
|
||||||
|
HttpReply *addConfiguredDevice(const QByteArray &payload) const;
|
||||||
|
|
||||||
|
// Put methods
|
||||||
|
HttpReply *editDevice(Device *device, const QByteArray &payload) const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void actionExecuted(const ActionId &actionId, DeviceManager::DeviceError status);
|
||||||
|
void deviceSetupFinished(Device *device, DeviceManager::DeviceError status);
|
||||||
|
void deviceEditFinished(Device *device, DeviceManager::DeviceError status);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
71
server/rest/logsresource.cpp
Normal file
71
server/rest/logsresource.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "logsresource.h"
|
||||||
|
#include "network/httprequest.h"
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
LogsResource::LogsResource(QObject *parent) :
|
||||||
|
RestResource(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *LogsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *LogsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);}
|
||||||
|
|
||||||
|
HttpReply *LogsResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *LogsResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *LogsResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
62
server/rest/logsresource.h
Normal file
62
server/rest/logsresource.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef LOGSRESOURCE_H
|
||||||
|
#define LOGSRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class LogsResource : public RestResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit LogsResource(QObject *parent = 0);
|
||||||
|
|
||||||
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
// Get methods
|
||||||
|
|
||||||
|
// Delete methods
|
||||||
|
|
||||||
|
// Post methods
|
||||||
|
|
||||||
|
// Put methods
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // LOGSRESOURCE_H
|
||||||
72
server/rest/pluginsresource.cpp
Normal file
72
server/rest/pluginsresource.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "pluginsresource.h"
|
||||||
|
#include "network/httprequest.h"
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
PluginsResource::PluginsResource(QObject *parent) :
|
||||||
|
RestResource(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *PluginsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *PluginsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *PluginsResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *PluginsResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *PluginsResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
62
server/rest/pluginsresource.h
Normal file
62
server/rest/pluginsresource.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef PLUGINSRESOURCE_H
|
||||||
|
#define PLUGINSRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class PluginsResource : public RestResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PluginsResource(QObject *parent = 0);
|
||||||
|
|
||||||
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
// Get methods
|
||||||
|
|
||||||
|
// Delete methods
|
||||||
|
|
||||||
|
// Post methods
|
||||||
|
|
||||||
|
// Put methods
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PLUGINSRESOURCE_H
|
||||||
108
server/rest/restresource.cpp
Normal file
108
server/rest/restresource.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httprequest.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
#include "guhcore.h"
|
||||||
|
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
RestResource::RestResource(QObject *parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RestResource::~RestResource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::createSuccessReply()
|
||||||
|
{
|
||||||
|
HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeSync);
|
||||||
|
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::createErrorReply(const HttpReply::HttpStatusCode &statusCode)
|
||||||
|
{
|
||||||
|
HttpReply *reply = new HttpReply(statusCode, HttpReply::TypeSync);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::createAsyncReply()
|
||||||
|
{
|
||||||
|
HttpReply *reply = new HttpReply(HttpReply::Ok, HttpReply::TypeAsync);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<bool, QVariant> RestResource::verifyPayload(const QByteArray &payload)
|
||||||
|
{
|
||||||
|
QVariant data;
|
||||||
|
if (!payload.isEmpty()) {
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument jsonDoc = QJsonDocument::fromJson(payload, &error);
|
||||||
|
|
||||||
|
if(error.error != QJsonParseError::NoError) {
|
||||||
|
qCWarning(dcRest) << "Failed to parse JSON payload" << payload << ":" << error.errorString();
|
||||||
|
return QPair<bool, QVariant>(true, QVariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
data = jsonDoc.toVariant();
|
||||||
|
}
|
||||||
|
return QPair<bool, QVariant>(true, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RestResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
59
server/rest/restresource.h
Normal file
59
server/rest/restresource.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef RESTRESOURCE_H
|
||||||
|
#define RESTRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QPair>
|
||||||
|
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
class HttpReply;
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class RestResource : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit RestResource(QObject *parent = 0);
|
||||||
|
virtual ~RestResource() = 0;
|
||||||
|
|
||||||
|
virtual HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) = 0;
|
||||||
|
|
||||||
|
static HttpReply *createSuccessReply();
|
||||||
|
static HttpReply *createErrorReply(const HttpReply::HttpStatusCode &statusCode);
|
||||||
|
static HttpReply *createAsyncReply();
|
||||||
|
static QPair<bool, QVariant> verifyPayload(const QByteArray &payload);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens);
|
||||||
|
virtual HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens);
|
||||||
|
virtual HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens);
|
||||||
|
virtual HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RESTRESOURCE_H
|
||||||
@ -36,11 +36,16 @@ RestServer::RestServer(QObject *parent) :
|
|||||||
connect(m_webserver, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected);
|
connect(m_webserver, &WebServer::clientDisconnected, this, &RestServer::clientDisconnected);
|
||||||
connect(m_webserver, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest);
|
connect(m_webserver, &WebServer::httpRequestReady, this, &RestServer::processHttpRequest);
|
||||||
|
|
||||||
// Resources
|
|
||||||
m_deviceResource = new DevicesResource(this);
|
|
||||||
|
|
||||||
|
|
||||||
m_webserver->startServer();
|
m_webserver->startServer();
|
||||||
|
|
||||||
|
QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestServer::setup()
|
||||||
|
{
|
||||||
|
// Create resources
|
||||||
|
m_deviceResource = new DevicesResource(this);
|
||||||
|
m_deviceClassesResource = new DeviceClassesResource(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestServer::clientConnected(const QUuid &clientId)
|
void RestServer::clientConnected(const QUuid &clientId)
|
||||||
@ -55,108 +60,65 @@ void RestServer::clientDisconnected(const QUuid &clientId)
|
|||||||
|
|
||||||
void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &request)
|
void RestServer::processHttpRequest(const QUuid &clientId, const HttpRequest &request)
|
||||||
{
|
{
|
||||||
qCDebug(dcRest) << "Process HTTP request" << clientId << request.method() << request.urlQuery().query();
|
qCDebug(dcRest) << "Process HTTP request";
|
||||||
|
qCDebug(dcRest) << request;
|
||||||
|
|
||||||
QStringList urlTokens = request.urlQuery().query(QUrl::FullyDecoded).split("/");
|
QStringList urlTokens = request.url().path().split("/");
|
||||||
urlTokens.removeAll(QString());
|
urlTokens.removeAll(QString());
|
||||||
|
|
||||||
qCDebug(dcRest) << urlTokens;
|
qCDebug(dcRest) << urlTokens;
|
||||||
|
|
||||||
if (urlTokens.count() < 3) {
|
if (urlTokens.count() < 3) {
|
||||||
m_webserver->sendHttpReply(clientId, HttpReply(HttpReply::BadRequest));
|
HttpReply *reply = new HttpReply(HttpReply::BadRequest, HttpReply::TypeSync, this);
|
||||||
|
reply->setClientId(clientId);
|
||||||
|
m_webserver->sendHttpReply(reply);
|
||||||
|
reply->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urlTokens.at(2) == "devices") {
|
if (urlTokens.at(2) == "devices") {
|
||||||
HttpReply httpReply = m_deviceResource->proccessDeviceRequest(request, urlTokens);
|
HttpReply *reply = m_deviceResource->proccessRequest(request, urlTokens);
|
||||||
qCDebug(dcRest) << "sending header" << httpReply.rawHeader();
|
reply->setClientId(clientId);
|
||||||
m_webserver->sendHttpReply(clientId, httpReply);
|
if (reply->type() == HttpReply::TypeAsync) {
|
||||||
|
connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished);
|
||||||
|
reply->startWait();
|
||||||
|
m_asyncReplies.insert(clientId, reply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_webserver->sendHttpReply(reply);
|
||||||
|
reply->deleteLater();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (urlTokens.at(2) == "deviceclasses") {
|
||||||
// QString targetNamespace;
|
HttpReply *reply = m_deviceClassesResource->proccessRequest(request, urlTokens);
|
||||||
// QString method;
|
reply->setClientId(clientId);
|
||||||
// QVariantMap params;
|
if (reply->type() == HttpReply::TypeAsync) {
|
||||||
|
connect(reply, &HttpReply::finished, this, &RestServer::asyncReplyFinished);
|
||||||
// // check filter
|
reply->startWait();
|
||||||
// QVariantList deviceList;
|
m_asyncReplies.insert(clientId, reply);
|
||||||
// if (!request.urlQuery().hasQueryItem("id")) {
|
return;
|
||||||
// HttpReply httpReply = m_deviceResource->proccessDeviceRequest(request);
|
}
|
||||||
// m_webserver->sendHttpReply(clientId, httpReply);
|
m_webserver->sendHttpReply(reply);
|
||||||
// return;
|
reply->deleteLater();
|
||||||
// } else {
|
return;
|
||||||
// foreach (const QString& idString, request.urlQuery().allQueryItemValues("id")) {
|
}
|
||||||
// Device *device = GuhCore::instance()->deviceManager()->findConfiguredDevice(DeviceId(idString));
|
|
||||||
// if (device == Device()) {
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// if (request.method() == HttpRequest::Get && request.urlQuery().query() == "/api/v1/devices.json") {
|
|
||||||
// targetNamespace = "Devices";
|
|
||||||
// method = "GetConfiguredDevices";
|
|
||||||
// } else if (request.method() == HttpRequest::Get && request.urlQuery().query() == "/api/v1/devices.json") {
|
|
||||||
// targetNamespace = "Devices";
|
|
||||||
// method = "GetConfiguredDevices";
|
|
||||||
// } else {
|
|
||||||
// HttpReply httpReply(HttpReply::BadRequest);
|
|
||||||
// httpReply.setPayload("400 Bad Request.");
|
|
||||||
// httpReply.packReply();
|
|
||||||
// m_webserver->sendHttpReply(clientId, httpReply);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// JsonHandler *handler = GuhCore::instance()->jsonRPCServer()->handlers().value(targetNamespace);
|
|
||||||
|
|
||||||
// QPair<bool, QString> validationResult = handler->validateParams(method, params);
|
|
||||||
// if (!validationResult.first) {
|
|
||||||
// qCWarning(dcWebServer) << "Invalid params: " << validationResult.second;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// JsonReply *jsonReply;
|
|
||||||
// QMetaObject::invokeMethod(handler, method.toLatin1().data(), Q_RETURN_ARG(JsonReply*, jsonReply), Q_ARG(QVariantMap, params));
|
|
||||||
// if (jsonReply->type() == JsonReply::TypeAsync) {
|
|
||||||
// jsonReply->setClientId(clientId);
|
|
||||||
// connect(jsonReply, &JsonReply::finished, this, &RestServer::asyncReplyFinished);
|
|
||||||
// jsonReply->startWait();
|
|
||||||
// m_asyncReplies.insert(clientId, jsonReply);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// HttpReply httpReply(HttpReply::Ok);
|
|
||||||
// httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
|
||||||
// httpReply.setPayload(QJsonDocument::fromVariant(jsonReply->data()).toJson());
|
|
||||||
// httpReply.packReply();
|
|
||||||
|
|
||||||
// m_webserver->sendHttpReply(clientId, httpReply);
|
|
||||||
|
|
||||||
// jsonReply->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RestServer::asyncReplyFinished()
|
void RestServer::asyncReplyFinished()
|
||||||
{
|
{
|
||||||
JsonReply *jsonReply = qobject_cast<JsonReply*>(sender());
|
HttpReply *reply = qobject_cast<HttpReply*>(sender());
|
||||||
QUuid clientId = m_asyncReplies.key(jsonReply);
|
|
||||||
|
|
||||||
if (!jsonReply->timedOut()) {
|
qCDebug(dcWebServer) << "sending reply" << reply->data();
|
||||||
HttpReply httpReply(HttpReply::Ok);
|
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
if (!reply->timedOut()) {
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(jsonReply->data()).toJson());
|
reply->setHttpStatusCode(HttpReply::Ok);
|
||||||
httpReply.packReply();
|
|
||||||
m_webserver->sendHttpReply(clientId, httpReply);
|
|
||||||
} else {
|
} else {
|
||||||
HttpReply httpReply(HttpReply::GatewayTimeout);
|
reply->setHttpStatusCode(HttpReply::GatewayTimeout);
|
||||||
httpReply.setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
|
|
||||||
httpReply.setPayload(QJsonDocument::fromVariant(jsonReply->data()).toJson());
|
|
||||||
httpReply.packReply();
|
|
||||||
m_webserver->sendHttpReply(clientId, httpReply);
|
|
||||||
}
|
}
|
||||||
jsonReply->deleteLater();
|
|
||||||
|
m_webserver->sendHttpReply(reply);
|
||||||
|
reply->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
#include "webserver.h"
|
#include "webserver.h"
|
||||||
#include "jsonhandler.h"
|
#include "jsonhandler.h"
|
||||||
#include "devicesresource.h"
|
#include "devicesresource.h"
|
||||||
|
#include "deviceclassesresource.h"
|
||||||
|
|
||||||
class HttpRequest;
|
class HttpRequest;
|
||||||
class HttpReply;
|
class HttpReply;
|
||||||
@ -38,17 +39,17 @@ class RestServer : public QObject
|
|||||||
public:
|
public:
|
||||||
explicit RestServer(QObject *parent = 0);
|
explicit RestServer(QObject *parent = 0);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebServer *m_webserver;
|
WebServer *m_webserver;
|
||||||
QList<QUuid> m_clientList;
|
QList<QUuid> m_clientList;
|
||||||
QHash<QUuid, JsonReply *> m_asyncReplies;
|
QHash<QUuid, HttpReply *> m_asyncReplies;
|
||||||
|
|
||||||
DevicesResource *m_deviceResource;
|
DevicesResource *m_deviceResource;
|
||||||
|
DeviceClassesResource *m_deviceClassesResource;
|
||||||
signals:
|
|
||||||
void httpReplyReady(const HttpReply &httpReply);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void setup();
|
||||||
void clientConnected(const QUuid &clientId);
|
void clientConnected(const QUuid &clientId);
|
||||||
void clientDisconnected(const QUuid &clientId);
|
void clientDisconnected(const QUuid &clientId);
|
||||||
|
|
||||||
|
|||||||
70
server/rest/rulesresource.cpp
Normal file
70
server/rest/rulesresource.cpp
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "rulesresource.h"
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
RulesResource::RulesResource(QObject *parent) :
|
||||||
|
RestResource(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *RulesResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
62
server/rest/rulesresource.h
Normal file
62
server/rest/rulesresource.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef RULESRESOURCE_H
|
||||||
|
#define RULESRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class RulesResource : public RestResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit RulesResource(QObject *parent = 0);
|
||||||
|
|
||||||
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
// Get methods
|
||||||
|
|
||||||
|
// Delete methods
|
||||||
|
|
||||||
|
// Post methods
|
||||||
|
|
||||||
|
// Put methods
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // RULESRESOURCE_H
|
||||||
72
server/rest/vendorsresource.cpp
Normal file
72
server/rest/vendorsresource.cpp
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#include "vendorsresource.h"
|
||||||
|
#include "network/httprequest.h"
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
VendorsResource::VendorsResource(QObject *parent) :
|
||||||
|
RestResource(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *VendorsResource::proccessRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *VendorsResource::proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *VendorsResource::proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *VendorsResource::proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpReply *VendorsResource::proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens)
|
||||||
|
{
|
||||||
|
Q_UNUSED(request)
|
||||||
|
Q_UNUSED(urlTokens)
|
||||||
|
|
||||||
|
return createErrorReply(HttpReply::NotImplemented);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
62
server/rest/vendorsresource.h
Normal file
62
server/rest/vendorsresource.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||||
|
* *
|
||||||
|
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
|
||||||
|
* *
|
||||||
|
* This file is part of guh. *
|
||||||
|
* *
|
||||||
|
* Guh is free software: you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation, version 2 of the License. *
|
||||||
|
* *
|
||||||
|
* Guh 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 General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with guh. If not, see <http://www.gnu.org/licenses/>. *
|
||||||
|
* *
|
||||||
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
#ifndef VENDORSRESOURCE_H
|
||||||
|
#define VENDORSRESOURCE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
|
||||||
|
#include "jsontypes.h"
|
||||||
|
#include "restresource.h"
|
||||||
|
#include "network/httpreply.h"
|
||||||
|
|
||||||
|
class HttpRequest;
|
||||||
|
|
||||||
|
namespace guhserver {
|
||||||
|
|
||||||
|
class VendorsResource : public RestResource
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit VendorsResource(QObject *parent = 0);
|
||||||
|
|
||||||
|
HttpReply *proccessRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Process method
|
||||||
|
HttpReply *proccessGetRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessDeleteRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPutRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
HttpReply *proccessPostRequest(const HttpRequest &request, const QStringList &urlTokens) override;
|
||||||
|
|
||||||
|
// Get methods
|
||||||
|
|
||||||
|
// Delete methods
|
||||||
|
|
||||||
|
// Post methods
|
||||||
|
|
||||||
|
// Put methods
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // VENDORSRESOURCE_H
|
||||||
@ -26,7 +26,13 @@ SOURCES += $$top_srcdir/server/guhcore.cpp \
|
|||||||
$$top_srcdir/server/servermanager.cpp \
|
$$top_srcdir/server/servermanager.cpp \
|
||||||
$$top_srcdir/server/websocketserver.cpp \
|
$$top_srcdir/server/websocketserver.cpp \
|
||||||
$$top_srcdir/server/rest/restserver.cpp \
|
$$top_srcdir/server/rest/restserver.cpp \
|
||||||
|
$$top_srcdir/server/rest/restresource.cpp \
|
||||||
$$top_srcdir/server/rest/devicesresource.cpp \
|
$$top_srcdir/server/rest/devicesresource.cpp \
|
||||||
|
$$top_srcdir/server/rest/deviceclassesresource.cpp \
|
||||||
|
$$top_srcdir/server/rest/vendorsresource.cpp \
|
||||||
|
$$top_srcdir/server/rest/logsresource.cpp \
|
||||||
|
$$top_srcdir/server/rest/pluginsresource.cpp \
|
||||||
|
$$top_srcdir/server/rest/rulesresource.cpp \
|
||||||
|
|
||||||
|
|
||||||
HEADERS += $$top_srcdir/server/guhcore.h \
|
HEADERS += $$top_srcdir/server/guhcore.h \
|
||||||
@ -52,6 +58,12 @@ HEADERS += $$top_srcdir/server/guhcore.h \
|
|||||||
$$top_srcdir/server/servermanager.h \
|
$$top_srcdir/server/servermanager.h \
|
||||||
$$top_srcdir/server/websocketserver.h \
|
$$top_srcdir/server/websocketserver.h \
|
||||||
$$top_srcdir/server/rest/restserver.h \
|
$$top_srcdir/server/rest/restserver.h \
|
||||||
|
$$top_srcdir/server/rest/restresource.h \
|
||||||
$$top_srcdir/server/rest/devicesresource.h \
|
$$top_srcdir/server/rest/devicesresource.h \
|
||||||
|
$$top_srcdir/server/rest/deviceclassesresource.h \
|
||||||
|
$$top_srcdir/server/rest/vendorsresource.h \
|
||||||
|
$$top_srcdir/server/rest/logsresource.h \
|
||||||
|
$$top_srcdir/server/rest/pluginsresource.h \
|
||||||
|
$$top_srcdir/server/rest/rulesresource.h \
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ ServerManager::ServerManager(QObject *parent) :
|
|||||||
qCDebug(dcApplication) << "Starting JSON RPC Server";
|
qCDebug(dcApplication) << "Starting JSON RPC Server";
|
||||||
m_jsonServer = new JsonRPCServer(this);
|
m_jsonServer = new JsonRPCServer(this);
|
||||||
|
|
||||||
qCDebug(dcApplication) << "Starting REST Webserver";
|
qCDebug(dcApplication) << "Starting REST Server";
|
||||||
m_restServer = new RestServer(this);
|
m_restServer = new RestServer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -84,10 +84,16 @@ void WebServer::sendData(const QList<QUuid> &clients, const QVariantMap &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebServer::sendHttpReply(const QUuid &clientId, const HttpReply &reply)
|
void WebServer::sendHttpReply(HttpReply *reply)
|
||||||
{
|
{
|
||||||
QTcpSocket *socket = m_clientList.value(clientId);
|
QTcpSocket *socket = 0;
|
||||||
writeData(socket, reply.data());
|
socket = m_clientList.value(reply->clientId());
|
||||||
|
|
||||||
|
if (!socket) {
|
||||||
|
qCDebug(dcWebServer) << "Invalid socket pointer! This should never happen!!!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeData(socket, reply->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebServer::verifyFile(QTcpSocket *socket, const QString &fileName)
|
bool WebServer::verifyFile(QTcpSocket *socket, const QString &fileName)
|
||||||
@ -202,7 +208,6 @@ void WebServer::readClient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(dcWebServer) << QString("Got valid request from %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
qCDebug(dcWebServer) << QString("Got valid request from %1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort());
|
||||||
qCDebug(dcWebServer) << request;
|
|
||||||
|
|
||||||
// verify method
|
// verify method
|
||||||
if (request.method() == HttpRequest::Unhandled) {
|
if (request.method() == HttpRequest::Unhandled) {
|
||||||
@ -215,7 +220,7 @@ void WebServer::readClient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// verify query
|
// verify query
|
||||||
if (request.urlQuery().query().startsWith("/api/v1")) {
|
if (request.url().path().startsWith("/api/v1")) {
|
||||||
emit httpRequestReady(clientId, request);
|
emit httpRequestReady(clientId, request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ public:
|
|||||||
|
|
||||||
void sendData(const QUuid &clientId, const QVariantMap &data) override;
|
void sendData(const QUuid &clientId, const QVariantMap &data) override;
|
||||||
void sendData(const QList<QUuid> &clients, const QVariantMap &data) override;
|
void sendData(const QList<QUuid> &clients, const QVariantMap &data) override;
|
||||||
void sendHttpReply(const QUuid &clientId, const HttpReply &reply);
|
void sendHttpReply(HttpReply *reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTcpServer *m_server;
|
QTcpServer *m_server;
|
||||||
|
|||||||
@ -23,8 +23,9 @@
|
|||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
WebSocketServer::WebSocketServer(QObject *parent) :
|
WebSocketServer::WebSocketServer(QObject *parent) :
|
||||||
QObject(parent)
|
TransportInterface(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,12 +23,14 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "transportinterface.h"
|
||||||
|
|
||||||
// Note: WebSocket Protocol from the Internet Engineering Task Force (IETF) -> RFC6455 V13:
|
// Note: WebSocket Protocol from the Internet Engineering Task Force (IETF) -> RFC6455 V13:
|
||||||
// http://tools.ietf.org/html/rfc6455
|
// http://tools.ietf.org/html/rfc6455
|
||||||
|
|
||||||
namespace guhserver {
|
namespace guhserver {
|
||||||
|
|
||||||
class WebSocketServer : public QObject
|
class WebSocketServer : public TransportInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user