JsonCpp to QTJson (Part 5) (#270)

* Update Hyperion.h

* Update ImageProcessorFactory.h

* Update ProtoConnection.h

* Update WebConfig.h

* Update CMakeLists.txt

* Update Hyperion.cpp

* Update CMakeLists.txt

* Update CMakeLists.txt

* Update CgiHandler.cpp

* Update CgiHandler.h

* Update WebConfig.cpp

* Update CMakeLists.txt

* Update hyperion-remote.cpp

* Update JsonConnection.cpp

* Update JsonConnection.h

* Update hyperiond.cpp

* Update hyperiond.h

* Delete JsonFactory.h

* Delete JsonSchemaChecker.h

* Delete JsonSchemaChecker.cpp

* Update WebConfig.cpp
This commit is contained in:
Paulchen Panther 2016-10-11 19:51:20 +02:00 committed by redPanther
parent 102fd611fa
commit ebbb6b9440
20 changed files with 223 additions and 899 deletions

View File

@ -74,7 +74,7 @@ public:
};
///
/// Destructor; cleans up resourcess
/// Destructor; cleans up resources
///
~Hyperion();
@ -128,7 +128,6 @@ public:
/// gets the current json config object
/// @return json config
const Json::Value& getJsonConfig() { return _jsonConfig; };
const QJsonObject& getQJsonConfig() { return _qjsonConfig; };
/// get filename of configfile
@ -149,7 +148,7 @@ public:
const PriorityRegister& getPriorityRegister() { return _priorityRegister; }
/// enable/disable automatic/priorized source selection
/// @param enable the state
/// @param enabled the state
void setSourceAutoSelectEnabled(bool enabled);
/// set current input source to visible
@ -244,14 +243,14 @@ public slots:
/// Run the specified effect on the given priority channel and optionally specify a timeout
/// @param effectName Name of the effec to run
/// @param priority The priority channel of the effect
/// @param timout The timeout of the effect (after the timout, the effect will be cleared)
/// @param timeout The timeout of the effect (after the timout, the effect will be cleared)
int setEffect(const QString & effectName, int priority, int timeout = -1);
/// Run the specified effect on the given priority channel and optionally specify a timeout
/// @param effectName Name of the effec to run
/// @param args arguments of the effect script
/// @param priority The priority channel of the effect
/// @param timout The timeout of the effect (after the timout, the effect will be cleared)
/// @param timeout The timeout of the effect (after the timout, the effect will be cleared)
int setEffect(const QString & effectName, const QJsonObject & args, int priority, int timeout = -1);
public:

View File

@ -6,14 +6,6 @@
// QT includes
#include <QJsonObject>
// if (jsoncpp_converted_to_QtJSON)
// {
// remove("#include <json/json.h>");
// }
// Jsoncpp includes
#include <json/json.h>
#include <hyperion/LedString.h>
// Forward class declaration
@ -38,8 +30,7 @@ public:
/// Initialises this factory with the given led-configuration
///
/// @param[in] ledString The led configuration
/// @param[in] enableBlackBorderDetector Flag indicating if the blacborder detector should be enabled
/// @param[in] blackborderThreshold The threshold which the blackborder detector should use
/// @param[in] blackborderConfig Contains the blackborder configuration
///
void init(const LedString& ledString, const QJsonObject &blackborderConfig);

View File

@ -17,7 +17,6 @@
#include <utils/VideoMode.h>
#include <utils/Logger.h>
// jsoncpp includes
#include <message.pb.h>
///

View File

@ -1,74 +0,0 @@
#pragma once
#include <string>
#include <istream>
#include <fstream>
#include <stdexcept>
#include <sstream>
// JSON-Schema includes
#include <utils/jsonschema/JsonSchemaChecker.h>
class JsonFactory
{
public:
static int load(const std::string& schema, const std::istream& config, Json::Value json);
static int load(const std::string& schema, const std::string& config, Json::Value& json)
{
// Load the schema and the config trees
Json::Value schemaTree = readJson(schema);
Json::Value configTree = readJson(config);
// create the validator
JsonSchemaChecker schemaChecker;
schemaChecker.setSchema(schemaTree);
bool valid = schemaChecker.validate(configTree);
for (const std::string& message : schemaChecker.getMessages())
{
std::cout << message << std::endl;
}
if (!valid)
{
std::cerr << "Validation failed for configuration file: " << config.c_str() << std::endl;
return -3;
}
json = configTree;
return 0;
}
static Json::Value readJson(const std::string& filename)
{
// Open the file input stream
std::ifstream ifs(filename.c_str());
return readJson(ifs);
}
static Json::Value readJson(std::istream& stream)
{
// will contains the root value after parsing.
Json::Value jsonTree;
Json::Reader reader;
if (! reader.parse(stream, jsonTree, false))
{
// report to the user the failure and their locations in the document.
std::stringstream sstream;
sstream << "Failed to parse configuration: " << reader.getFormattedErrorMessages().c_str();
throw std::runtime_error(sstream.str());
}
return jsonTree;
}
static void writeJson(const std::string& filename, Json::Value& jsonTree)
{
Json::StyledStreamWriter writer;
std::ofstream ofs(filename.c_str());
writer.write(ofs, jsonTree);
}
};

View File

