diff --git a/libsrc/jsonserver/CMakeLists.txt b/libsrc/jsonserver/CMakeLists.txt index 80233de4..3fed8c6e 100644 --- a/libsrc/jsonserver/CMakeLists.txt +++ b/libsrc/jsonserver/CMakeLists.txt @@ -1,33 +1,42 @@ # Define the current source locations -SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver) -SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver) +set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver) +set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver) # Group the headers that go through the MOC compiler -SET(JsonServer_QT_HEADERS +set(JsonServer_QT_HEADERS ${CURRENT_HEADER_DIR}/JsonServer.h ${CURRENT_SOURCE_DIR}/JsonClientConnection.h ) -SET(JsonServer_HEADERS +set(JsonServer_HEADERS ) -SET(JsonServer_SOURCES +set(JsonServer_SOURCES ${CURRENT_SOURCE_DIR}/JsonServer.cpp ${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp ) +set(JsonServer_RESOURCES + ${CURRENT_SOURCE_DIR}/resource.qrc +) + qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS}) +qt4_add_resources(JsonServer_RESOURCES_RCC ${JsonServer_RESOURCES} OPTIONS "-no-compress") + add_library(jsonserver ${JsonServer_HEADERS} ${JsonServer_QT_HEADERS} - ${JsonServer_HEADERS_MOC} ${JsonServer_SOURCES} + ${JsonServer_RESOURCES} + ${JsonServer_HEADERS_MOC} + ${JsonServer_RESOURCES_RCC} ) target_link_libraries(jsonserver hyperion + hyperion-utils jsoncpp) qt4_use_modules(jsonserver diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index ceb4cd3a..f14d9c6d 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -1,12 +1,36 @@ +// system includes +#include +#include + // stl includes #include +#include +#include +// Qt includes +#include + +// project includes #include "JsonClientConnection.h" JsonClientConnection::JsonClientConnection(QTcpSocket *socket) : QObject(), - _socket(socket) + _socket(socket), + _schemaChecker(), + _receiveBuffer() { + // read the json schema from the resource + QResource schemaData(":/schema.json"); + assert(schemaData.isValid()); + Json::Reader jsonReader; + Json::Value schemaJson; + if (!jsonReader.parse(reinterpret_cast(schemaData.data()), reinterpret_cast(schemaData.data()) + schemaData.size(), schemaJson, false)) + { + throw std::runtime_error("Schema error: " + jsonReader.getFormattedErrorMessages()) ; + } + _schemaChecker.setSchema(schemaJson); + + // connect internal signals and slots connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed())); connect(_socket, SIGNAL(readyRead()), this, SLOT(readData())); } @@ -50,6 +74,19 @@ void JsonClientConnection::handleMessage(const std::string &message) return; } + if (!_schemaChecker.validate(messageRoot)) + { + const std::list & errors = _schemaChecker.getMessages(); + std::stringstream ss; + ss << "Error while validating json: {"; + foreach (const std::string & error, errors) { + ss << error << ", "; + } + ss << "}"; + sendErrorReply(ss.str()); + return; + } + handleNotImplemented(messageRoot); } diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h index b8c6f9a9..ee46e642 100644 --- a/libsrc/jsonserver/JsonClientConnection.h +++ b/libsrc/jsonserver/JsonClientConnection.h @@ -10,6 +10,9 @@ // jsoncpp includes #include +// util includes +#include + class JsonClientConnection : public QObject { Q_OBJECT @@ -35,5 +38,7 @@ private: private: QTcpSocket * _socket; + JsonSchemaChecker _schemaChecker; + QByteArray _receiveBuffer; }; diff --git a/libsrc/jsonserver/JsonServer.cpp b/libsrc/jsonserver/JsonServer.cpp index 9155499a..5b3e3c36 100644 --- a/libsrc/jsonserver/JsonServer.cpp +++ b/libsrc/jsonserver/JsonServer.cpp @@ -18,6 +18,9 @@ JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) : // Set trigger for incoming connections connect(&_server, SIGNAL(newConnection()), this, SLOT(newConnection())); + + // make sure the resources are loaded (they may be left out after static linking + Q_INIT_RESOURCE(resource); } JsonServer::~JsonServer() diff --git a/libsrc/jsonserver/resource.qrc b/libsrc/jsonserver/resource.qrc new file mode 100644 index 00000000..cb387153 --- /dev/null +++ b/libsrc/jsonserver/resource.qrc @@ -0,0 +1,5 @@ + + + schema.json + + diff --git a/libsrc/jsonserver/schema.json b/libsrc/jsonserver/schema.json new file mode 100644 index 00000000..3ad665f0 --- /dev/null +++ b/libsrc/jsonserver/schema.json @@ -0,0 +1,89 @@ +{ + "type":"object", + "required":true, + "properties":{ + "command": { + "type" : "string", + "required" : true, + "enum" : ["color", "image", "serverinfo", "clear", "clearall", "transform"] + }, + "priority": { + "type": "integer", + "required": false + }, + "duration": { + "type": "integer", + "required": false + }, + "color": { + "type": "array", + "required": false, + "items" :{ + "type" : "integer" + }, + "minItems": 3, + "maxItems": 3 + }, + "imagewidth": { + "type" : "integer", + "required": false, + "minimum": 0 + }, + "imageheight": { + "type" : "integer", + "required": false, + "minimum": 0 + }, + "imagedata": { + "type": "string", + "required": false + }, + "transform": { + "type": "object", + "required": false, + "properties": { + "threshold": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0, + "maximum": 1.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "gamma": { + "type": "array", + "required": false, + "items" : { + "type": "double", + "minimum": 0.0 + }, + "minItems": 3, + "maxItems": 3 + }, + "blacklevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + }, + "whitelevel": { + "type": "array", + "required": false, + "items" : { + "type": "double" + }, + "minItems": 3, + "maxItems": 3 + } + }, + "additionalProperties": false + } + }, + "additionalProperties": false +} diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp index 3f4b887d..c1aff4e2 100644 --- a/src/hyperion-remote/JsonConnection.cpp +++ b/src/hyperion-remote/JsonConnection.cpp @@ -87,9 +87,9 @@ void JsonConnection::setImage(QImage image, int priority, int duration) Json::Value command; command["command"] = "image"; command["priority"] = priority; - command["width"] = image.width(); - command["height"] = image.height(); - command["data"] = std::string(base64Image.data(), base64Image.size()); + command["imagewidth"] = image.width(); + command["imageheight"] = image.height(); + command["imagedata"] = std::string(base64Image.data(), base64Image.size()); if (duration > 0) { command["duration"] = duration;