@ -1,194 +0,0 @@
#pragma once
// stl includes
#include <string>
#include <list>
// jsoncpp includes
#include <json/json.h>
/// JsonSchemaChecker is a very basic implementation of json schema.
/// The json schema definition draft can be found at
/// http://tools.ietf.org/html/draft-zyp-json-schema-03
///
/// The following keywords are supported:
/// - type
/// - required
/// - properties
/// - items
/// - enum
/// - minimum
/// - maximum
/// - addtionalProperties
/// - minItems
/// - maxItems
///
/// And the non-standard:
/// - dependencies
class JsonSchemaChecker
{
public:
JsonSchemaChecker();
virtual ~JsonSchemaChecker();
///
/// @param schema The schema to use
/// @return true upon succes
///
bool setSchema(const Json::Value & schema);
///
/// @brief Validate a JSON structure
/// @param value The JSON value to check
/// @return true when the arguments is valid according to the schema
///
bool validate(const Json::Value & value, bool ignoreRequired = false);
///
/// @return A list of error messages
///
const std::list<std::string> & getMessages() const;
private:
///
/// Validates a json-value against a given schema. Results are stored in the members of this
/// class (_error & _messages)
///
/// @param[in] value The value to validate
/// @param[in] schema The schema against which the value is validated
///
void validate(const Json::Value &value, const Json::Value & schema);
///
/// Adds the given message to the message-queue (with reference to current line-number)
///
/// @param[in] message The message to add to the queue
///
void setMessage(const std::string & message);
///
/// Retrieves all references from the json-value as specified by the schema
///
/// @param[in] value The json-value
/// @param[in] schema The schema
///
void collectDependencies(const Json::Value & value, const Json::Value &schema);
private:
// attribute check functions
///
/// Checks if the given value is of the specified type. If the type does not match _error is set
/// to true and an error-message is added to the message-queue
///
/// @param[in] value The given value
/// @param[in] schema The specified type (as json-value)
///
void checkType(const Json::Value & value, const Json::Value & schema);
///
/// Checks is required properties of an json-object exist and if all properties are of the
/// correct format. If this is not the case _error is set to true and an error-message is added
/// to the message-queue.
///
/// @param[in] value The given json-object
/// @param[in] schema The schema of the json-object
///
void checkProperties(const Json::Value & value, const Json::Value & schema);
///
/// Verifies the additional configured properties of an json-object. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param value The given json-object
/// @param schema The schema for the json-object
/// @param ignoredProperties The properties that were ignored
///
void checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties);
///
/// Checks if references are configued and used correctly. If this is not the case _error is set
/// to true and an error-message is added to the message-queue.
///
/// @param value The given json-object
/// @param schemaLink The schema of the json-object
///
void checkDependencies(const Json::Value & value, const Json::Value & schemaLink);
///
/// Checks if the given value is larger or equal to the specified value. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param[in] value The given value
/// @param[in] schema The minimum value (as json-value)
///
void checkMinimum(const Json::Value & value, const Json::Value & schema);
///
/// Checks if the given value is smaller or equal to the specified value. If this is not the
/// case _error is set to true and an error-message is added to the message-queue.
///
/// @param[in] value The given value
/// @param[in] schema The maximum value (as json-value)
///
void checkMaximum(const Json::Value & value, const Json::Value & schema);
///
/// Validates all the items of an array.
///
/// @param value The json-array
/// @param schema The schema for the items in the array
///
void checkItems(const Json::Value & value, const Json::Value & schema);
///
/// Checks if a given array has at least a minimum number of items. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param value The json-array
/// @param schema The minimum size specification (as json-value)
///
void checkMinItems(const Json::Value & value, const Json::Value & schema);
///
/// Checks if a given array has at most a maximum number of items. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param value The json-array
/// @param schema The maximum size specification (as json-value)
///
void checkMaxItems(const Json::Value & value, const Json::Value & schema);
///
/// Checks if a given array contains only unique items. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param value The json-array
/// @param schema Bool to enable the check (as json-value)
///
void checkUniqueItems(const Json::Value & value, const Json::Value & schema);
///
/// Checks if an enum value is actually a valid value for that enum. If this is not the case
/// _error is set to true and an error-message is added to the message-queue.
///
/// @param value The enum value
/// @param schema The enum schema definition
///
void checkEnum(const Json::Value & value, const Json::Value & schema);
private:
/// The schema of the entire json-configuration
Json::Value _schema;
/// ignore the required value in json schema
bool _ignoreRequired;
/// The current location into a json-configuration structure being checked
std::list<std::string> _currentPath;
/// The result messages collected during the schema verification
std::list<std::string> _messages;
/// Flag indicating an error occured during validation
bool _error;
/// A list with references (string => json-value)
std::map<std::string, const Json::Value *> _references; // ref 2 value
};

View File

@ -4,7 +4,6 @@
#include <QObject>
#include <QString>
#include <string>
#include <utils/jsonschema/JsonFactory.h>
#include <hyperion/Hyperion.h>
class StaticFileServing;

View File

@ -52,6 +52,5 @@ qt5_use_modules(effectengine Core Gui)
target_link_libraries(effectengine
hyperion
jsoncpp
${QT_LIBRARIES}
${PYTHON_LIBRARIES})

View File

@ -13,9 +13,6 @@
#include <QCryptographicHash>
#include <QFile>
// JsonSchema include
#include <utils/jsonschema/JsonFactory.h>
// hyperion include
#include <hyperion/Hyperion.h>
#include <hyperion/ImageProcessorFactory.h>

View File

@ -38,5 +38,4 @@ qt5_use_modules(jsonserver Network)
target_link_libraries(jsonserver
hyperion
hyperion-utils
jsoncpp
${QT_LIBRARIES})

View File

@ -46,10 +46,6 @@ add_library(hyperion-utils
${CURRENT_HEADER_DIR}/RgbToRgbw.h
${CURRENT_SOURCE_DIR}/RgbToRgbw.cpp
${CURRENT_HEADER_DIR}/jsonschema/JsonFactory.h
${CURRENT_HEADER_DIR}/jsonschema/JsonSchemaChecker.h
${CURRENT_SOURCE_DIR}/jsonschema/JsonSchemaChecker.cpp
${CURRENT_HEADER_DIR}/jsonschema/QJsonFactory.h
${CURRENT_HEADER_DIR}/jsonschema/QJsonSchemaChecker.h
${CURRENT_SOURCE_DIR}/jsonschema/QJsonSchemaChecker.cpp

View File

@ -1,465 +0,0 @@
// stdlib includes
#include <cassert>
#include <iterator>
#include <sstream>
#include <algorithm>
// Utils-Jsonschema includes
#include <utils/jsonschema/JsonSchemaChecker.h>
JsonSchemaChecker::JsonSchemaChecker()
{
// empty
}
JsonSchemaChecker::~JsonSchemaChecker()
{
// empty
}
bool JsonSchemaChecker::setSchema(const Json::Value & schema)
{
_schema = schema;
// TODO: check the schema
return true;
}
bool JsonSchemaChecker::validate(const Json::Value & value, bool ignoreRequired)
{
// initialize state
_ignoreRequired = ignoreRequired;
_error = false;
_messages.clear();
_currentPath.clear();
_currentPath.push_back("[root]");
_references.clear();
// collect dependencies
collectDependencies(value, _schema);
// validate
validate(value, _schema);
return !_error;
}
void JsonSchemaChecker::collectDependencies(const Json::Value & value, const Json::Value &schema)
{
assert (schema.isObject());
// check if id is present
if (schema.isMember("id"))
{
// strore reference
assert (schema["id"].isString());
std::ostringstream ref;
ref << "$(" << schema["id"].asString() << ")";
_references[ref.str()] = &value;
}
// check the current json value
if (schema.isMember("properties"))
{
const Json::Value & properties = schema["properties"];
assert(properties.isObject());
for (Json::Value::const_iterator j = properties.begin(); j != properties.end(); ++j)
{
std::string property = j.memberName();
if (value.isMember(property))
{
collectDependencies(value[property], properties[property]);
}
}
}
}
void JsonSchemaChecker::validate(const Json::Value & value, const Json::Value &schema)
{
assert (schema.isObject());
// check the current json value
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
{
std::string attribute = i.memberName();
const Json::Value & attributeValue = *i;
if (attribute == "type")
checkType(value, attributeValue);
else if (attribute == "properties")
checkProperties(value, attributeValue);
else if (attribute == "additionalProperties")
{
// ignore the properties which are handled by the properties attribute (if present)
Json::Value::Members ignoredProperties;
if (schema.isMember("properties")) {
const Json::Value & props = schema["properties"];
ignoredProperties = props.getMemberNames();
}
checkAdditionalProperties(value, attributeValue, ignoredProperties);
}
else if (attribute == "dependencies")
checkDependencies(value, attributeValue);
else if (attribute == "minimum")
checkMinimum(value, attributeValue);
else if (attribute == "maximum")
checkMaximum(value, attributeValue);
else if (attribute == "items")
checkItems(value, attributeValue);
else if (attribute == "minItems")
checkMinItems(value, attributeValue);
else if (attribute == "maxItems")
checkMaxItems(value, attributeValue);
else if (attribute == "uniqueItems")
checkUniqueItems(value, attributeValue);
else if (attribute == "enum")
checkEnum(value, attributeValue);
else if (attribute == "required")
; // nothing to do. value is present so always oke
else if (attribute == "id")
; // references have already been collected
else
{
// no check function defined for this attribute
setMessage(std::string("No check function defined for attribute ") + attribute);
continue;
}
}
}
void JsonSchemaChecker::setMessage(const std::string & message)
{
std::ostringstream oss;
std::copy(_currentPath.begin(), _currentPath.end(), std::ostream_iterator<std::string>(oss, ""));
oss << ": " << message;
_messages.push_back(oss.str());
}
const std::list<std::string> & JsonSchemaChecker::getMessages() const
{
return _messages;
}
void JsonSchemaChecker::checkType(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isString());
std::string type = schema.asString();
bool wrongType = false;
if (type == "string")
wrongType = !value.isString();
else if (type == "number")
wrongType = !value.isNumeric();
else if (type == "integer")
wrongType = !value.isIntegral();
else if (type == "double")
wrongType = !value.isDouble();
else if (type == "boolean")
wrongType = !value.isBool();
else if (type == "object")
wrongType = !value.isObject();
else if (type == "array")
wrongType = !value.isArray();
else if (type == "null")
wrongType = !value.isNull();
else if (type == "enum")
wrongType = !value.isString();
else if (type == "any")
wrongType = false;
// else
// assert(false);
if (wrongType)
{
_error = true;
setMessage(type + " expected");
}
}
void JsonSchemaChecker::checkProperties(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isObject());
if (!value.isObject())
{
_error = true;
setMessage("properies attribute is only valid for objects");
return;
}
for (Json::Value::const_iterator i = schema.begin(); i != schema.end(); ++i)
{
std::string property = i.memberName();
const Json::Value & propertyValue = *i;
assert(propertyValue.isObject());
_currentPath.push_back(std::string(".") + property);
if (value.isMember(property))
{
validate(value[property], propertyValue);
}
else if (propertyValue.get("required", false).asBool() && !_ignoreRequired)
{
_error = true;
setMessage("missing member");
}
_currentPath.pop_back();
}
}
void JsonSchemaChecker::checkAdditionalProperties(const Json::Value & value, const Json::Value & schema, const Json::Value::Members & ignoredProperties)
{
if (!value.isObject())
{
_error = true;
setMessage("additional properies attribute is only valid for objects");
return;
}
for (Json::Value::const_iterator i = value.begin(); i != value.end(); ++i)
{
std::string property = i.memberName();
if (std::find(ignoredProperties.begin(), ignoredProperties.end(), property) == ignoredProperties.end())
{
// property has no property definition. check against the definition for additional properties
_currentPath.push_back(std::string(".") + property);
if (schema.isBool())
{
if (schema.asBool() == false)
{
_error = true;
setMessage("no schema definition");
}
}
else
{
validate(value[property], schema);
}
_currentPath.pop_back();
}
}
}
void JsonSchemaChecker::checkDependencies(const Json::Value & value, const Json::Value & schemaLink)
{
if (!value.isObject())
{
_error = true;
setMessage("dependencies attribute is only valid for objects");
return;
}
assert(schemaLink.isString());
std::map<std::string, const Json::Value *>::iterator iter = _references.find(schemaLink.asString());
if (iter == _references.end())
{
_error = true;
std::ostringstream oss;
oss << "reference " << schemaLink.asString() << " could not be resolved";
setMessage(oss.str());
return;
}
const Json::Value & schema = *(iter->second);
std::list<std::string> requiredProperties;
if (schema.isString())
{
requiredProperties.push_back(schema.asString());
}
else if (schema.isArray())
{
for (Json::UInt i = 0; i < schema.size(); ++i)
{
assert(schema[i].isString());
requiredProperties.push_back(schema[i].asString());
}
}
else
{
_error = true;
std::ostringstream oss;
oss << "Exepected reference " << schemaLink.asString() << " to resolve to a string or array";
setMessage(oss.str());
return;
}
for (std::list<std::string>::const_iterator i = requiredProperties.begin(); i != requiredProperties.end(); ++i)
{
if (!value.isMember(*i))
{
_error = true;
std::ostringstream oss;
oss << "missing member " << *i;
setMessage(oss.str());
}
}
}
void JsonSchemaChecker::checkMinimum(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isNumeric());
if (!value.isNumeric())
{
// only for numeric
_error = true;
setMessage("minimum check only for numeric fields");
return;
}
if (value.asDouble() < schema.asDouble())
{
_error = true;
std::ostringstream oss;
oss << "value is too small (minimum=" << schema.asDouble() << ")";
setMessage(oss.str());
}
}
void JsonSchemaChecker::checkMaximum(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isNumeric());
if (!value.isNumeric())
{
// only for numeric
_error = true;
setMessage("maximum check only for numeric fields");
return;
}
if (value.asDouble() > schema.asDouble())
{
_error = true;
std::ostringstream oss;
oss << "value is too large (maximum=" << schema.asDouble() << ")";
setMessage(oss.str());
}
}
void JsonSchemaChecker::checkItems(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isObject());
if (!value.isArray())
{
// only for arrays
_error = true;
setMessage("items only valid for arrays");
return;
}
for(Json::ArrayIndex i = 0; i < value.size(); ++i)
{
// validate each item
std::ostringstream oss;
oss << "[" << i << "]";
_currentPath.push_back(oss.str());
validate(value[i], schema);
_currentPath.pop_back();
}
}
void JsonSchemaChecker::checkMinItems(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isIntegral());
if (!value.isArray())
{
// only for arrays
_error = true;
setMessage("minItems only valid for arrays");
return;
}
int minimum = schema.asInt();
if (static_cast<int>(value.size()) < minimum)
{
_error = true;
std::ostringstream oss;
oss << "array is too small (minimum=" << minimum << ")";
setMessage(oss.str());
}
}
void JsonSchemaChecker::checkMaxItems(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isIntegral());
if (!value.isArray())
{
// only for arrays
_error = true;
setMessage("maxItems only valid for arrays");
return;
}
int maximum = schema.asInt();
if (static_cast<int>(value.size()) > maximum)
{
_error = true;
std::ostringstream oss;
oss << "array is too large (maximum=" << maximum << ")";
setMessage(oss.str());
}
}
void JsonSchemaChecker::checkUniqueItems(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isBool());
if (!value.isArray())
{
// only for arrays
_error = true;
setMessage("uniqueItems only valid for arrays");
return;
}
if (schema.asBool() == true)
{
// make sure no two items are identical
for(Json::UInt i = 0; i < value.size(); ++i)
{
for (Json::UInt j = i+1; j < value.size(); ++j)
{
if (value[i] == value[j])
{
// found a value twice
_error = true;
setMessage("array must have unique values");
}
}
}
}
}
void JsonSchemaChecker::checkEnum(const Json::Value & value, const Json::Value & schema)
{
assert(schema.isArray());
for(Json::ArrayIndex i = 0; i < schema.size(); ++i)
{
if (schema[i] == value)
{
// found enum value. done.
return;
}
}
// nothing found
_error = true;
std::ostringstream oss;
oss << "Unknown enum value (allowed values are: ";
std::string values = Json::FastWriter().write(schema);
oss << values.substr(0, values.size()-1); // The writer append a new line which we don't want
oss << ")";
setMessage(oss.str());
}

View File

@ -11,7 +11,7 @@
CgiHandler::CgiHandler (Hyperion * hyperion, QString baseUrl, QObject * parent)
: QObject(parent)
, _hyperion(hyperion)
, _hyperionConfig(_hyperion->getJsonConfig())
, _hyperionConfig(_hyperion->getQJsonConfig())
, _baseUrl(baseUrl)
{
}
@ -44,10 +44,10 @@ void CgiHandler::cmd_cfg_jsonserver(const QStringList & args, QtHttpReply * repl
if ( args.at(0) == "cfg_jsonserver" )
{
quint16 jsonPort = 19444;
if (_hyperionConfig.isMember("jsonServer"))
if (_hyperionConfig.contains("jsonServer"))
{
const Json::Value & jsonConfig = _hyperionConfig["jsonServer"];
jsonPort = jsonConfig.get("port", jsonPort).asUInt();
const QJsonObject jsonConfig = _hyperionConfig["jsonServer"].toObject();
jsonPort = jsonConfig["port"].toInt(jsonPort);
}
// send result as reply

View File

@ -5,7 +5,6 @@
#include <QString>
#include <QStringList>
#include <utils/jsonschema/JsonFactory.h>
#include <hyperion/Hyperion.h>
#include "QtHttpReply.h"
@ -28,7 +27,7 @@ public:
private:
Hyperion* _hyperion;
QtHttpReply * _reply;
const Json::Value &_hyperionConfig;
const QJsonObject &_hyperionConfig;
const QString _baseUrl;
};

View File

@ -11,16 +11,16 @@ WebConfig::WebConfig(QObject * parent)
Logger* log = Logger::getInstance("WEBSERVER");
_port = WEBCONFIG_DEFAULT_PORT;
_baseUrl = WEBCONFIG_DEFAULT_PATH;
const Json::Value &config = _hyperion->getJsonConfig();
const QJsonObject config = _hyperion->getQJsonConfig();
bool webconfigEnable = true;
if (config.isMember("webConfig"))
if (config.contains("webConfig"))
{
const Json::Value & webconfigConfig = config["webConfig"];
webconfigEnable = webconfigConfig.get("enable", true).asBool();
_port = webconfigConfig.get("port", _port).asUInt();
_baseUrl = QString::fromStdString( webconfigConfig.get("document_root", _baseUrl.toStdString()).asString() );
const QJsonObject webconfigConfig = config["webConfig"].toObject();
webconfigEnable = webconfigConfig["enable"].toBool(true);
_port = webconfigConfig["port"].toInt(_port);
_baseUrl = webconfigConfig["document_root"].toString(_baseUrl);
}
if (_baseUrl != ":/webconfig")

View File

@ -28,7 +28,6 @@ add_executable(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
effectengine
commandline
jsoncpp
${QT_LIBRARIES})
qt5_use_modules(${PROJECT_NAME} Gui Core Network)

View File

@ -1,9 +1,14 @@
// stl includes
#include <stdexcept>
#include <cassert>
#include <sstream>
#include <iostream>
// Qt includes
#include <QRgb>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
// hyperion-remote includes
#include "JsonConnection.h"
@ -41,26 +46,28 @@ JsonConnection::~JsonConnection()
void JsonConnection::setColor(std::vector<QColor> colors, int priority, int duration)
{
std::cout << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "") << std::endl;
qDebug() << "Set color to " << colors[0].red() << " " << colors[0].green() << " " << colors[0].blue() << (colors.size() > 1 ? " + ..." : "");
// create command
Json::Value command;
command["command"] = "color";
QJsonObject command;
command["command"] = QString("color");
command["priority"] = priority;
Json::Value & rgbValue = command["color"];
QJsonArray rgbValue;
for (const QColor & color : colors)
{
rgbValue.append(color.red());
rgbValue.append(color.green());
rgbValue.append(color.blue());
}
command["color"] = rgbValue;
if (duration > 0)
{
command["duration"] = duration;
}
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -68,7 +75,7 @@ void JsonConnection::setColor(std::vector<QColor> colors, int priority, int dura
void JsonConnection::setImage(QImage &image, int priority, int duration)
{
std::cout << "Set image has size: " << image.width() << "x" << image.height() << std::endl;
qDebug() << "Set image has size: " << image.width() << "x" << image.height();
// ensure the image has RGB888 format
image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
@ -87,19 +94,19 @@ void JsonConnection::setImage(QImage &image, int priority, int duration)
const QByteArray base64Image = binaryImage.toBase64();
// create command
Json::Value command;
command["command"] = "image";
QJsonObject command;
command["command"] = QString("image");
command["priority"] = priority;
command["imagewidth"] = image.width();
command["imageheight"] = image.height();
command["imagedata"] = base64Image.data();
command["imagedata"] = QString(base64Image.data());
if (duration > 0)
{
command["duration"] = duration;
}
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -110,26 +117,47 @@ void JsonConnection::setEffect(const QString &effectName, const QString & effect
qDebug() << "Start effect " << effectName;
// create command
Json::Value command;
command["command"] = "effect";
QJsonObject command, effect;
command["command"] = QString("effect");
command["priority"] = priority;
Json::Value & effect = command["effect"];
effect["name"] = effectName.toStdString();
effect["name"] = effectName;
if (effectArgs.size() > 0)
{
Json::Reader reader;
if (!reader.parse(effectArgs.toStdString(), effect["args"], false))
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(effectArgs.toUtf8() ,&error);
if (error.error != QJsonParseError::NoError)
{
throw std::runtime_error("Error in effect arguments: " + reader.getFormattedErrorMessages());
// report to the user the failure and their locations in the document.
int errorLine(0), errorColumn(0);
for( int i=0, count=qMin( error.offset,effectArgs.size()); i<count; ++i )
{
++errorColumn;
if(effectArgs.at(i) == '\n' )
{
errorColumn = 0;
++errorLine;
}
}
std::stringstream sstream;
sstream << "Error in effect arguments: " << error.errorString().toStdString() << " at Line: " << errorLine << ", Column: " << errorColumn;
throw std::runtime_error(sstream.str());
}
effect["args"] = doc.object();
command["effect"] = effect;
}
if (duration > 0)
{
command["duration"] = duration;
}
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -137,25 +165,26 @@ void JsonConnection::setEffect(const QString &effectName, const QString & effect
QString JsonConnection::getServerInfo()
{
std::cout << "Get server info" << std::endl;
qDebug() << "Get server info";
// create command
Json::Value command;
command["command"] = "serverinfo";
QJsonObject command;
command["command"] = QString("serverinfo");
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
if (parseReply(reply))
{
if (!reply.isMember("info") || !reply["info"].isObject())
if (!reply.contains("info") || !reply["info"].isObject())
{
throw std::runtime_error("No info available in result");
}
const Json::Value & info = reply["info"];
return QString(info.toStyledString().c_str());
QJsonDocument doc(reply["info"].toObject());
QString info(doc.toJson(QJsonDocument::Indented));
return info;
}
return QString();
@ -163,15 +192,15 @@ QString JsonConnection::getServerInfo()
void JsonConnection::clear(int priority)
{
std::cout << "Clear priority channel " << priority << std::endl;
qDebug() << "Clear priority channel " << priority;
// create command
Json::Value command;
command["command"] = "clear";
QJsonObject command;
command["command"] = QString("clear");
command["priority"] = priority;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -179,14 +208,14 @@ void JsonConnection::clear(int priority)
void JsonConnection::clearAll()
{
std::cout << "Clear all priority channels" << std::endl;
qDebug() << "Clear all priority channels";
// create command
Json::Value command;
command["command"] = "clearall";
QJsonObject command;
command["command"] = QString("clearall");
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -197,14 +226,14 @@ void JsonConnection::setComponentState(const QString & component, const bool sta
qDebug() << (state ? "Enable" : "Disable") << "Component" << component;
// create command
Json::Value command;
command["command"] = "componentstate";
Json::Value & parameter = command["componentstate"];
parameter["component"] = component.toStdString();
QJsonObject command, parameter;
command["command"] = QString("componentstate");
parameter["component"] = component;
parameter["state"] = state;
command["componentstate"] = parameter;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -213,12 +242,12 @@ void JsonConnection::setComponentState(const QString & component, const bool sta
void JsonConnection::setSource(int priority)
{
// create command
Json::Value command;
command["command"] = "sourceselect";
QJsonObject command;
command["command"] = QString("sourceselect");
command["priority"] = priority;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -227,12 +256,12 @@ void JsonConnection::setSource(int priority)
void JsonConnection::setSourceAutoSelect()
{
// create command
Json::Value command;
command["command"] = "sourceselect";
QJsonObject command;
command["command"] = QString("sourceselect");
command["auto"] = true;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -241,26 +270,27 @@ void JsonConnection::setSourceAutoSelect()
QString JsonConnection::getConfig(std::string type)
{
assert( type == "schema" || type == "config" );
std::cout << "Get configuration file from Hyperion Server" << std::endl;
qDebug() << "Get configuration file from Hyperion Server";
// create command
Json::Value command;
command["command"] = "config";
command["subcommand"] = (type == "schema")? "getschema" : "getconfig";
QJsonObject command;
command["command"] = QString("config");
command["subcommand"] = (type == "schema") ? QString("getschema") : QString("getconfig");
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
if (parseReply(reply))
{
if (!reply.isMember("result") || !reply["result"].isObject())
if (!reply.contains("result") || !reply["result"].isObject())
{
throw std::runtime_error("No configuration file available in result");
}
const Json::Value & config = reply["result"];
return QString(config.toStyledString().c_str());
QJsonDocument doc(reply["result"].toObject());
QString result(doc.toJson(QJsonDocument::Indented));
return result;
}
return QString();
@ -269,22 +299,41 @@ QString JsonConnection::getConfig(std::string type)
void JsonConnection::setConfig(const QString &jsonString)
{
// create command
Json::Value command;
command["command"] = "config";
command["subcommand"] = "setconfig";
QJsonObject command;
command["command"] = QString("config");
command["subcommand"] = QString("setconfig");
Json::Value & config = command["config"];
if (jsonString.size() > 0)
{
Json::Reader reader;
if (!reader.parse(jsonString.toStdString(), config, false))
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8() ,&error);
if (error.error != QJsonParseError::NoError)
{
throw std::runtime_error("Error in configset arguments: " + reader.getFormattedErrorMessages());
// report to the user the failure and their locations in the document.
int errorLine(0), errorColumn(0);
for( int i=0, count=qMin( error.offset,jsonString.size()); i<count; ++i )
{
++errorColumn;
if(jsonString.at(i) == '\n' )
{
errorColumn = 0;
++errorLine;
}
}
std::stringstream sstream;
sstream << "Error in configset arguments: " << error.errorString().toStdString() << " at Line: " << errorLine << ", Column: " << errorColumn;
throw std::runtime_error(sstream.str());
}
command["config"] = doc.object();
}
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -301,16 +350,15 @@ void JsonConnection::setTransform(const QString &transformId,
QColor blacklevel,
QColor whitelevel)
{
std::cout << "Set color transforms" << std::endl;
qDebug() << "Set color transforms";
// create command
Json::Value command;
command["command"] = "transform";
Json::Value & transform = command["transform"];
QJsonObject command, transform;
command["command"] = QString("transform");
if (!transformId.isNull())
{
transform["id"] = transformId.toStdString();
transform["id"] = transformId;
}
if (saturation != nullptr)
@ -340,38 +388,44 @@ void JsonConnection::setTransform(const QString &transformId,
if (threshold.isValid())
{
Json::Value & v = transform["threshold"];
v.append(threshold.red());
v.append(threshold.green());
v.append(threshold.blue());
QJsonArray t;
t.append(threshold.red());
t.append(threshold.green());
t.append(threshold.blue());
transform["threshold"] = t;
}
if (gamma.isValid())
{
Json::Value & v = transform["gamma"];
v.append(gamma.red());
v.append(gamma.green());
v.append(gamma.blue());
QJsonArray g;
g.append(gamma.red());
g.append(gamma.green());
g.append(gamma.blue());
transform["gamma"] = g;
}
if (blacklevel.isValid())
{
Json::Value & v = transform["blacklevel"];
v.append(blacklevel.red());
v.append(blacklevel.green());
v.append(blacklevel.blue());
QJsonArray b;
b.append(blacklevel.red());
b.append(blacklevel.green());
b.append(blacklevel.blue());
transform["blacklevel"] = b;
}
if (whitelevel.isValid())
{
Json::Value & v = transform["whitelevel"];
v.append(whitelevel.red());
v.append(whitelevel.green());
v.append(whitelevel.blue());
QJsonArray w;
w.append(whitelevel.red());
w.append(whitelevel.green());
w.append(whitelevel.blue());
transform["whitelevel"] = w;
}
command["transform"] = transform;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
@ -382,62 +436,67 @@ void JsonConnection::setAdjustment(const QString &adjustmentId,
const QColor & greenAdjustment,
const QColor & blueAdjustment)
{
std::cout << "Set color adjustments" << std::endl;
qDebug() << "Set color adjustments";
// create command
Json::Value command;
command["command"] = "adjustment";
Json::Value & adjust = command["adjustment"];
QJsonObject command, adjust;
command["command"] = QString("adjustment");
if (!adjustmentId.isNull())
{
adjust["id"] = adjustmentId.toStdString();
adjust["id"] = adjustmentId;
}
if (redAdjustment.isValid())
{
Json::Value & v = adjust["redAdjust"];
v.append(redAdjustment.red());
v.append(redAdjustment.green());
v.append(redAdjustment.blue());
QJsonArray red;
red.append(redAdjustment.red());
red.append(redAdjustment.green());
red.append(redAdjustment.blue());
adjust["redAdjust"] = red;
}
if (greenAdjustment.isValid())
{
Json::Value & v = adjust["greenAdjust"];
v.append(greenAdjustment.red());
v.append(greenAdjustment.green());
v.append(greenAdjustment.blue());
QJsonArray green;
green.append(greenAdjustment.red());
green.append(greenAdjustment.green());
green.append(greenAdjustment.blue());
adjust["greenAdjust"] = green;
}
if (blueAdjustment.isValid())
{
Json::Value & v = adjust["blueAdjust"];
v.append(blueAdjustment.red());
v.append(blueAdjustment.green());
v.append(blueAdjustment.blue());
QJsonArray blue;
blue.append(blueAdjustment.red());
blue.append(blueAdjustment.green());
blue.append(blueAdjustment.blue());
adjust["blueAdjust"] = blue;
}
command["adjustment"] = adjust;
// send command message
Json::Value reply = sendMessage(command);
QJsonObject reply = sendMessage(command);
// parse reply message
parseReply(reply);
}
Json::Value JsonConnection::sendMessage(const Json::Value & message)
QJsonObject JsonConnection::sendMessage(const QJsonObject & message)
{
// serialize message (FastWriter already appends a newline)
std::string serializedMessage = Json::FastWriter().write(message);
// serialize message
QJsonDocument writer(message);
QByteArray serializedMessage = writer.toJson(QJsonDocument::Compact) + "\n";
// print command if requested
if (_printJson)
{
std::cout << "Command: " << serializedMessage;
std::cout << "Command: " << serializedMessage.constData();
}
// write message
_socket.write(serializedMessage.c_str());
_socket.write(serializedMessage);
if (!_socket.waitForBytesWritten())
{
throw std::runtime_error("Error while writing data to host");
@ -464,26 +523,26 @@ Json::Value JsonConnection::sendMessage(const Json::Value & message)
}
// parse reply data
Json::Reader jsonReader;
Json::Value reply;
if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
QJsonParseError error;
QJsonDocument reply = QJsonDocument::fromJson(serializedReply ,&error);
if (error.error != QJsonParseError::NoError)
{
throw std::runtime_error("Error while parsing reply: invalid json");
}
return reply;
return reply.object();
}
bool JsonConnection::parseReply(const Json::Value &reply)
bool JsonConnection::parseReply(const QJsonObject &reply)
{
bool success = false;
std::string reason = "No error info";
QString reason = "No error info";
try
{
success = reply.get("success", false).asBool();
success = reply["success"].toBool(false);
if (!success)
reason = reply.get("error", reason).asString();
reason = reply["error"].toString(reason);
}
catch (const std::runtime_error &)
{
@ -492,7 +551,7 @@ bool JsonConnection::parseReply(const Json::Value &reply)
if (!success)
{
throw std::runtime_error("Error: " + reason);
throw std::runtime_error("Error: " + reason.toStdString());
}
return success;

View File

@ -7,12 +7,7 @@
#include <QColor>
#include <QImage>
#include <QTcpSocket>
#include <QMap>
// jsoncpp includes
#include <json/json.h>
// hyperion-remote includes
#include <QJsonObject>
///
/// Connection class to setup an connection to the hyperion server and execute commands
@ -54,7 +49,7 @@ public:
///
/// Start the given effect
///
/// @param effect The name of the effect
/// @param effectName The name of the effect
/// @param effectArgs The arguments to use instead of the default ones
/// @param priority The priority
/// @param duration The duration in milliseconds
@ -164,7 +159,7 @@ private:
///
/// @return The returned reply
///
Json::Value sendMessage(const Json::Value & message);
QJsonObject sendMessage(const QJsonObject & message);
///
/// Parse a reply message
@ -173,7 +168,7 @@ private:
///
/// @return true if the reply indicates success
///
bool parseReply(const Json::Value & reply);
bool parseReply(const QJsonObject & reply);
private:
/// Flag for printing all send and received json-messages to the standard out

View File

@ -2,6 +2,7 @@
#include <clocale>
#include <initializer_list>
#include <limits>
#include <iostream>
// Qt includes
#include <QCoreApplication>

View File

@ -17,7 +17,6 @@
#include "HyperionConfig.h"
#include <utils/jsonschema/JsonFactory.h> // DEPRECATED | Remove this only when the conversion have been completed from JsonCpp to QTJson
#include <utils/jsonschema/QJsonFactory.h>
#include <utils/Components.h>
@ -163,7 +162,24 @@ void HyperionDaemon::loadConfig(const QString & configFile)
QJsonSchemaChecker schemaChecker;
schemaChecker.setSchema(schemaJson.object());
_config = JsonFactory::readJson(configFile.toStdString()); // DEPRECATED | Remove this only when the conversion have been completed from JsonCpp to QTJson
// ----------------- DEPRECATED BEGIN -----------------
// NOTE: Remove this code block when the conversion have been completed from JsonCpp to QTJson
std::ifstream ifs(configFile.toStdString().c_str());
Json::Reader reader;
if (! reader.parse(ifs, _config, false))
{
// report to the user the failure and their locations in the document.
std::stringstream sstream;
sstream << "Failed to parse configuration: " << reader.getFormattedErrorMessages().c_str();
throw std::runtime_error(sstream.str());
}
// ----------------- DEPRECATED END -----------------
_qconfig = QJsonFactory::readJson(configFile);
if (!schemaChecker.validate(_qconfig))
{

View File

@ -40,6 +40,15 @@
#include <utils/Logger.h>
// ----------------- DEPRECATED BEGIN -----------------
// NOTE: Remove this code block when the conversion have been completed from JsonCpp to QTJson
#include <json/json.h>
#include <istream>
#include <fstream>
// ----------------- DEPRECATED END -----------------
#include <kodivideochecker/KODIVideoChecker.h>
#include <jsonserver/JsonServer.h>
#include <protoserver/ProtoServer.h>